I am trying to find a cell containing certain value in a different, closed file from where I am running my code. Once I find it, I want to receive the row number of said cell. Somehow my code won't work. It is a mixture of stuff I have found on this site and things I have coded myself. Any help would be great!
Dim file_dir As Workbook
Set file_dir = Workbooks.Open("PATH.xlsx")
Dim j As Integer
Dim n As Integer
Dim temp As Range
n = file_dir.ActiveSheet.Cells(file_dir.ActiveSheet.Cells.Rows.Count, "A").End(xlUp).Row
Set temp = file_dir.ActiveSheet.Range("A1:A" & n).Find(what:="LOOKUP_VALUE")
j = temp.Row
MsgBox j
Welcome to Stack Overflow, I can see you are a beginner so I thought I would show a different way of solving this. You need to learn the data types and what functions return so I think instead of using nested functions etc it is better to start off with a simpler code and then you can make it more sophisticated by making it run faster etc. It seems your value is in column A so instead of using FIND just loop and compare it to your lookup_value. Make sure that you give the lookup_value a real value inside the routine:
Sub Main()
Dim bValueFound As Boolean
Dim j As Integer
Dim n As Integer
Dim temp As Range
Dim WS As Worksheet
Dim file_dir As Workbook
Set file_dir = Workbooks.Open("PATH.xlsx")
Set WS = file_dir.ActiveSheet
n = WS.Cells(WS.Cells.Rows.Count, "A").End(xlUp).Row
Set temp = file_dir.ActiveSheet.Range("A1:A" & n)
For j = 1 To n
If WS.Cells(j, 1).Value = LOOKUP_VALUE Then
bValueFound = True
Exit For
End If
Next j
If bValueFound Then
MsgBox "The row is " & j
Else
MsgBox "Lookup value was not found"
End If
End Sub
Related
I need to update a macro to add some new information to log sheets and a couple other fixes. I want to understand how this codes sorts an array (why are there 3 variable) so I don't break the macro when I update it.
I understand the array components - but i'm not sure how the columns end up sorted into the array order when the loops are finished.
Dim rang As Range
Dim i As Integer
Dim j As Integer
Dim Temp
Dim nams As Variant
Dim F
Dim Dex As Integer
nams = Array("Assay_type", "Revd_date", "Lab#", "Outside#", "Last,First
Name", "MRN", "DOB", "Requestor", "CollDate", "Sample_info",
"Order_Comment", "Signout_comment", "Sample_Comment", "Materials_recvd",
"Order_status", "DIagnosis.1", "Molec_Summary")
Set rang = Range("A1").CurrentRegion
For i = 1 To rang.Columns.Count
For j = i To rang.Columns.Count
For F = 0 To UBound(nams)
If nams(F) = rang(j) Then Dex = F: Exit For
Next F
If F < i Then
Temp = rang.Columns(i).value
rang(i).Resize(rang.Rows.Count) = rang.Columns(j).value
rang(j).Resize(rang.Rows.Count) = Temp
End If
Next j
Next i
I added two new columns to the array and I want to make sure the code will sort them with no problem. I'm just learning to make and update these macros and would like to be careful.
I am trying to check a PO list against an open PO list and clear the cell from
the PO List if not in the open PO List. I tried multiple variations of code (below) and this one is giving me a Mismatch error. Usually, I do something like i = 0 to 5 but that's when I know the exact length of the list. Doing this without knowing the length has been a challenge. Any help would be very much appreciated.
Sub POCheck()
Dim OpenPO As Worksheet
Set OpenPO = Worksheets("OpenPO")
Dim All As Worksheet
Set All = Worksheets("All")
Dim OpenPOList As Variant
OpenPOList = OpenPO.Range("A2:A" And LastRowPO).Value
Set AllPO = All.Range("B2:B" & LastRow)
Dim i As Long
LastRow = All.Range("AH" & Rows.Count).End(xlUp).Row
LastRowPO = OpenPO.Range("A" & Rows.Count).End(xlUp).Row
For Each cell In AllPO.Cells
For i = LBound(OpenPOList) To UBound(OpenPOList)
Found = False
If Not cell.Find(OpenPOList(i)) Is Nothing Then
Found = True
Exit For
End If
Next i
If Not Found Then cell.Value = ""
Next cell
It is very quick to use arrays and Application.Match to see if current value is in the array containing the values to match against. No looping cells and data is read in and written out in one go.
Option Explicit
Public Sub POCheck()
Dim openPO As Worksheet, all As Worksheet, lastRow As Long, lastRowPO As Long
Set openPO = ThisWorkbook.Worksheets("OpenPO")
Set all = ThisWorkbook.Worksheets("All")
With all
lastRow = .Range("AH" & .Rows.Count).End(xlUp).Row
End With
With openPO
lastRowPO = .Range("A" & Rows.Count).End(xlUp).Row
End With
Dim openPOList(), allPOList(), i As Long
openPOList = Application.Transpose(openPO.Range("A2:A" & lastRowPO))
allPOList = Application.Transpose(all.Range("B2:B" & lastRow))
For i = LBound(allPOList) To UBound(allPOList)
If IsError(Application.Match(allPOList(i), openPOList, 0)) Then
allPOList(i) = vbNullString
End If
Next
openPO.Range("A2").Resize(UBound(allPOList), 1) = Application.Transpose(allPOList)
End Sub
It is considered a best practice to add Option Explicit to the top of the code modules and declare a variables with the correct datatypes.
Dim LastRow As Long, LastRowPO As Long
Use & not And when concatenating strings.
OpenPOList = OpenPO.Range("A2:A" And LastRowPO).Value
LastRowPO is being used before its value is set.
LastRowPO = OpenPO.Range("A" & Rows.Count).End(xlUp).row
OpenPOList = OpenPO.Range("A2:A" & LastRowPO).Value
Use Range.Find to search a group of cells not a single cell.
If Not cell.Find(OpenPOList(i)) Is Nothing Then
Using a Scripting.Dictionary to match unique values is vastly faster then using nested loops. Watch: Excel VBA Introduction Part 39 - Dictionaries.
You should download RubberDuck and use its code formatter often.
You can do a vlookup to see if it exists and then clear the value if vlookup in adjacent cell isn't #N/A?
Or loop down the first list and do a countif in VBA to see if it resides within the other list, if it does, clear it?
So may ways to do it in VBA also...
I have found a couple of other questions dealing with variants but none of them seem to address my issue.
I have very simple for loops doing comparisons. The purpose is to color the Excel cell red if there isn't a match. The results are 99% accurate, but I have noticed a couple of seemingly random errors. For example, a cell containing the number 104875 is not colored red, which indicates that there should be a matching cell in the comparison column. But there isn't. It seems like they should all be wrong or all be correct. Some of the other threads about variants have mentioned that the comparisons have to be of the same type or you will get weird errors. In my case, they are of the same type (both integers), so this isn't the problem.
I am brand new to VBA and still trying to understand how it works.
This is the relevant part of the code:
Private Sub CommandButton1_Click()
Dim i As Long, j As Long
Dim flag As Boolean
Dim array1() As Variant, array2() As Variant
Dim column1 As Double
Dim column2 As Double
column1 = convertColumn(TextBox1.Text)
column2 = convertColumn(TextBox2.Text)
Set wb1 = Workbooks("Advocate July 2017 Data.xlsm").Sheets(1)
Set wb2 = Workbooks("BI Report 8-18-17.xlsm").Sheets(1)
array1 = Intersect(wb1.Columns(column1), wb1.UsedRange)
array2 = Intersect(wb2.Columns(column2), wb2.UsedRange)
For i = 2 To UBound(array1)
flag = False
For j = 2 To UBound(array2)
If IsNumeric(array1(i, 1)) And IsNumeric(array2(j, 1)) Then If CDbl(array1(i, 1)) = CDbl(array2(j, 1)) Then flag = True
Next j
If Not flag Then wb1.Cells(i, column1).Interior.Color = vbRed
Next i
End Sub
EDIT: Turns out that my code works fine. The problem was simply that some of the cells on one of the sheets were hidden and I didn't realize it. ~facepalm~ that's what I get for being inexperienced in excell
Try to simplify your code, to something easily reproductible. E.g., lets say that you want to compare the first 50 cells in columns A and B in the activesheet. Put some values and it will look like this:
Option Explicit
Public Sub TestMe()
Dim array1 As Variant
Dim array2 As Variant
Dim i As Long
Dim j As Long
Dim flag As Boolean
With ActiveSheet
array1 = .Range("A1:A50")
array2 = .Range("B1:B50")
.Range("A1:A10").Interior.Color = vbWhite
For i = LBound(array1) To UBound(array1)
flag = False
For j = LBound(array2) To UBound(array2)
If array1(i, 1) = array2(j, 1) Then flag = True
Next j
If Not flag Then .Cells(i, 1).Interior.Color = vbRed
Next i
End With
End Sub
Then try to adapt the solution to yours. It should work.
I've got this idea - in a file I'm setting name and file to search and want the VBA to open that file, iterate through all the sheets, find the value that i search for and return some values at the same row. First at all I only find a method to search only in one column, but in my file the value could be in 5-6 columns. Does anyone has a idea how can I search in hole worksheet? Also I've got simple solution (the data that i searched for will be always in columns D, F, H, J...) and I'll just check the worst case and iterate overall unless find it, return my information, close the file and close the macros. So far this is my code:
Sub BTS()
Dim RowID As Integer
Dim SiteID As String
Dim objFindSiteID As Range
Dim objControllerData As Workbook
Dim WS As Worksheet
Dim lastRow As Long
Dim v As Range
SiteID = ThisWorkbook.Sheets("Sheet1").Range("A3").Value
If ThisWorkbook.Sheets("Sheet1").Range("B3").Value = "someValue" Then
Set objControllerData = Workbooks.Open("C:\Users\bla\bababa\bla.xls", True, True)
End If
For Each WS In objControllerData.Worksheets
lastRow = WS.Cells(WS.Rows.Count, "B").End(xlUp).Row
For I = 1 To lastRow
v = WS.Range("D" & I).Value
If v = SiteID Then
RowID = v.Row
MsgBox lastRow
MsgBox RowID
End If
Next I
Next WS
End Sub
Im almost done with that task, but there is a problem - Run time error 91. I already managed error 424, 1004, but this one is rly hard to find why occurred :/
remove Dim v As Range, you give him a value, not a range.
or, keep the range, and remove .Value at the end of the equal line. then get the value to another primitive, like myValue = v.Value
The code I've written below to replace some index match formulas in a sheet. It seems to work well enough, but I think the loop is a bit clumsy and may be prone to errors. Does anyone have any recommended improvements?
Sub match_SIC_code_sheet_loop()
'sic code needs to match value in column j or a in sic code sheet, '
'if not available = met10 works, but probably needs a bit more
'debugging to make it robust.
Dim ws As Integer
Dim lastrow As Long
Dim lastrow_sic As Long
Dim output_wb As Workbook
Dim SIC_sheet As Worksheet
Dim Demand_CAT As String
Dim sic_DMA As String
Dim i As Integer
Dim row As Integer
Dim WS_count As Long
Dim x As String
Dim y As String
Set output_wb = Workbooks("DMA_customers_SICTEST.xlsx") 'use thisworkbook instead
Set SIC_sheet = Workbooks("DMA_metered_tool_v12_SICTEST.xlsm").Sheets("SIC codes")
With SIC_sheet 'count the number of SIC codes to search through
lastrow_sic = .Range("j" & .Rows.Count).End(xlUp).row
End With
With output_wb 'count the no. of sheets in the generated customer workbook
WS_count = output_wb.Worksheets.Count
End With
With output_wb
For ws = 1 To WS_count 'loop through each sheet in the customer workbook
With output_wb.Sheets(ws)
y = output_wb.Sheets(ws).Name
lastrow = .Range("a" & .Rows.Count).End(xlUp).row ' number of rows in the
'current customer sheet
For i = 2 To lastrow 'data starts in row 2; sic code in column 9
sic_DMA = .Cells(i, 9).Text 'the lookup value
With SIC_sheet
'SIC codes start in row 2, if the sic code matches,
'the correct demand category is appointed, if the sic code does not
'match, then MET_10 is given as the default value.
For row = 2 To lastrow_sic
x = .Cells(row, 3).Text
If x = sic_DMA Then
Demand_CAT = .Cells(row, 10).Text
Exit For
Else
Demand_CAT = "MET_10"
End If
Next row
output_wb.Sheets(ws).Cells(i, 23).Value = Demand_CAT
End With
Next i
End With
Next ws
End With
output_wb.Save
End Sub
Thanks
For starters you could break that long procedure into a few smaller methods. For example you could have a ProcessSheet procedure into which you pass each sheet under :
For ws = 1 To WS_count 'loop through each sheet in the customer workbook
That would definitely help readability etc. If you're still not satisfied then continue breaking the loop into smaller logical procedures. Just don't go too crazy.
Apart from that some error checking and value validation would go a long way in a deeply nested loop. For example ensure that various calculated variables such as 'lastrow' are correct or within a valid threshold etc.
Finally instead of hardcoded values sprinkled through your long loop like magically camoflauged debug-from-hell-where's-waldo fairies; prefer instead a few meaningfully named Const variable alternatives i.e.
Private Const SIC_START_ROW = 2