I'm working on an Excel Spreadsheet that pulls a pick list from the SQL Database and populates the sheet. It then prompts the user to Scan a Part number. I am trying to locate the part number in Column A, and return the row for the part number.
The part number begins as a Variant type, but thinking that type was the problem, I converted it to string by setting its value to another variable.
Finally, I found this snippet of code (I've tried many and none have worked so far), and it works when you specify a number (123456789012) as in the code below. It does not work if you replace that number with the variable sPart nor scanPart.
I need it to work to find the row of the variable sPart (String) or scanPart (Variant). What am I doing wrong?
Function ReturnRowNumber()
Dim ws As Excel.Worksheet
Set ws = ActiveSheet
Dim scanPart As Variant
Dim sPart As String
Dim FoundRow As String
scanPart = InputBox("Scan the first part number", "Part Number") 'Get Part Number
sPart = scanPart
MsgBox sPart
Dim SearchRange As Range
Dim FindRow As Range
Set SearchRange = Range("A1", Range("A65536").End(xlUp))
Set FindRow = SearchRange.Find(123456789012#, LookIn:=xlValues, lookat:=xlWhole)
MsgBox FindRow.Row
End Function
Thanks in advance for any help!
Dana
The code as written in your post will NEVER work, as the syntax is not correct, especially in the .Find statement. Perhaps that issue was throwing you in the
wrong direction, thinking it was a data type issue.
Please see this code. Tested on both string and numerical values.
Option Explicit
Sub Test()
Dim sPart As String
sPart = InputBox("Scan the first part number", "Part Number") 'Get Part Number
MsgBox ReturnRowNumber(sPart)
End Sub
Function ReturnRowNumber(sPart As String) As Long
Dim ws As Worksheet
Set ws = Worksheets("Sheet1") 'be more explicit than 'ActiveSheet
Dim SearchRange As Range
Dim FindRow As Range
Set SearchRange = ws.Range("A1", ws.Range("A65536").End(xlUp))
Set FindRow = SearchRange.Find(sPart, LookIn:=xlValues, lookat:=xlWhole)
If Not FindRow Is Nothing Then ReturnRowNumber = FindRow.Row
End Function
From your code and the description of your problem it sounds like what is happening is you are defining a variable as Variant, but that Varian is really a String (thus, never use Variant unless you have a very specific reason to).
Something like:
Dim Foo as Variant
Dim Bar as Long
Foo = "123"
Bar = "123"
Is basically like saying:
Dim Foo as String
Dim Bar as Long
Foo = "123"
Bar = CLng("123")
The reason why this is important is because:
12345 <> "12345"
They are different values. One is a Long representation, the other is a String representation.
The solution to your problem? It depends on how your initial values are stored. If you are using String representations of your barcodes then you want to declare your barcode as a String, and use that String to search. It seems though that you are actually storing whole numbers, and if that is the case you will want to declare your barcode as a Long.
If, by some curse, you are storing Barcodes as Strings and as whole numbers, well you will either need to choose one or the other, or you will need to use a more robust find method (I recommend dictionaries).
Function ReturnRowNumber()
Dim ws As Excel.Worksheet
Set ws = ActiveSheet
Dim scanPart As Variant
Dim sPart As String
Dim FoundRow As String
Dim xlCell as Range
scanPart = InputBox("Scan the first part number", "Part Number") 'Get Part Number
sPart = scanPart
Dim SearchRange As Range
Dim FindRow As Range
Set SearchRange = Range(Range("A1"), Range("A1").End(xlDown))
Set xlCell = ActiveCell
Application.ScreenUpdating = False
SearchRange.Select
Set FindRow = SearchRange.Find(What:=sPart, After:=ActiveCell, SearchOrder:=xlByRows)
xlCell.Select
Application.ScreenUpdating = True
MsgBox FindRow.Row
End Function
It looks like your find function was not formatted properly. The code above works perfectly for me
Related
I want to find a date in a range, or rather part of a date. For example, I have the month and the year from a user input, stored in two variables userInputMonth and userInputYear, and would now like to find out in which row they appear.
Option Explicit
Sub CheckDate()
Dim wb As Workbook
Dim ws As Worksheet
Dim userInputYear As String
Dim userInputMonth As String
Dim rngDate As Range
Dim foundCell As Range
Set wb = ThisWorkbook
Set ws = wb.Sheets(2)
userInputYear = Right(wb.Sheets(1).Range("A1").Value, 4) 'e.g. "2019"
userInputMonth = Mid(wb.Sheets(1).Range("A1").Value, 2, 2) 'e.g. "09"
Set rngDate = ws.Range("A3:A11")
Set foundCell = rngDate.Find("??." & userInputMonth & "." & userInputYear)
Debug.Print foundCell.Row '-> error
'=====Trying out stuff=====
Set foundCell = rngDate.Find(userInputMonth)
Debug.Print foundCell.Row 'works
Set foundCell = rngDate.Find(userInputMonth & ".")
Debug.Print foundCell.Row '-> error
Set foundCell = rngDate.Find("12.2019")
Debug.Print foundCell.Row '-> error
End Sub
I guess the format is the problem, but how do I deal with this, but I don't know how to apply something like CStr to this issue
edit: The data in rngDate looks like this: 31.12.2019 (formatted as date). A1 is text (e.g. A12 2019).
In my opinion you have to decide which type of data you want to manipulate. Do you prefer working with dates or strings ? After that choice, it will be easier to determine which operations will be necessary and which method or function will be applicable (you cannot do the same thing with dates or strings). Cheers
HI there I am trying to put a VBA code to look for a specific string (text) I have defined in the code located in another workbook find the number of missing values text from the list I defined and produce a report how many values text are missing and if any values wrong do not match the text how many are wrong. this is some of the code I have put but I am struggling to find a code to look for the defined text and produce a report of the number of missing instrument and nr of wrong instrument: Any suggestions will be highly appreciated.
Dim mypath As String
Dim folderpath As String
Dim filename As String
Dim MyBook As Workbook, newbook As Workbook
Set MyBook = ThisWorkbook
Dim file As String, sheetdata As String
Dim ws As Worksheet
Dim x As Workbook
Dim y As Workbook
Dim FindString As String
Dim Rng As Range
Dim findrow As Integer
Dim i As Integer
Dim finalrow As Integer
Dim bottomA As Integer
Dim c As Range
Dim TESTMarketFI2015submitted As Worksheet
Dim FI As Worksheet
Dim a As Range
Dim col As Integer
Dim row As Integer
Dim cell As Integer
Dim inputbox As Variant
Dim application As String
Dim value As String
Dim bond As String
Dim promissoryNote As String
Dim loan As String
Dim certificatesOfDeposit As String
Dim embededOptionBond As String
Dim repo As String
Dim bondOption As String
Dim bondForward As String
Dim securedBond As String
Dim inflationLinkedBond As String
Set x = Workbooks.Open(filename:="Z:\Profiles\My Documents\MAPPING\TEST MAPPING TABLES\TEST_Market_FI_2015 - submitted.csv")
worksheets("TEST_Market_FI_2015 - submitted").Range("A:A").Select
For Each c In Sheets("TEST_Market_FI_2015 - submitted").Range("A:A")
Next
If value = ("bond,promissoryNote,loan,certificatesOfDeposit,embededOptionBond,repo,bondOption,bondForward,securedBond,inflationLinkedBond") Then
c.EntireRow.Copy Worksheets("TEST_Market_FI_2015 - submitted").Range("A:A" & Rows.Count).End(xlUp).Offset(1)
Worksheets("FI").Select
Range("A2").End(xlUp).Offset(i, 0).PasteSpecial
Else
MsgBox "Nothing found under instrument"
End If
End Sub
You need to put your next under the End If. When it checks the value, it does not know what it's actually checking. It should be:
For Each c In Sheets("TEST_Market_FI_2015 - submitted").Range("A:A")
If c.value = ("bond,promissoryNote,loan,certificatesOfDeposit,embededOptionBond,repo,bondOption,bondForward,securedBond,inflationLinkedBond") Then
c.EntireRow.Copy Worksheets("TEST_Market_FI_2015 - submitted").Range("A:A" & Rows.Count).End(xlUp).Offset(1)
Worksheets("FI").Select
Range("A2").End(xlUp).Offset(i, 0).PasteSpecial
Else
MsgBox "Nothing found under instrument"
End If
Next
So now what will happen is, it will loop through each cell, in your selected range and check the value of c (the cell it's presently looking at). If the value of c matches your string then it will do stuff.
However, I doubt the cell value you're looking for is truly a comma delimited string. Are you trying to search for all of those strings individually, meaning that if c.value is ANY of the words in your () then it should do stuff. If so, one option to pursue would be creating a string array, and having the c.value look in the array instead.
I am working in excel. I need to be able to find the first blank/empty cell in row 20 starting from column A. The return should be the actual column namei.e. AB, AAD, etc. What I am going to do is paste a value into this cell. Here is a picture of it with that row highlighted in green.
Dim wkb As Excel.Workbook
Dim wks2 As Excel.Worksheet
Dim strMSG As String
Dim LastRow As Long
Set wkb2 = ThisWorkbook
Set wks2 = wkb2.Sheets("Daily")
columnNumber = wks2.Cells(20, wks2.Columns.Count).End(xlToLeft).Column
Your query of: -
to find the first blank/empty cell in row
Is not answered by your code wks2.Cells(20, wks2.Columns.Count).End(xlToLeft).Column. Its a subtle but significant difference.
.End(xlToLeft) or .End(xlUp) is often used to find the last used cell in a row/column, a common requirement. To find the first used cell you either want to check each one or create a range based on all blank cells in a range, and look at the first item in that range.
The below code did it for me, and included the column reference as a letter.
Public Sub Sample()
Dim wkb2 As Excel.Workbook
Dim wks2 As Excel.Worksheet
Dim strMSG As String
Dim StrColumn As String
Set wkb2 = ThisWorkbook
Set wks2 = wkb2.Worksheets("Daily")
StrColumn = Replace(wks2.Range("20:20").SpecialCells(xlCellTypeBlanks).Cells(1, 1).Address, "$", "")
StrColumn = Left(StrColumn, Len(StrColumn) - 2)
Set wks2 = Nothing
Set wkb2 = Nothing
End Sub
I have a function that converts a column number to its letter, but I will try and convert it to simple code.
dim colLetter as string
Dim vArr
vArr = Split(Cells(1, columnNumber).address(True, False), "$")
colLetter = vArr(0)
I am not sure how well it works standalone. The function that I use is:
Public Function Col_Letter(lngCol As Long) As String
Dim vArr
vArr = Split(Cells(1, lngCol).address(True, False), "$")
Col_Letter = vArr(0)
End Function
And I know that works. Use whichever you like!
I'm trying to get data from an excel sheet to a word document. I try using the 'Find' function however I keep getting the same error "Type mismatch" on this line:
Set FoundRange = .Cells.Find(260707)
Here is the subroutine I am running.
Sub GetID()
Dim oXL As Object
Dim oWB As Object
Dim oSheet As Object
Dim WorkbookToWorkOn As String
Dim FoundRange As Range
Dim dummyvar As String
'Start a new instance of Excel
Set oXL = CreateObject("Excel.Application")
'Line to make Excel Visible or not
oXL.Visible = False
'Open the workbook
'Set the file path to access the 'Certified Personnel' table
WorkbookToWorkOn = "\\DataSource\CertifiedPersonnel.xlsx"
Set oWB = oXL.Workbooks.Open(FileName:=WorkbookToWorkOn, ReadOnly:=True, IgnoreReadOnlyRecommended:=True)
Set oSheet = oXL.ActiveWorkbook.Sheets("tblCertifiedPersonnel")
'End of Excel Automation. Everything from this point on can reference Excel.
With oSheet
dummyvar = .Cells(1, 2).Text
.Cells(1, 2).Select
'Set the range of the cell containing the ID number
'If the ID was found
Set FoundRange = .Cells.Find(260707)
If Not FoundRange Is Nothing Then
'Set the NTlogin equal to the value of column 1, and row corresponding to the FoundRange row
NTlogin = .Cells(FoundRange.Rows, 1).Text
Role = .Cells(FoundRange.Rows, 4).Text
End If
End With
'End Excel reference
oXL.ActiveWorkbook.Close SaveChanges:=False
oXL.Application.Quit
Set oXL = Nothing
Set oWB = Nothing
Set oSheet = Nothing
End Sub
I know it is accessing the correct workbook, because the dummy variable (dummyvar) is returning the value I expect. I have tried several things related to the 'Find' function, however I have not been able to get it to work. Any ideas? Much appreciated.
You are using late binding and have FoundRange declared as a Range. Since this is in a Word document, you're implicitly declaring it as a Word.Range here:
Dim FoundRange As Range
.Find is returning an Excel.Range. Change it to:
Dim FoundRange As Object
With the assumption that the ID values are stored as text in the worksheet, either with a cell type of Text or with an apostrophe/single-quote in front of the number, you may need to format the ID as string. With the further assumption that eventually you may want to pass the ID via parameter to the procedure, give this a try:
Set FoundRange = .Cells.Find(CStr(260707))
That will also allow you to replace the constant number with a variable if desired.
I've been working on an excel sheet where I am using a macro to basically run a 'Find Function' to find a word/phrase on a separate sheet and then delete the entire column that this word/phrase is located in. Currently, thanks to my last post (Is there a way to use the find function with changing, user inputted values in an excel macro?) I have this:
Dim strFind As String
Dim rngFind As Range
Dim i As Integer
strFind = Sheets("Instructions").Range("E56").Value
Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
check if value is found
Do While Not rngFind Is Nothing
If Not rngFind Is Nothing Then
i = 0
Do While rngFind.Offset(0, i + 1) = ""
i = i + 1
Loop
rngFind.Resize(1, i + 1).EntireColumn.Delete Shift:=xlShiftToLeft
Loop
End If
This works perfectly to reference Cell C53 (which is where the word/phrase is inputted by a user) and then go to the 'Forecast' sheet and delete the columns the word/phrase is located in along with the subsequent columns to the right until the next populated column. However, I need it to do 2 more things.
Currently it only finds the word once, even though it may exist in the sheet multiple times, and I need it to delete all of them- basically it "finds next" instead of "find all". I was thinking making a loop so that once it finds one and deletes the column, it finds the same word again and deletes that column (and the subsequent empty rows next to it) until the word is no longer on the sheet at all.
Secondly, I need it to find more than one word/phrase. Right now it references cell 'C53' but I need it to then go on to 'C54' and do the same thing, then 'C55', then 'C56', etc. etc. UNTIL it reaches a cell that simply has a '0' in it. The problem is, the list size in column C is always different (but always starts at C53). The Once it reaches a "0" (not a blank cell), I need it to stop.
Any help with this 'Loop Inception' problem would be greatly appreciated! I am very new to VBA and I was just given the task of doing this. Thanks a lot!
I've been working on an excel sheet where I am using a macro to
basically run a 'Find Function' to find a word/phrase on a separate
sheet and then delete the entire column that this word/phrase is
located in.
If I understand you correctly - it seems to me you are over-complicating your sub:
Sub DeleteColumnsWithString()
Dim strFind As String
Dim rngFind As Range
strFind = Sheets("Instructions").Range("C53").Value
Do
Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
If Not rngFind Is Nothing Then
rngFind.EntireColumn.Delete
End If
Loop Until rngFind Is Nothing
End Sub
If you wanted to do multiple strings you could do it like this:
Sub DeleteColumnsWithAnyOfTheseStrings()
Dim strFind As String
Dim rngFind As Range
Dim SearchTerms As Range
Set SearchTerms = Sheets("Instructions").Range("C53:C55")
For Each Cell In SearchTerms.Cells
strFind = Cell.Value
Do
Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
If Not rngFind Is Nothing Then
rngFind.EntireColumn.Delete
End If
Loop Until rngFind Is Nothing
Next Cell
End Sub
UPDATED PER YOUR COMMENTS:
Sub DeleteColumnsWithTheseStringsAndToTheRightBlanksColumns()
Dim strFind As String
Dim rngFind As Range
Dim strFindAddress As String
Dim SearchTerms As Range
Dim Counter As Long
Set SearchTerms = Sheets("Instructions").Range("C53:C55")
For Each Cell In SearchTerms.Cells
Counter = 0
strFind = Cell.Value
Do
Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
If Not rngFind Is Nothing Then
strFindAddress = rngFind.Address
Do
Range(strFindAddress).EntireColumn.Delete
Counter = Counter + 1
Loop Until Range(strFindAddress).Value <> "" Or Counter >= 100
End If
Loop Until rngFind Is Nothing
Next Cell
End Sub
I think you have a good foundation here.
Any help with this 'Loop Inception' problem would be greatly appreciated!
I think something like this should help with your first point (untested, but this is the idea of using another Do loop, until rngFind Is Nothing):
Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
Do While Not rngFind Is Nothing '## Makes sure the value is found before operating the rest of the loop
i = 0
Do While rngFind.Offset(0, i + 1) = ""
i = i + 1
Loop
rngFind.Resize(1, i + 1).EntireColumn.Delete Shift:=xlShiftToLeft
'## Find the NEXT instanct of strFind within rngFind
Set rngFind = Sheets("Forecast").Cells.FindNext(What:=strFind, LookAt:=xlPart)
Loop
For your second point, store a list of values to search for in an array. You can use the Split function on a comma-delimited string to create an array. Useful for smaller lists. Otherwise you might need to use a different method to create the array.
Updated Per Comments:
Dim valsToSearch() As Variant
Dim val As Variant
Dim numberOfValues as Long
numberOfValues = CInt(Application.InputBox("How Many Search Terms?"))
valsToSearch = Range("C53").Resize(numberOfValues,1)
Then, enclose above in a For/Next loop to iterate over the values in the array:
For each val in valsToSearch
strFind = val
Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
Do While Not rngFind Is Nothing '## Makes sure the value is found before operating the rest of the loop
i = 0
Do While rngFind.Offset(0, i + 1) = ""
i = i + 1
Loop
rngFind.Resize(1, i + 1).EntireColumn.Delete Shift:=xlShiftToLeft
'## Find the NEXT instanct of strFind within rngFind
Set rngFind = Sheets("Forecast").Cells.FindNext(What:=strFind, LookAt:=xlPart)
Loop
Next