Excel search and copy from more sheet - excel

I have a file.xls with three sheets.
Sheet1, 2 columns, 3000 rows;
ColumnA: location_id
ColumnB: location_label
Sheet2, 2 columns, 5000 rows;
ColumnA: location_id
ColumnB: screen_id
Sheet3, 2 columns, 6000 rows;
ColumnA: screen_id
ColumnB: screen_name
how to group data into a new sheet4 with the following syntax (view image);
ColumnA: Location_label
ColumnB: screen_name
location_id get location_label name in sheet 1, location_id get screen_id value in sheet2, screen_id get screen_name value in sheet3 and in sheet4 result with location_label and screen_name.
#EDIT QUESTION WITH USE VLOOKUP;
I tried to use VLOOKUP but from error after the first id number 19 of sheet2...i have used this '
=VLOOKUP(Sheet2!A2;Sheet1!A2:B2133;2;)
i get
RED
GREEN
YELLOW
#N/D
#N/D

Public Sub pair_value()
'here i tried to deconstruct the code so it is easy to follow
'this type of paring would work much better with access
'you can use this code to start
Dim h1 As Integer 'row count in sheet1
Dim h2 As Integer 'row count in sheet2
Dim h3 As Integer 'row count in sheet3
Dim h4 As Integer 'row count in sheet4
Dim ar1() As Variant
Dim ar2() As Variant
Dim ar3() As Variant
Dim ar4() As Variant
Dim pair1() As Variant
Dim range1 As Range
Dim range2 As Range
Dim range3 As Range
Dim i As Integer
Dim j As Integer
'---------------------------------------------------
'This exercise would be so much easier using ACCESS
'---------------------------------------------------
'number of rows in each sheets
h1 = Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row
h2 = Worksheets(2).Cells(Rows.Count, 1).End(xlUp).Row
h3 = Worksheets(3).Cells(Rows.Count, 1).End(xlUp).Row
h4 = Worksheets(4).Cells(Rows.Count, 1).End(xlUp).Row
'define arrays
ReDim ar1(h1, 2)
ReDim ar2(h2, 2)
ReDim ar3(h3, 2)
ReDim pair1(h2, 2)
'set range
Set range1 = Worksheets(1).Range(Worksheets(1).Cells(2, 1), Worksheets(1).Cells(h1, 2))
Set range2 = Worksheets(2).Range(Worksheets(2).Cells(2, 1), Worksheets(2).Cells(h2, 2))
Set range3 = Worksheets(3).Range(Worksheets(3).Cells(1, 1), Worksheets(3).Cells(h3, 2))
'load range into arrays
ar1 = range1
ar2 = range2
ar3 = range3
'associate location_label to screen_id using location_id as primary key
For i = 1 To UBound(ar2)
For j = 1 To UBound(ar1)
If ar2(i, 1) = ar1(j, 1) Then
'load screen id + label in pair1 in pair1 array
pair1(i, 1) = ar2(i, 2)
pair1(i, 2) = ar1(j, 2)
End If
Next j
Next i
'associate location_label to screen_name using screen_id as primary key
For i = 1 To UBound(ar3)
For j = 1 To UBound(pair1)
If ar3(i, 1) = pair1(j, 1) Then
Debug.Print j
'past results in sheets(4)
h4 = Worksheets(4).Cells(Rows.Count, 1).End(xlUp).Row
Worksheets(4).Cells(h4 + 1, 1).Value = pair1(j, 2)
Worksheets(4).Cells(h4 + 1, 2).Value = ar3(i, 2)
End If
Next j
Next i
End Sub

Well I'm not the best with Excel and I do not fully understand what you want as an end result. But here is my guess what I think is the problem.
I suspect that in sheet 4 you type you code in A2 and use your mouse to drag the formula to the bottom of the column. If this is the case, your formula will not be exactly the same in every cell, because your matrix in the formula will change while you drag your mouse. Therefore the error #N/D
To prevent your matrix from changing while dragging your mouse you should use '$'.
So your formula would be:
=VLOOKUP(Sheet2!A2;Sheet1!$A$2:$B$2133;2;)
Possibly a tip:
I see you have the same columns in more than 1 sheet. You can put all you data in 1 sheet and then use filters to select the data you want. See this article.

Related

Excel VBA Simulating "Not In" SQL functionality

