I am at an impasse figuring out how to catch this null range variable exception.
I am attempting to scan for a row of headers to recover data from a few rows under, the excel datasheets may have multiple "pages" with a new header and date on the next "page" if there happens to be data to fill it and this can extend to many pages.
My loop appears to break on the second pass after the find function is unable to find additional rows with the desired header. My if statement is not able to detect that the variable is blank and I get an object not set error repeatedly.
I have tried several ways at calling null exceptions such as is empty, is null, both in a few different syntax forms, but still no success.
Thanks in advance for your help!
Sub testingBreak()
Dim testing As String
Dim starting As String
testing = "testing"
starting = "starting"
Dim productNameRange() As Range
Dim PN2CellAddress As String
Dim rowCount As Integer
rowCount = 0
Dim oldCount As Integer
oldCount = 0
ReDim productNameRange(rowCount)
Dim r As Integer
Set productNameRange(rowCount) = Sheets(starting).Cells.Find( _
What:="Product Name", LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True)
If productNameRange(rowCount) Is Nothing Then
MsgBox ("Search Error: Header Not found")
Else
Do While Not IsEmpty(productNameRange(rowCount)) 'this is to search for additional rows with the same header name
oldCount = rowCount
rowCount = rowCount + 1
MsgBox rowCount & " & " & oldCount
ReDim Preserve productNameRange(rowCount)
If IsNull(productNameRange(oldCount)) Then '<<<<this if statement does not catch that the variable was not set :( <<<<<
MsgBox "null exception worked"
Else
MsgBox productNameRange(oldCount) '<<<<on second loop, I get the error "object varriable or with block varriable not set"... <<<<<<
End If
Set productNameRange(rowCount) = Sheets(starting).Range(productNameRange(oldCount).Address).FindNext( _
productNameRange(oldCount)) ' <<< does not set the next range if there is none
Loop
MsgBox rowCount & "Row(s) have been found!"
For r = 0 To rowCount - 1
MsgBox productNameRange(r)
Next r
End If
End Sub
So this seemed to fix my issue. Thank you to everyone for your help
Dim f As Variant
Private Function FindAllHeaderRows(val As String, filePath As String) As Collection
Dim rv As New Collection, g As Range
Dim addr As String
Dim wb As Workbook: Set wb = Workbooks.Open(filePath) ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1")
Set g = ws.Cells.Find(What:=val, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True)
If Not g Is Nothing Then addr = g.Address
Do Until g Is Nothing
rv.Add g
Set g = ws.Cells.FindNext(After:=g)
If Not g Is Nothing Then
If g.Address = addr Then Exit Do
End If
Loop
Set FindAllHeaderRows = rv
End Function 'working!
Sub testSub1()
Dim FileToOpen As String
FileToOpen = Application.GetOpenFilename(Title:="Select Data file")
Set rangeCo = FindAllHeaderRows("Product Name", FileToOpen)
For Each f In rangeCo
MsgBox f.Address 'shows address
Next f
MsgBox rangeCo.count ' shows how many
End Sub
Find Criteria Cells (Find & FindNext)
Sub FindCriteriaCells()
Const wsName As String = "Starting"
Const Criteria As String = "Product Name"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
Dim rg As Range: Set rg = ws.UsedRange
Dim fCell As Range: Set fCell = rg.Find(What:=Criteria, _
After:=rg.Cells(rg.Rows.Count, rg.Columns.Count), LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=True)
Dim Headers() As Range
Dim n As Long
If Not fCell Is Nothing Then
Dim FirstAddress As String: FirstAddress = fCell.Address
Do
ReDim Preserve Headers(0 To n)
Set Headers(n) = fCell
n = n + 1
Set fCell = rg.FindNext(After:=fCell)
Loop Until fCell.Address = FirstAddress
End If
Dim Msg As String
If n > 0 Then
Msg = "The header '" & Criteria & "' was found in " _
& n & " cell(s):" & vbLf
For n = 0 To n - 1
Msg = Msg & vbLf & Headers(n).Address(0, 0)
Next n
MsgBox Msg, vbInformation
Else
Msg = "The header '" & Criteria & "' was not found."
MsgBox Msg, vbExclamation
End If
End Sub
Related
Every day I receive several.xls containing information about a particular item, for example, a car.
I developed this macro in which I don't need to open all the files because the macro imports all the data I need.
For Each File In Folder.Files
DoEvents
Set xlBook = xlApp.Workbooks.Open(File, False)
Set xlSheet = xlBook.Sheets(1)
On Error Resume Next
Do
ws.Cells(i, 1) = FindCarModel(xlSheet) 'MODEL:
Loop While xlSheet.Cells(j, rngQTE.Column) <> ""
ThisWorkbook.Worksheets("T_G").Cells(n, 1) = FindCarModel(xlSheet)
n = n + 1
xlBook.Close False
Set xlBook = Nothing
Next
End Sub
Private Function FindCarModel(ws As Worksheet) As String
Dim EncontraString As String
Dim Intervalo As Range
Dim i As Integer
EncontraString = "MODEL:"
With ws.Range("A:IV")
Set Intervalo = .Find(What:=EncontraString, _
After:=.Cells(1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If Not Intervalo Is Nothing Then
i = Intervalo.Column + 1
Do While ws.Cells(Intervalo.Row, i) = ""
i = i + 1
Loop
FindCarModel = ws.Cells(Intervalo.Row, i)
End If
End With
End Function
The macro searches for the word "model" and pastes the value of the first cell to the right.
I am no longer receiving files with a single "car model".
How can I return all the car models inside the xls and not just the first one found.
Use FindNext
Option Explicit
Sub FindAll()
Dim fso As Object, ts As Object, folder, file
Dim wb As Workbook, ws As Worksheet, result As Collection
Dim xlBook As Workbook, xlSheet As Worksheet
Dim r As Long, n As Integer
Set wb = ThisWorkbook
Set ws = wb.Sheets("T_G")
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.getfolder("path-to-files")
r = 1
For Each file In folder.Files
Set xlBook = Workbooks.Open(file, False, True) ' read only
Set xlSheet = xlBook.Sheets(1)
Set result = FindCarModel(xlSheet) 'MODEL:
xlBook.Close False
Set xlBook = Nothing
For n = 1 To result.Count
r = r + 1
ws.Cells(r, 1) = result.Item(n)
Next
Next
MsgBox r & " Items found"
End Sub
Private Function FindCarModel(ws As Worksheet) As Collection
Const EncontraString = "MODEL:"
Dim Intervalo As Range, i As Integer, sFirstFind As String
Dim result As New Collection
With ws.Range("A:IV")
Set Intervalo = .Find(What:=EncontraString, _
After:=.Cells(1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If Not Intervalo Is Nothing Then
sFirstFind = Intervalo.Address
Do
i = Intervalo.Column + 1
Do While ws.Cells(Intervalo.Row, i) = ""
i = i + 1
Loop
result.Add ws.Cells(Intervalo.Row, i).Value2
Set Intervalo = .FindNext(Intervalo)
Loop While Intervalo.Address <> sFirstFind
End If
End With
Set FindCarModel = result
End Function
I need to create an Excel VBA Macro that is able to Loop through some Files and if it finds the given String it should fill the Excel Worksheet where I need to.
Currently it looks like this: I show a UserForm that has a TextBox where the String gets entered and a Button.
If the User clicks on that Button then the files should get looped through and if it finds the string in one of that files it should enter something new to the excel where the macro is called from.
I have searched on SO but with no Luck, I found this:
Sub LoopThroughFiles()
Dim StrFile As String
StrFile = Dir("C:\Users\xxx\xxx\xxx\test\*test*")
Do While Len(StrFile) > 0
Debug.Print StrFile
StrFile = Dir
Loop
End Sub
But this looks like it loops and looks if the filename has test in it and not if the actual file has a Value that is called "test".
Also the string that needs to be found is always in the first column of the files. And I would have to read the second column in that activeCell that I would get if the String is found and add that to the Excel where I call this Macro from.
Sincerly Faded ~
Edit:
Sub ReadDataFromAnotherWorkBook()
' Open Workbook A with specific location
Dim src As Workbook
Set src = Workbooks.Open("C:\Users\xxx\Desktop\xxx\test\x1x.xlsx", True, True)
Dim valueBookA As String
Dim valueBookB As Integer
valueBookA = src.Worksheets("Tabelle1").Cells(2, 1) ' Works but here I need to put the enteredValue and search for it
Cells(1, 1).Value = valueBookA
' Close Workbooks A
src.Close False
Set src = Nothing
' Dialog Answer
MsgBox valueBookA
End Sub
This gives me a Value from the read Excel which is good as a first start. I need to loop that to open up more files and also I need the part where I can search for the given String and get the value in that row.
Edit2:
This is what I have now but I cant get the value.. what am I doing wrong :/
Sub ReadDataFromAnotherWorkBook()
Dim SearchString As String
Dim SearchRange As Range, cl As Range
Dim FirstFound As String
Dim sh As Worksheet
' Open Workbook A with specific location
Dim src As Workbook
Set src = Workbooks.Open("C:\Users\x\Desktop\xxx\test\xxx.xlsx", True, True)
' Set Search value
SearchString = TextBox1.Value ' TEST mit TextBox Value -- works
Application.FindFormat.Clear
' loop through all sheets
For Each sh In src.Worksheets
' Find first instance on sheet
Set cl = sh.Cells.Find(What:=SearchString, _
After:=sh.Cells(1, 1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
If Not cl Is Nothing Then
' if found, remember location
FirstFound = cl.Address
MsgBox FirstFound
' format found cell
Do
' cl.Font.Bold = True
' cl.Interior.ColorIndex = 3
Debug.Print FirstFound
MsgBox FirstFound ' Does not work..
' Debug.Print cl.Value
MsgBox cl.Value ' Also does not work -- I need the VALUE that is in the Excel Row or Column where the string gets found
' find next instance
Set cl = sh.Cells.FindNext(After:=cl)
' repeat until back where we started
Loop Until FirstFound = cl.Address
End If
Next
MsgBox "Value in Excel? : " + FirstFound 'cl.Value > Is empty..
MsgBox "SEARCHSTRING :: " + SearchString ' Gives me the right String
' Close Workbooks A ' Closes the Workbook
src.Close False
Set src = Nothing
End Sub
Use Dir to loop over the files in turn
Sub SearchFiles()
Const FOLDER = "C:\Users\xxx\Desktop\xxx\test\"
Dim wb As Workbook, wbSrc As Workbook
Dim ws As Worksheet, wsSrc As Worksheet
Dim sText As String, sFilename As String
Dim cell As Range, rng As Range
Dim n As Long, i As Long, FirstFound As String
sText = TextBox1.Value
' location of search results
Set wb = ThisWorkbook
Set ws = wb.Sheets(1) ' results of search
ws.Cells.Clear
ws.Range("A1:B1") = Array("Search Test = ", sText)
ws.Range("A2:C2") = Array("Address", "Col A", "Col B")
ws.Range("A2:C2").Font.Bold = True
i = 3
' scan all xlsx files in folder
sFilename = Dir(FOLDER & "*.xlsx")
Do While Len(sFilename) > 0
Set wbSrc = Workbooks.Open(FOLDER & sFilename, True, True)
For Each wsSrc In wbSrc.Sheets
n = n + 1
Set rng = wsSrc.Columns(1)
Set cell = rng.Find(What:=sText, _
After:=rng.Cells(1, 1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
' text found
If Not cell Is Nothing Then
FirstFound = cell.Address
Do ' update sheet
ws.Cells(i, 1) = cell.Address(0, 0, xlA1, True)
ws.Cells(i, 2) = cell
ws.Cells(i, 3) = cell.Offset(0, 1)
i = i + 1
Set cell = rng.FindNext(After:=cell)
' repeat until back where we started
Loop Until FirstFound = cell.Address
End If
Next
wbSrc.Close
sFilename = Dir
Loop
MsgBox n & " sheets scanned", vbInformation
End Sub
How do you go through the specific worksheet and in a specific column for every row that contains word "firewall" - then insert an empty row above? The Row with "firewall" may be followed by rows that contain other values. The last line in the column is always "Grand Total". I supposed can be used as condition to stop the loop.
I found on Stack Overflow this example which is almost exactly what I need, but it does it only once, and I need through the entire column for all matches. The worksheet should be specified.
Sub NewRowInsert()
Dim SearchText As String
Dim GCell As Range
SearchText = "Original"
Set GCell = Worksheets("Sheet2").Cells.Find(SearchText).Offset(1)
GCell.EntireRow.Insert
End Sub
My data example:
firewall abc
policy x
policy y
firewall xyz
policy z
policy xxx
Grand Total
Insert Rows (Find feat. Union)
Option Explicit
Sub NewRowInsert()
Const sText As String = "FirEWaLL"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1")
Dim LastRow As Long: LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim rg As Range: Set rg = ws.Range("A2:A" & LastRow)
Dim sCell As Range: Set sCell = rg.Find(sText, , xlFormulas, xlPart)
Application.ScreenUpdating = False
Dim trg As Range
Dim sCount As Long
If Not sCell Is Nothing Then
Dim FirstAddress As String: FirstAddress = sCell.Address
Do
If trg Is Nothing Then
Set trg = sCell
Else
Set trg = Union(trg, sCell.Offset(, sCount Mod 2))
End If
sCount = sCount + 1
Set sCell = rg.FindNext(sCell)
Loop Until sCell.Address = FirstAddress
trg.EntireRow.Insert
End If
Application.ScreenUpdating = True
Select Case sCount
Case 0
MsgBox "'" & sText & "' not found.", vbExclamation, "Fail?"
Case 1
MsgBox "Found 1 occurrence of '" & sText & "'.", _
vbInformation, "Success"
Case Else
MsgBox "Found " & sCount & " occurrences of '" & sText & "'.", _
vbInformation, "Success"
End Select
End Sub
I need to find a specific word from an Excel file. I want to search row by row, and if the word is found, skip 2 rows down and copy the next 20 rows and loop to the next word.
Sub Example4()
Dim FilePath As Workbook
Dim wsheet As Worksheet
Dim i, lcount, lcount2 As Integer
Dim cell, rgFound As Range
Dim Found As Range, LastRow As Long
Set FilePath = Workbooks.Open("D:\SLC.txt")
Dim rowVal As Integer
rowVal = 1
For lcount = 1 To FilePath.Sheets("SLC").Range("A1048576").End(xlUp).Row
Set rgFound = Range("A1:A1048576").Find("TXN. NO TXN SEQ", ThisWorkbook.Sheets(), Cells(rowVal, 1))
FilePath.Cells(wsheet.Range(rowVal).End(xlDown).Row + 3).xlCopy
wbook2.Worksheets(1).Range("A1").PasteSpecial xlPasteValuesAndNumberFormats
wbook2.SaveAs ("D:\SLC_Copied.xlsx")
wbook2.Close
rowVal = rgFound1.Row
Debug.Print lcount
Next lcount
End Sub
As Siddharth Rout suggested, use Find and FindNext.
Try to choose variable names appropriate to their type, calling a workbook object FilePath is confusing to others trying to understand your script.
Option Explicit
Sub Example4()
Const TEXT = "TXN. NO TXN SEQ"
Const TEXT_FILENAME = "D:\SLC.txt"
Const OUT_FILENAME = "D:\SLC_Copied.xlsx"
Dim wbText As Workbook, wbOut As Workbook, rngOut As Range
Dim wsText As Worksheet, wsOut As Worksheet, count As Integer
Dim rngSearch As Range, rngFound As Range, rowFirstFind As Long
' open text file no link update, read only
Set wbText = Workbooks.Open(TEXT_FILENAME, False, True)
Set wsText = wbText.Sheets(1)
' search
Set rngSearch = wsText.Columns("A:A")
Set rngFound = rngSearch.Find(what:=TEXT, LookIn:=xlValues, LookAt:=xlPart)
If rngFound Is Nothing Then
wbText.Close
MsgBox "No lines match [" & TEXT & "]", vbCritical, "Exiting Sub"
Exit Sub
Else
' create new workbook for results
Set wbOut = Workbooks.Add
Set wsOut = wbOut.Sheets(1)
Set rngOut = wsOut.Range("A1")
rowFirstFind = rngFound.Row
Do
'Debug.Print rngFound.Row
rngFound.Offset(3, 0).Resize(20, 1).Copy rngOut
Set rngOut = rngOut.Offset(20, 0)
Set rngFound = rngSearch.FindNext(rngFound)
count = count + 1
Loop Until rngFound.Row = rowFirstFind
End If
wbText.Close False
wbOut.SaveAs OUT_FILENAME
MsgBox count & " blocks copied to " & wbOut.Name, vbInformation, "Finished"
wbOut.Close
End Sub
I am trying to make a macro to insert a new column after the last occupied column in a sheet, then search for the column title "Part Number" in my example and Ctrl+F search for each string listed in the column, and search for it in another workbook. If the string is found in that workbook, I want "Found in 'Workbook Name'" to be filled in the same row as the part number it just searched for but the column that was created at the beginning. This is a part of a larger function so I am passing all the variables in including what's being searched for 'colTitle1', the book and sheet the values are on, 'BOM', the sheet "BOMSheet", and the document being searched 'SearchDoc".
The main function is here:
Public Sub OCCLCheck(colTitle As String, BOM As Workbook, BOMSheet As Worksheet)
Dim OCCL As Variant
Dim OpenBook As Workbook
Dim pn As Variant
Dim lastRow As Integer
'Counts number of rows in Column A with content
lastRow = WorksheetFunction.CountA(Range("A:A"))
'Flashy but not good for regular use - uncomment when not showing off product
'Application.ScreenUpdating = False
'Code for user to indicate the OCCL doc with a file path box - add something to prompt again if cancelled
OCCL = Application.GetOpenFilename(Title:="Choose OCCL File", FileFilter:="Excel Files (*.xls*),*xls*")
If OCCL <> False Then
Set OpenBook = Application.Workbooks.Open(OCCL)
'OpenBook.Sheets(1).Range("A1:E20").Copy
End If
'Application.ScreenUpdating = True
Call SearchFunc("Part Number", BOM, BOMSheet, OCCL)
End Sub
The search function is here:
Public Sub SearchFunc(colTitle1 As String, BOM As Workbook, BOMSheet As Worksheet, SearchDoc As Workbook)
Dim pn As String
Dim colTitle2 As String
Dim c As Variant
Dim lastRow As Integer
'Code to search for something on something else, made for searching across books
'Find the column with colTitle1
With ActiveSheet.UsedRange
Set c = .find(colTitle1, LookIn:=xlValues)
If Not c Is Nothing Then
pn = ActiveSheet.Range(c.Address).Offset(1, 0).Select
End If
End With
'Count number of rows to iterate search through
lastRow = WorksheetFunction.CountA(Range("A:A"))
For i = 1 To lastRow
If Cells.find(What:=Workbooks(BOM).Worksheets(BOMSheet).Range(i, 2).Value, After:=ActiveCell, _
LookIn:=Workbooks(SearchDoc).Worksheets(1).xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate <> .Range(i, 2).Value Then 'Write not on occl to first unoccupied column also add code to find unoccupied column before this loop
End If
End Sub
I am pretty lost at where to go now as I know what I want to do but I am new to VBA so getting the program to do it is my problem ATM, any suggestions are appreciated!
This is the error with the macro searching for const "Part Number"
[3
Most of the essential parts needed to build your solution should be within this script. I used xlWhole in the Find so that ABC1 would not match ABC10 but if part numbers are fixed length maybe xlPart is OK. Refactor into smaller subs and functions as necessary.
Option Explicit
Sub macro()
Const COL_TITLE = "Part Number"
Dim wb As Workbook, ws As Worksheet, found As Range
Dim wbSearch As Workbook, wsSearch As Worksheet
Dim rng As Range, iResultCol As Integer, iPartCol As Integer
Set wb = ThisWorkbook
Set ws = wb.Sheets("BOM D6480000005")
' headers
Set rng = ws.UsedRange.Rows(1)
' determine part number col
Set found = rng.Find(COL_TITLE, , xlValues, xlPart)
If found Is Nothing Then
MsgBox "Can't find " & COL_TITLE, vbCritical, "Search failed"
Exit Sub
End If
iPartCol = found.Column
' determine last col
iResultCol = rng.Columns.count + rng.Column
ws.Cells(1, iResultCol) = "Search Result"
Debug.Print rng.Address, iPartCol, iResultCol
Dim sFilename As String
sFilename = Application.GetOpenFilename(Title:="Choose OCCL File", FileFilter:="Excel Files (*.xls*),*xls*")
If Len(sFilename) > 0 Then
Set wbSearch = Application.Workbooks.Open(sFilename)
Else
MsgBox "No file chosen", vbExclamation
Exit Sub
End If
' find last row
Dim iLastRow As Long, iRow As Long, sPartNo As String, count As Long
iLastRow = ws.Cells(Rows.count, iPartCol).End(xlUp).Row
Debug.Print "iLastRow", iLastRow
' search each sheet
For Each wsSearch In wbSearch.Sheets
For iRow = 2 To iLastRow
sPartNo = ws.Cells(iRow, iPartCol)
If Len(sPartNo) > 0 Then
Set found = wsSearch.UsedRange.Find(sPartNo, , xlValues, xlWhole)
If found Is Nothing Then
' not found
Else
ws.Cells(iRow, iResultCol) = "Found in " & wbSearch.Name & _
" " & wsSearch.Name & _
" at " & found.Address
count = count + 1
End If
End If
Next
Next
' end
wbSearch.Close False
MsgBox count & " matches", vbInformation, "Finished"
End Sub