All -
I have a 2 sheet excel.
Sheet 1 is three columns (name, date, value)
Sheet 2 is name.
I want to write a VBA script that displays all of Sheet 1 data that does NOT have any of the name field listed in Sheet 2 anywhere in sheet 1 (name can appear in different columns so ideally it would search all cells in Sheet 1) to appear in sheet 3
See the sample image for a rough idea of what I"m hoping to accomplish. I have searched but have not had luck.
If you have Excel 365 you can use the Dynamic Array formulas
=LET(Names,FILTER(Sheet1!$C:$E,Sheet1!$C:$C<>""),FILTER(Names,ISERROR(MATCH(INDEX(Names,,1),Sheet2!$G:$G,0))))
Example:
Data (Sheet1)
Exclusion List (Sheet2)
Result
Note: this excludes the headers because the header label Name is present in both the Data column and the Exclusion column so be sure to maintain that
Without Excel 365. I'd recommend a UDF
Function FilterList(ByVal Data As Range, ByVal Exclusion As Range) As Variant
Dim Res As Variant
Dim Dat As Variant
Dim Excl As Variant
Dim rw As Long
Dim idx As Long
Dim cl As Long
Dim ExcludeIt As Variant
Dim Cols As Long
Dim TopRow As Long
ReDim Res(1 To Application.Caller.Rows.Count, 1 To Application.Caller.Columns.Count)
If IsEmpty(Data.Cells(1, 1)) Then
TopRow = Data.Cells(1, 1).End(xlDown).Row
Set Data = Data.Resize(Data.Rows.Count - TopRow).Offset(TopRow - 1)
End If
If IsEmpty(Data.Cells(Data.Rows.Count, 1)) Then
Set Data = Data.Resize(Data.Cells(Data.Rows.Count, 1).End(xlUp).Row - Data.Row + 1)
End If
Dat = Data.Value
Excl = Exclusion.Columns(1).Value
Cols = Application.Min(UBound(Dat, 2), UBound(Res, 2))
idx = 0
For rw = 1 To UBound(Dat, 1)
ExcludeIt = Application.Match(Dat(rw, 1), Excl, 0)
If IsError(ExcludeIt) Then
idx = idx + 1
For cl = 1 To Cols
Res(idx, cl) = Dat(rw, cl)
Next
End If
Next
For rw = 1 To UBound(Res, 1)
For cl = IIf(rw <= idx, UBound(Dat, 2) + 1, 1) To UBound(Res, 2)
Res(rw, cl) = vbNullString
Next
Next
FilterList = Res
End Function
Enter it as an Array Formula (complete it with Ctrl+Shift+Enter) in a range large enough to hold the returned data (can be larger), and pass it your input Data range and Exclusion range (both as whole columns)
=FilterList(Sheet1!$C:$E,Sheet2!$G:$G)
Welcome to Stack Overflow!
You did not say where the source table and criteria table begin, or where to place the result of the "anti-filter". I wrote this code on the assumption that they all start at the first cell of the worksheet, A1:
Sub AntiFilter()
Dim aSource As Range, aCriteria As Range, oCell As Range, oTarget As Range, countCells As Long
Set aSource = Worksheets("Sheet1").Range("A1").CurrentRegion
countCells = aSource.Columns.Count
Set aCriteria = Worksheets("Sheet2").Range("A1").CurrentRegion
Set oTarget = Worksheets("Sheet3").Range("A1")
aSource.AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:=aCriteria, Unique:=False
For Each oCell In Application.Intersect(aSource, aSource.Columns(1))
If oCell.RowHeight < 1 Then
oCell.Resize(1, countCells).Copy Destination:=oTarget
Set oTarget = oTarget.Offset(1, 0)
End If
Next oCell
On Error Resume Next
aSource.Worksheet.ShowAllData
On Error GOTO 0
End Sub
Workbook with macro, test data and examples of selection criteria on Sheet2
If the macro does not work as expected, make sure that you have sheets named Sheet1, Sheet2, and Sheet3 in your workbook, and that the source data range and criteria range start with cells A1. If this is not the case, make the necessary changes to the text of the macro:

Excel find top 10 values on each column

Let's say I have a table: the columns correspond to years (such as 1999, 2000, ..., 2020) and the rows are countries.
How can I make Excel display only the top 10 values of each column and set other countries values =0 ?
I assume the first cell ("Country") is the cell A1.
Open your sheet.
Alt + F11
Insert => Module
Paste this code:
Sub leave_top_10_on_every_column()
Dim iLastRow As Long
Dim iLastCol As Long
Dim i As Long
Dim j As Long
Dim dblTop10 As Double
iLastRow = ActiveSheet.Cells(1, 1).End(xlDown).Row
iLastCol = ActiveSheet.Cells(1, 1).End(xlToRight).Column
For i = 2 To iLastCol
dblTop10 = WorksheetFunction.Large(ActiveSheet.Cells(1, i).EntireColumn, 10)
For j = 2 To iLastRow
If ActiveSheet.Cells(j, i) < dblTop10 Then ActiveSheet.Cells(j, i) = 0
Next
Next
End Sub
Put the mouse pointer somewhere in the middle of this code and hit F5 to run the code.

How to "merge/group by" rows in excel and add the values located on a different column in excel

ID Name Valued
1 John 1.23
2 Eve 2.20
1 John 2.30
3 Adam 4.50
3 Eve 2.00
and so on...
And I want the result like this
ID Name Valued
1 John 3.33 "valued were sum from rows 1 & 2 - because they have the same ID"
2 Eve 2.20
3 Adam 6.50 "valued were sum from 4 & 5 - because they have the same ID whatever the data under the column Name"
How can I write this using VBA for Excel?
Take a look at the SUMIF() function in Excel - https://support.office.com/en-us/article/SUMIF-function-169b8c99-c05c-4483-a712-1697a653039b
It does exactly what you need. In your case these are the formulas:
=SUMIF(C:C,1)
=SUMIF(C:C,2)
=SUMIF(C:C,3)
Assumption: Name occurring first for unique id with multiple names should be displayed in the result.
Solution 1: Using VBA
Considering your data is in Column A-C following will display result in Column E-G
Sub Demo()
Dim ws As Worksheet
Dim dataRng As Range
Dim dic1 As Variant, dic2 As Variant, arr As Variant
Dim cnt As Long
Set ws = ThisWorkbook.Sheets("Sheet1") 'change Sheet1 to your data sheet
Set dic1 = CreateObject("Scripting.Dictionary")
Set dic2 = CreateObject("Scripting.Dictionary")
Application.ScreenUpdating = False
With ws
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row 'get last row in Column A
Set dataRng = .Range("A2:C" & lastRow) 'range of data Column A-C
arr = dataRng.Value 'range to array
For i = 1 To UBound(arr) 'loop through each row
dic1(arr(i, 1)) = dic1(arr(i, 1)) + arr(i, 3) 'add values of unique id
If dic2.exists(arr(i, 1)) = False Then
dic2(arr(i, 1)) = arr(i, 2) 'first name for unique id
End If
Next
.Range("E2").Resize(dic1.Count, 1) = Application.WorksheetFunction.Transpose(dic1.keys) 'uniques id in Column E
.Range("G2").Resize(dic1.Count, 1) = Application.WorksheetFunction.Transpose(dic1.items) 'names in Column E
.Range("F2").Resize(dic2.Count, 1) = Application.WorksheetFunction.Transpose(dic2.items) 'sum of values in Column E
End With
Application.ScreenUpdating = True
End Sub
See image for reference.
Solution 2: Using Formula
To get Unique ID, enter following formula in Cell E2
=IFERROR(INDEX($A$2:$A$6,MATCH(0,INDEX(COUNTIF(E$1:$E1,$A$2:$A$6),0,0),0)),"")
In Cell F2 enter following formula to get first occurring corresponding Name for ID
=INDEX($B$2:$B$6,MATCH(E2,$A$2:$A$6,0))
Finally to get Sum of Values, enter below formula in Cell G2
=SUMIF($A$2:$A$6,E2,$C$2:$C$6)
Drag/Copy down all formulas as required and change range as per your data.

Splitting specific information in one excel cell to several others

I need to find a way to split some data on excel: e.g.
If a cell has the following in: LWPO0001653/1654/1742/1876/241
All of the info after the / should be LWPO000... with that number.
Is there anyway of separating them out and adding in the LWPO000in? So they come out as LWPO0001653
LWPO0001654
etc etc
I could do manually yes, but i have thousands to do so would take a long time.
Appreciate your help!
Here is a solution using Excel Formulas.
With your original string in A1, and assuming the first seven characters are the one's that get repeated, then:
B1: =LEFT($A1,FIND("/",$A1)-1)
C1: =IF(LEN($A1)-LEN(SUBSTITUTE($A1,"/",""))< COLUMNS($A:A),"",LEFT($A1,7)&TRIM(MID(SUBSTITUTE(MID($A1,8,99),"/",REPT(" ",99)),(COLUMNS($A:A))*99,99)))
Select C1 and fill right as far as required. Then Fill down from Row 1
EDIT: For a VBA solution, try this code. It assumes the source data is in column A, and puts the results adjacent starting in Column B (easily changed if necessary). It works using arrays within VBA, as doing multiple worksheet read/writes can slow things down. It will handle different numbers of splits in the various cells, although could be shortened if we knew the number of splits was always the same.
Option Explicit
Sub SplitSlash()
Dim vSrc As Variant
Dim rRes As Range, vRes() As Variant
Dim sFirst7 As String
Dim V As Variant
Dim COL As Collection
Dim I As Long, J As Long
Dim lMaxColCount As Long
Set rRes = Range("B1") 'Set to A1 to overwrite
vSrc = Range("a1", Cells(Rows.Count, "A").End(xlUp))
'If only a single cell, vSrc won't be an array, so change it
If Not IsArray(vSrc) Then
ReDim vSrc(1 To 1, 1 To 1)
vSrc(1, 1) = Range("a1")
End If
'use collection since number of columns can vary
Set COL = New Collection
For I = 1 To UBound(vSrc)
sFirst7 = Left(vSrc(I, 1), 7)
V = Split(vSrc(I, 1), "/")
For J = 1 To UBound(V)
V(J) = sFirst7 & V(J)
Next J
lMaxColCount = IIf(lMaxColCount < UBound(V), UBound(V), lMaxColCount)
COL.Add V
Next I
'Results array
ReDim vRes(1 To COL.Count, 1 To lMaxColCount + 1)
For I = 1 To UBound(vRes, 1)
For J = 0 To UBound(COL(I))
vRes(I, J + 1) = COL(I)(J)
Next J
Next I
'Write results to sheet
Set rRes = rRes.Resize(UBound(vRes, 1), UBound(vRes, 2))
With rRes
.EntireColumn.Clear
.Value = vRes
.EntireColumn.AutoFit
End With
End Sub
I'm clearly missing the point :-) but anyway, in B1 and copied down to suit:
=SUBSTITUTE(A1,"/","/"&LEFT(A1,7))
Select ColumnB, Copy and Paste Special, Values over the top.
Apply Text to Columns to ColumnB, Delimited, with / as the delimiter.
There's a couple of ways to solve this. The quickest is probably:
Assuming that the data is in column A:
Highlight the column, go to Data>>Text To Columns
Choose "Delimited" and in the "Other" box, put /
Click ok. You'll have your data split into multiple cells
Insert a column at B and put in the formula =Left(A1, 7)
Insert a column at C and pit in formula =Right(A1, Length(A1)-7)
You'll now have Column B with your first 7 characters, and columns B,C,D,E,F, etc.. with the last little bit. You can concatenate the values back together for each column you have with =Concatenate(B1,C1), =Concatenate(B1,D1), etc..
A quick VBa, which does nearly the same thing that #Kevin's does as well. I wrote it before I saw his answer, and I hate to throw away work ;)
Sub breakUpCell()
Dim rngInput As Range, rngInputCell As Range
Dim intColumn As Integer
Dim arrInput() As String
Dim strStart As String
Dim strEnd As Variant
'Set the range for the list of values (Assuming Sheet1 and A1 is the start)
Set rngInput = Sheet1.Range("A1").Resize(Sheet1.Range("A1").End(xlDown).Row)
'Loop through each cell in the range
For Each rngInputCell In rngInput
'Split up the values after the first 7 characters using "/" as the delimiter
arrInput = Split(Right(rngInputCell.Value, Len(rngInputCell.Value) - 7), "/")
'grab the first 7 characters
strStart = Left(rngInputCell.Value, 7)
'We'll be writing out the values starting in column 2 (B)
intColumn = 2
'Loop through each split up value and assign to strEnd
For Each strEnd In arrInput
'Write the concatenated value out starting at column B in the same row as rngInputCell
Sheet1.Cells(rngInputCell.Row, intColumn).Value = strStart & strEnd
'Head to the next column (C, then D, then E, etc)
intColumn = intColumn + 1
Next strEnd
Next rngInputCell
End Sub
Here is how you can do it with a macro:
This is what is happening:
1) Set range to process
2) Loop through each cell in range and check it isn't blank
3) If the cell contains the slash character then split it and process
4) Skip the first record and concatenate "LWPO000" plus the current string to adjacent cells.
Sub CreateLWPO()
On Error Resume Next
Application.ScreenUpdating = False
Dim theRange
Dim cellValue
Dim offset As Integer
Dim fields
'set the range of cells to be processed here
Set theRange = range("A1:A50")
'loop through each cell and if not blank process
For Each c In theRange
offset = 0 'this will be used to offset each item found 1 cell to the right (change this number to this first column to be populated)
If c.Value <> "" Then
cellValue = c.Value
If InStr(cellValue, "/") > 0 Then
fields = Split(cellValue, "/")
For i = 1 To UBound(fields)
offset = offset + 1
cellValue = "LWPO000" & fields(i)
'if you need to pad the number of zeros based on length do this and comment the line above
'cellValue = "LWPO" & Right$(String(7, "0") & fields(i), 7)
c.offset(0, offset).Value = cellValue
Next i
End If
End If
Next
Application.ScreenUpdating = True
End Sub

Excel multiple string search

I have Sheet2 with data (names of products) alphabetically sorted by column yielding 26 columns plus one column for numeric data. On Sheet1 there is a list of nearly 10,000 names of products which is to be tested whether we have them on Sheet2 or not. To search one name at a time is a matter of craze, so I was thinking if we could bulk search data in Sheet1 and next to each cell the search result will be shown with the address of the cell where that product is found in Sheet2, or not found, such as:
SEARCH STRINGS SEARCH RESULT
Vodafone A4
Mirinda C105
Coca-Cola Y59
HeroHonda not found
Bournvita S27
Maggi not found
I have done some search to find similar code for what is needed above, and found the following code at: http://www.excelforum.com/excel-programming-vba-macros/714965-search.html, which does the search for one string. Can this script be modified to yeild the desired results?
Sub DataSearch()
Dim Data() As Variant
Dim DstWks As Worksheet
Dim Food As String
Dim N As Variant
Dim R As Long
Dim Rng As Range
Dim RngEnd As Range
Dim SrcWks As Worksheet
Set SrcWks = Worksheets("Test 2")
Set DstWks = Worksheets("Test1")
R = 6
Food = DstWks.Range("E3")
N = DstWks.Range("E4")
If DstWks.Range("C6") <> "" Then
DstWks.Range("C6").CurrentRegion.Offset(0, 1).ClearContents
End If
Set Rng = SrcWks.Range("A4:E4")
Set RngEnd = SrcWks.Cells(Rows.Count, Rng.Column).End(xlUp)
Set Rng = IIf(RngEnd.Row < Rng.Row, Rng, SrcWks.Range(Rng, RngEnd))
ReDim Data(1 To Rng.Rows.Count, 1 To Rng.Columns.Count)
Data = Rng.Value
For I = 1 To UBound(Data, 1)
If Data(I, 1) = N And InStr(1, Data(I, 3), Food, vbTextCompare) > 0 Then
DstWks.Cells(R, "C").Resize(1, Rng.Columns.Count) = Rng.Rows(I).Value
R = R + 1
End If
Next I
End Sub
Always appreciating your invaluable assistance.
I would use something quick and dirty such as a hlookup, and see if it returns a value to determine whether or not it is in the 10,000 products.
e.g. Assuming that in sheet 2, your data are in stored such that:
- Each product record is in a column
- Different products are in different columns
- Product name is in row 1, starting with A1
Also assuming that in sheet 1,
- Product names are in column A, starting with A1
- There are no other data in the sheet
In Sheet 1, put the following formula in B2 (and subsequently copy it all the way to B10001):
=IF(ISNA(HLOOKUP(A1,Sheet2!$A$1:$Z$1,1)),"not found",ADDRESS(1,MATCH(A1,Sheet2!$A$1:$Z$1,0),1))

Resources