Combine Cells into a String, so they are searchable with input box - excel

I am attempting to create an Excel sheet based on an already existing workbook. I can't change the format of the workbook, so I am stuck with what follows.
We are creating a system to use a hand scanner with barcodes containing staff names, for the purposes of tracking COVID testing.
Our workbook has one column for first name, one for last.
So B2 = Cluff, C2 = Aaron
How do I use an input box (for the scanner) that searches the string "Cluff, Aaron" (user input in the box, not the name specifically in the code) and returns the row with the data above?
Bonus points if it opens a new input box to enter the test UPC (another input looking for a string), and inputs into Column AA on the same row.
My knowledge of VBA is very limited.
I tried various edits to the following code:
Sub DualFind()
Dim vFind1 As String, vFind2 As String
Dim rFound As Range, lLoop As Long
Dim bFound As Boolean
Dim rLookIn1 As Range, rLookIn2 As Range
vFind1 = InputBox("Find What: First value?", "FIND FIRST VALUE")
If vFind1 = vbNullString Then Exit Sub
vFind2 = InputBox("Find What: Second value?", "FIND SECOND VALUE")
If vFind2 = vbNullString Then Exit Sub
If Selection.Areas.Count > 1 Then
Set rLookIn1 = Selection.Areas(1).Columns(1)
Set rLookIn2 = Selection.Areas(2).Columns(1)
Else
Set rLookIn1 = Selection.Columns(1)
Set rLookIn2 = Selection.Columns(2)
End If
Set rFound = rLookIn1.Cells(1, 1)
For lLoop = 1 To WorksheetFunction.CountIf(rLookIn1, vFind1)
Set rFound = rLookIn1.Find(What:=vFind1, After:=rFound, LookAt:=xlWhole)
If UCase(rLookIn2.Cells(rFound.Row, 1)) = UCase(vFind2) Then
bFound = True
Exit For
End If
Next lLoop
If bFound = True Then
MsgBox "Match found", vbInformation, "ozgrid.com"
Range(rFound, rLookIn2.Cells(rFound.Row, 1)).Select
Else
MsgBox "Sorry, no match found", vbInformation, "ozgrid.com"
End If
End Sub
From what I gather, it needs two separate inputs to search the columns. I need it to search two columns with one input. I imagine you'd have to compile columns B and C into a string, and then search it based on input from the box.

Not entirely sure if this is what you were after but hopefully it will at least give you some more ideas. I've written this so that the user inputs the search name in the format [first name] [last name], e.g. Aaron Cluff. I've assumed from what you've written that the last name is found in column 2 and the first name in column 3.
Sub Demo()
Dim SearchName As String
Dim UPC As String
Dim LastRow As Long
Dim Row As Long
Dim RowMatch As Long
Dim ColFirstName As Integer
Dim ColLastName As Integer
ColLastName = 2
ColFirstName = 3
SearchName = InputBox("Enter search name: e.g. Aaron Cuff", "Search")
If SearchName = "" Then Exit Sub
SearchName = Trim(SearchName)
LastRow = Cells(Rows.Count, ColLastName).End(xlUp).Row
For Row = 1 To LastRow
If StrComp(SearchName, Trim(Cells(Row, ColFirstName)) & " " & Trim(Cells(Row, ColLastName)), vbTextCompare) = 0 Then
RowMatch = Row
Exit For
End If
Next
If RowMatch = 0 Then
MsgBox "Search Name: " & StrConv(SearchName, vbProperCase) & vbNewLine & vbNewLine & _
"No Match Found", vbInformation, "Search Result"
Exit Sub
End If
UPC = InputBox("Enter Test UPC for " & StrConv(SearchName, vbProperCase) & ": ", "Input")
If UPC <> "" Then
Cells(RowMatch, "AA") = UPC
End If
End Sub

Here's one way to do the staff name lookup:
Dim ws As Worksheet
Dim rng As Range, m, staffName
Set ws = Worksheets("Staff")
staffName = "Cluff, Aaron"
m = ws.Evaluate("MATCH(""" & staffName & """,A1:A1000 & "", "" &B1:B1000,0)")
If Not IsError(m) Then
Debug.Print "Matched on row " & m
Else
Debug.Print "No match for " & staffName
End If

Related

Using Input box for all variables in countif vba

I have tried to code a macro where a search is conducted for a specific text.
A)The column to search in,
B)The column where the result should appear and
C) The text for which the search is being conducted
All are referred by respective input boxes.
The input box for columns to be searched and where output is to be placed should only need the column name,(and not range) indicated by letters (text and so string) as value.
For example, if a search in column Y is to be done the input box should only need entry of letter "Y".
I have tried various permutations, but could not replace Y2:Y&LastRow in the code below, so that it refers to the input from input box for the column to search in.
The code is as follows:-
Sub CountIfAllVariablesFromInputBox()
Dim LastRow As Long
Dim ChkColumn As String
'display an input box asking for column
ChkColumn = InputBox( _
"Please enter column to check")
'if no input stop
ColumnNumber = Columns(ChkColumn).Column
If Len(ChkColumn) = 0 Then
MsgBox "No column entered"
Exit Sub
End If
Dim InputColumn As String
'display an input box asking for column
InputColumn = InputBox( _
"Please enter column to insert results")
'if no input stop
If Len(InputColumn) = 0 Then
MsgBox "No column entered"
Exit Sub
End If
'inputbox for text string to search for
Dim SuccessKeyWord As String
SuccessKeyWord = InputBox(Prompt:="Enter KeyWord For Success", _
Title:="KeyWord For Success", Default:="WOW!!")
LastRow = Range(ChkColumn & Rows.Count).End(xlUp).Row
Range(InputColumn & "1").Formula = "=COUNTIF(Range("Y2:Y"&LastRow),""" & SuccessKeyWord & """)"
End With
End Sub
Googling threw up so many ways to refer to ranges (with cells, cell, variables) that I am overwhelmed, unfortunately I could not get result by any of those.
I would be really thankful of your kind help.
I have posted a screenShot.sometimes I may need to search in column "W" and at others in column "Y". I need that flexibility by using the inputbox.
Screen Shot of the columns
Error after replacing the last line of the code by:-
Range(InputColumn & "1").Formula = "=COUNTIF(Range(""" & ChkColumn & 2 & ":" & ChkColumn & """&LastRow),""" & SuccessKeyWord & """)"
or
Range(InputColumn & "1").Formula = "=COUNTIF(Range(""" & ChkColumn & 2 & ":" & ChkColumn &LastRow & """),""" & SuccessKeyWord & """)"
Note:-
Search in column W
Result in column AA
Text to search WOW!!
Assumed you want the user to select the columns
Sub CountIfAllVariablesFromInputBox()
Dim LastRow As Long, Rng As Range
Dim ChkColumn As Range
Dim InputColumn As Range
Dim SuccessKeyWord As String
'display an input box asking for column
Set ChkColumn = Application.InputBox("Please enter column to check", Type:=8)
'if no input stop
If Len(ChkColumn) = 0 Then
MsgBox "No column entered"
Exit Sub
End If
ColumnNumber = ChkColumn.Column
'display an input box asking for column
Set InputColumn = Application.InputBox( _
"Please enter column to insert results", Type:=8)
'if no input stop
If InputColumn Is Nothing Then Exit Sub
'inputbox for text string to search for
SuccessKeyWord = InputBox(Prompt:="Enter KeyWord For Success", _
Title:="KeyWord For Success", Default:="WOW!!")
LastRow = Cells(Rows.Count, ColumnNumber).End(xlUp).Row
Set Rng = Range(Cells(1, ColumnNumber), Cells(LastRow, ColumnNumber))
Cells(1, InputColumn.Column) = "=COUNTIF(" & Rng.Address & ",""" & SuccessKeyWord & """)"
End Sub
Some modification from your line code:
Sub CountIfAllVariablesFromInputBox()
Dim LastRow As Long
Dim ChkColumn As String
'display an input box asking for column
ChkColumn = InputBox( _
"Please enter column to check")
'if no input stop
On Error Resume Next
ColumnNumber = Columns(ChkColumn).Column
If Err.Description <> "" Then
MsgBox "No column entered or Something Error"
Exit Sub
End If
On Error GoTo 0
Dim InputColumn As String
'display an input box asking for column
On Error Resume Next
InputColumn = InputBox( _
"Please enter column to insert results")
'if no input stop
If Err.Description <> "" Then
MsgBox "No column entered or Something Error"
Exit Sub
End If
On Error GoTo 0
'inputbox for text string to search for
Dim SuccessKeyWord As String
SuccessKeyWord = InputBox(Prompt:="Enter KeyWord For Success", _
Title:="KeyWord For Success", Default:="WOW!!")
LastRow = Range(ChkColumn & Rows.Count).End(xlUp).Row
Range(InputColumn & "1").Formula = "=COUNTIF(Range(""" & ChkColumn & 2 & ":" & ChkColumn &LastRow & """),""" & SuccessKeyWord & """)"
'End With
End Sub
Oh, Finally got it working
Sub CountIfAllVariablesFromInputBox()
Dim LastRow As Long
Dim ChkColumn As String
Dim InputColumn As String
Dim SuccessKeyWord As String
Dim rng As Range
'display an input box asking for column
ChkColumn = Application.InputBox("Please enter column to check")
'if no input stop
On Error Resume Next
ColumnNumber = Columns(ChkColumn).Column
If Err.Description <> "" Then
MsgBox "No column entered or Something Error"
Exit Sub
End If
On Error GoTo 0
'display an input box asking for column
On Error Resume Next
InputColumn = Application.InputBox( _
"Please enter column to insert results")
'if no input stop
If Err.Description <> "" Then
MsgBox "No column entered or Something Error"
Exit Sub
End If
On Error GoTo 0
'inputbox for text string to search for
SuccessKeyWord = Application.InputBox(Prompt:="Enter KeyWord For Success", _
title:="KeyWord For Success", Default:="WOW!!")
LastRow = Range(ChkColumn & Rows.Count).End(xlUp).Row
Set rng = Range(ChkColumn & 2 & ":" & ChkColumn & LastRow)
Range(InputColumn & "1").Value = WorksheetFunction.CountIf(rng, SuccessKeyWord)
End Sub
Thanks #JvdV #chrisneilsen #user11982798 #Davesexcel

VBA Filter Multiple Columns At Same Time

Jim L from Ontario was a tremendous help in solving my first challenge. You can review that at this link : Previous Discussion
I thought it would be a simple matter to add filters for additional columns once the DATE FILTER QUESTION was solved. Nope.
I've tried adding additional filters within the same confines as the DATE filter ... I've tried adding the additional filters in the same sub but below the DATE filter ... even placing the additional filters in separate subs. Nothing is working.
The example workbook may be downloaded here : Download Workbook
The end users will have a need to filter on one or more columns at the same time. How can I work that in with the existing code in the workbook ?
I'm stumped !
Thanks.
Try adding the auto-filter across all the columns and then use each button to set the criteria for one column only. Here is an example for the fist 3 columns that you can expand to the others.
COL_FILTER is an integer parameter to the sub filterCol which is generic to all the columns you want to add a filter to (except the date which is a special case). Assign your "UNIT" filter button to the sub FilterB, "Call RCVD" button to sub FilterC etc. When you first press any button the filter drop downs appear across all columns but only 1 column will have criteria applied. Pressing further buttons will set criteria for those additional columns and retain the previous filters. Entering a blank search term will remove the criteria for that column only
Option Explicit
Sub ResetFilters()
Dim Wks As Worksheet
Set Wks = Sheets("Call Log File")
With Wks
On Error Resume Next
If Wks.AutoFilterMode Then
Wks.AutoFilterMode = False
End If
End With
End Sub
Sub FilterB()
Call filterCol(2)
End Sub
Sub FilterC()
Call filterCol(3)
End Sub
Sub filterCol(COL_FILTER As Integer)
Dim wb As Workbook, ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.Sheets("Call Log File")
' set auto filter to all columns if not already on
Dim rngFilter As Range
Set rngFilter = ws.Range("A2:K2")
If ws.AutoFilterMode = False Then
rngFilter.AutoFilter
End If
'Debug.Print rngFilter.Address
' get filter criteria
Dim sColname As String
sColname = ws.Cells(2, COL_FILTER)
Dim sPrompt As String, sUserInput As String, n As Integer
sPrompt = "Enter " & sColname
sUserInput = InputBox$(sPrompt)
Dim criteria(2) As String
criteria(1) = "*" & sUserInput & "*"
' apply filter to the select column
If ws.AutoFilterMode = True Then
rngFilter.AutoFilter COL_FILTER, "=" & criteria(1)
End If
End Sub
Sub FilterDate()
Const COL_FILTER As Integer = 1 ' A
Dim wb As Workbook, ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.Sheets("Call Log File")
' set auto filter to all columns if not already on
Dim rngFilter As Range
Set rngFilter = ws.Range("A2:K2")
If ws.AutoFilterMode = False Then
rngFilter.AutoFilter
End If
'Debug.Print rngFilter.Address
Dim sPrompt As String, sUserInput As String, n As Integer
sPrompt = "Enter DATE" & vbCrLf & _
"For YEAR ONLY: YY" & vbCrLf & _
"For YEAR & MONTH: YYMM" & vbCrLf & _
"For YEAR & MONTH & DAY: YYMMDD"
sUserInput = InputBox$(sPrompt)
n = Len(sUserInput)
If n = 0 Then
rngFilter.AutoFilter COL_FILTER ' clear filter
Exit Sub
ElseIf Not (n = 2 Or n = 4 Or n = 6) Then
MsgBox sUserInput & " is not correct", vbExclamation, "Wrong Format"
Exit Sub
End If
Dim mydate As Variant
mydate = dateRange(sUserInput)
'Debug.Print sUserInput, mydate(1), mydate(2)
If ws.AutoFilterMode = True Then
rngFilter.AutoFilter COL_FILTER, ">=" & mydate(1), 1, "<=" & mydate(2)
End If
End Sub
Function dateRange(s As String)
Dim s1 As String, s2 As String
s1 = "000"
s2 = "999"
Select Case Len(s)
Case 2
s1 = "0101" & s1
s2 = "1231" & s2
Case 4
s1 = "01" & s1
s2 = "31" & s2
Case 6
' nothing to add
Case Else
dateRange = ""
Exit Function
End Select
Dim rng(2) As Long
rng(1) = CLng(s + s1)
rng(2) = CLng(s + s2)
dateRange = rng
End Function
Fo the benefit of others ... this following macro will search for a term in Col B, after the table was filtered by Col A. Although this is not a "filtering approach" in Col B, it is very effective and does precisely what I was looking for.
Thank you to all for your assistance.
Sub FilterB()
Dim cl As Range, rng As Range
Dim sPrompt As String, sUserInput As String
Set rng = Range("B3:B100")
sPrompt = "Enter SEARCH TERM"
sUserInput = InputBox$(sPrompt)
For Each cl In rng.SpecialCells(xlCellTypeVisible)
If cl.Value <> sUserInput Then
cl.Rows.Hidden = True
End If
Next cl
End Sub
And this can be duplicated as many times as required to further "filter down" additional columns.

Find Duplicate Entry

I am using Excel 2010.
I have some VBA code which creates a unique key and then looks for duplicate unique key entries. Any duplicates are coloured in red.
I need to automate this a little further. If there is a duplicate unique key, copy the information from the newest entry, and paste it into the line where the original entry is. I then want the newest entry deleted.
The unique key is a concat of the customer name and the date the file was created. There will only ever be at most one duplicate entry per customer and that will be because the date the file was last updated has changed. I need the duplicate concat entry with the newest date to copy the info over the top of the entry with the oldest date on it then delete the original newest date entry. This is because we have other checks that have been completed further along the sheet that we need to keep intact.
Ideally I would like for the message box to still advise how many duplicate entries were found and for the entry to remain coloured red once the copy/paste/delete has taken place to highlight the entry that has been changed.
Private Sub CommandButton1_Click()
'Start of Concatenate Code
Dim i As Integer
Dim r As Range
On Error Resume Next
' Tells Excel to look in column 3 (Column C) for the last one with data in it
lRow = Cells(Rows.Count, 3).End(xlUp).Row
' Tell Excel to focus on cells 4 to 5000
For i = 4 To lRow
' Tell Excel to paste the contents of cell 4 (column D) followed by |
' then the contents of cell 8 (column H) into cell 2 (column B)
Cells(i, 2).Value = Cells(i, 11) & " | " & Cells(i, 7)
Next i
'End of Concatenate Code
'Start of Check for Duplicates code
Dim j As Integer
Dim myCell As Range
Dim myRange As Integer
myRange = Range("A4:A5000").Count
j = 0
' Select the Range
For Each myCell In Range("B4:B5000")
' Check that the cells in the range are not blank
If WorksheetFunction.CountIf(Range("B4:B5000"), myCell.Value) > 1 Then
' Colour the duplicate entries in red
myCell.EntireRow.Interior.ColorIndex = 3
j = j + 1
End If
Next
MsgBox "There are " & j & " duplicates found." & vbCrLf & vbCrLf & _
"Any duplicates have been highlighted in red.", vbInformation + vbOKOnly, _
"Duplicate Entry Checker"
' End of Check for Duplicates code
End Sub
Screenshot of spreadsheet
Thank you #rickmanalexander, I just tried your code (and changed the name of the sheet) but I get a subscript out of range error with the number 9 in the msgbox title. There must be something i have missed but i am not sure what?
Here is the code I used:
Private Sub CommandButton1_Click()
On Error GoTo CleanFail
Dim wrkSht As Worksheet
Set wrkSht = Sheets("Raw Data")
Dim lRow As Long
lRow = wrkSht.Cells(wrkSht.Rows.Count, 3).End(xlUp).Row
Dim arrySheet As Variant
'get the worksheet data into an array
arrySheet = wrkSht.Range("D1:H" & lRow).Value2
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Dim keyValue As Variant
Dim i As Long
Dim rowNum As Long
Dim dupCount As Long
For i = LBound(arrySheet, 1) To UBound(arrySheet, 1)
'a concatenated key consisting of the:
'row number
'customer's name
keyValue = Join(Array(i, arrySheet(i, 1)), "|")
If Not dict.Exists(keyValue) Then
dict(keyValue) = arrySheet(i, 8) 'save the date for this unique key
Else
'if we make it here, then this is a duplicate customer
'for which we want to check the date
'If the current row's date is greater than the previouly saved date, then
'delete the current row
'determine the row umber for the previously saved entry
'place the most recent date in place of the old date
'color it red
'increase the duplicate counter
If arrySheet(i, 8) > dict(keyValue) Then
wrkSht.Rows(i).EntireRow.Delete
rowNum = CLng(Split(keyValue, "|")(0))
wrkSht.Cells(rowNum, "B").Value = CDate(arrySheet(i, 8))
wrkSht.Rows(rowNum).EntireRow.Interior.ColorIndex = 3
dupCount = dupCount = dupCount + 1
End If
End If
'clear variables
keyValue = vbNullString: rowNum = 0
Next i
MsgBox "There were " & dupCount & " duplicates found." & _
vbCrLf & vbCrLf & _
"Any duplicates have been highlighted in red.", _
vbInformation + vbOKOnly, "Duplicate Entry Checker"
CleanExit:
Exit Sub
CleanFail:
MsgBox Err.Description, vbCritical, Err.Number
Resume CleanExit
End Sub
Edit:
OP was getting Error 9 subscript out of range, because I used arrySheet(i, 8) instead of arrySheet(i, 4). I was thinking that I defined the array from the range starting at column A. Simple mistake with an easy fix.
The Dictionary Object is the perfect candidate for duplicate checks, so that is what I went with. The code below is untested, but should work for your needs.
Option Explicit
Private Sub CommandButton1_Click()
On Error GoTo CleanFail
Dim wrkSht As Worksheet
Set wrkSht = Sheets("Raw Data")
Dim lRow As Long
lRow = wrkSht.Cells(wrkSht.Rows.Count, 3).End(xlUp).Row
Dim arrySheet As Variant
'get the worksheet data into an array
arrySheet = wrkSht.Range("D1:H" & lRow).Value2
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Dim keyValue As Variant
Dim i As Long
Dim rowNum As Long
Dim dupCount As Long
For i = LBound(arrySheet, 1) To UBound(arrySheet, 1)
'a concatenated key consisting of the:
'row number
'customer's name
keyValue = Join(Array(i, arrySheet(i, 1)), "|")
If Not dict.Exists(keyValue) Then
dict(keyValue) = arrySheet(i, 4) 'save the date for this unique key
Else
'if we make it here, then this is a duplicate customer
'for which we want to check the date
'If the current row's date is greater than the previouly saved date, then
'delete the current row
'determine the row umber for the previously saved entry
'place the most recent date in place of the old date
'color it red
'increase the duplicate counter
If arrySheet(i,4) > dict(keyValue) Then
wrkSht.Rows(i).EntireRow.Delete
rowNum = CLng(Split(keyValue, "|")(0))
wrkSht.Cells(rowNum, "B").Value = CDate(arrySheet(i, 4))
wrkSht.Rows(rowNum).EntireRow.Interior.ColorIndex = 3
dupCount = dupCount = dupCount + 1
End If
End If
'clear variables
keyValue = vbNullString: rowNum = 0
Next i
MsgBox "There were " & dupCount & " duplicates found." & _
vbCrLf & vbCrLf & _
"Any duplicates have been highlighted in red.", _
vbInformation + vbOKOnly, "Duplicate Entry Checker"
CleanExit:
Exit Sub
CleanFail:
MsgBox Err.Description, vbCritical, Err.Number
Resume CleanExit
End Sub

Search words in two columns and copy to another sheet

In my problem:
First, I need to find "Unit Name" in Column B.
If it found "Unit Name" it should look for "First Name:" in Column D and copy 5 cell right. ("Obama" in I10)
Paste the name "Obama" to Unit Name sheet. (Paste "Obama" to Sheet "1" A1)
I am new in coding therefore i don't know too much about it. I tried with some codes but it is not efficient.
Here is an image to show my problem.
Sub Test()
Dim i As Integer
Dim m As Integer
Dim n As Integer
Dim z As Integer
For i = 1000 To 1 Step -1
If Range("B" & i).Value = "Unit Name" Then
m = 2
m = i + 1
n = i - 18
If Range("D" & n).Value = "First Name:" Then
m = Range("B" & m).Value + 1
Range("H" & n).Copy
Sheets(m).Range("B7").PasteSpecial xlPasteValues
End If
End If
Next i
End Sub
You don't need all those integer variables, you can use a few Range variables instead:
Sub find_name()
Dim mainWS As Worksheet, altWS As Worksheet
Dim unitCel As Range, fNameCell As Range
Set mainWS = Worksheets("Sheet2") 'CHANGE AS NEEDED
Set altWS = Worksheets("Sheet1")
With mainWS
Set unitCel = .Range("B:B").Find(What:="Unit Name")
If Not unitCel Is Nothing Then
Set fNameCell = .Range("D:D").Find(What:="First Name:").Offset(0, 5)
altWS.Range("A1").Value = fNameCell.Value
End If
End With
End Sub
May need to tweak this, depending on where your data is. I am assuming "Obama" could be any text, that is three columns right of column D, where "First Name:" is found.
Sub Shift_Over5()
Dim i As Long
'Sheet name should be a string
Dim SheetName As String
Dim FirstName As Range
Dim UnitName As Range
'Dim l As Byte --> I changed it to lUnitSheetLastrow, because we need to copy the data from sheet1 to sheet 1,2...
' then you need to check the last row of unit sheet and write data to the last row + 1.
Dim lUnitSheetLastrow As Long
Dim FirstMatch As Variant
Dim Start
Start = VBA.Timer
For i = 1 To 40000 Step 1
'For clear code and easy to follow, you need to mention the sheet you want to interact
'Here i use 'Activesheet', i assume that the current sheet is sheet1
If ActiveSheet.Range("A" & i).Value = "Unit Name" Then
' i think we dont need this code line, because we identified the cell in column B has value is "Unit Name"
'Set UnitName = Range("A:A").Find(what:="Unit Name")
' Here you dont need to use Offset
'SheetName = UnitName.Offset(1, 0).Value
SheetName = ActiveSheet.Range("A" & (i + 1)).Value
' Find "First Name" in 20 rows in column E.
' What happen if i<20, the nextline will show the error, because the minimum row is 1
If i < 40 Then
Set FirstName = ActiveSheet.Range("D1" & ":D" & i).Find(what:="First Name:")
Else
Set FirstName = ActiveSheet.Range("D" & i & ":D" & (i + 40)).Find(what:="First Name")
End If
' make sure the SheetName is not empty and Unit sheet is existing in you workbook then copy the first name to unit sheet
If SheetName <> "" And CheckWorkSheetAvailable(SheetName) Then
' Check the first name is not nothing
If Not FirstName Is Nothing Then
'Check if the cell B7 in unit sheet empty or not
If Worksheets(SheetName).Range("H7").Value = "" Then
'if empty, write to B7
Worksheets(SheetName).Range("H7").Value = FirstName.Offset(1, 0).Value
Else
'else, Find the lastrow in column D of unit sheet
lUnitSheetLastrow = Worksheets(SheetName).Cells(Worksheets(SheetName).Rows.Count, 1).End(xlUp).Row
'Write data to lastrow +1
Worksheets(SheetName).Range("A" & (lUnitSheetLastrow + 1)).Value = FirstName.Offset(, 1).Value
End If
End If
End If
'You forgot to put end if here
End If
Next i
Debug.Print Round(Timer - Start, 3)
End Sub
Function CheckWorkSheetAvailable(SheetName As String) As Boolean
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name = SheetName Then
CheckWorkSheetAvailable = True
Exit For
End If
Next
End Function
thank you everyone I found the answer.

how to iterate over all rows of a excel sheet in VBA

I have this code (This code is in Access VBA which tries to read an excel file and after checking, possibly import it):
Set ExcelApp = CreateObject("Excel.application")
Set Workbook = ExcelApp.Workbooks.Open(FileName)
Set Worksheet = Workbook.Worksheets(1)
now I want to iterate over all rows of the excel worksheet. I want something such as this:
for each row in Worksheet.rows
ProcessARow(row)
next row
where
function ProcessARow(row as ???? )
' process a row
' how Should I define the function
' how can I access each cell in the row
' Is there any way that I can understand how many cell with data exist in the row
end function
My questions:
How to define the for each code that it iterate correctly on all
rows that has data?
How to define ProcessARow properly
How to get the value of each cell in the row.
How to find how many cell with data exist in the row?
Is there any way that I detect what is the data type of each cell?
edit 1
The link solves on problem :
How to define the for each code that it iterate correctly on all rows that has data?
but what about other questions?
For example, how to define ProcessARow correctly?
If you need the values in the Row, you need use the 'Value' Property and after do an cycle to get each value
for each row in Worksheet.rows
Values=row.Value
For each cell in Values
ValueCell=cell
next cell
next row
Unfortunately you questions are very broad however I believe the below sub routine can show you a few ways of achieving what you are after. In regards to what datatype each cell is more involved as it depends what data type you wish to compare it to however I have included some stuff to hopefully help.
sub hopefullyuseful()
dim ws as worksheet
dim rng as Range
dim strlc as string
dim rc as long, i as long
dim lc as long, j as long
dim celltoprocess as range
set ws = activeworkbook.sheets(activesheet.name)
strlc = ws.cells.specialcells(xlcelltypeLastCell).address
set rng = ws.range("A1:" & lc)
rc = rng.rows.count()
debug.print "Number of rows: " & rc
lc = rng.columns.count()
debug.print "Number of columns: " & lc
'
'method 1 looping through the cells'
for i = 1 to rc
for j = 1 to lc
set celltoprocess = ws.cells(i,j)
'this gives you a cell object at the coordinates of (i,j)'
'[PROCESS HERE]'
debug.print celltoprocess.address & " is celltype: " & CellType(celltoprocess)
'here you can do any processing you would like on the individual cell if needed however this is not the best method'
set celltoprocess = nothing
next j
next i
'method 2 looping through the cells using a for each loop'
for each celltoprocess in rng.cells
debug.print celltoprocess.address & " is " & CellType(celltoprocess)
next celltoprocess
'if you just need the data in the cells and not the actual cell objects'
arrOfCellData = rng.value
'to access the data'
for i = lbound(arrOfCellData,1) to ubound(arrOfCellData,1)
'i = row'
for j = lbound(arrOfCellData,2) to ubound(arrOfCellData,2)
'j = columns'
debug.print "TYPE: " & typename(arrOfCellData(i,j)) & " character count:" & len(arrOfCellData(i,j))
next j
next i
set rng=nothing
set celltoprocess = nothing
set ws = nothing
end sub
Function CellType(byref Rng as range) as string
Select Case True
Case IsEmpty(Rng)
CellType = "Blank"
Case WorksheetFunction.IsText(Rng)
CellType = "Text"
Case WorksheetFunction.IsLogical(Rng)
CellType = "Logical"
Case WorksheetFunction.IsErr(Rng)
CellType = "Error"
Case IsDate(Rng)
CellType = "Date"
Case InStr(1, Rng.Text, ":") <> 0
CellType = "Time"
Case IsNumeric(Rng)
CellType = "Value"
End Select
end function
sub processRow(byref rngRow as range)
dim c as range
'it is unclear what you want to do with the row however... if you want
'to do something to cells in the row this is how you access them
'individually
for each c in rngRow.cells
debug.print "Cell " & c.address & " is in Column " & c.column & " and Row " & c.row & " has the value of " & c.value
next c
set c = nothing
set rngRow = nothing
exit sub
if you want your other questions answered you will have to be more specific as to what you are trying to accomplish
While I like the solution offered by #krazynhazy I believe that the following solution might be slightly shorter and closer to what you asked for. Still, I'd use the CellType function offered by Krazynhazy rather than all the Iif I currently have in the below code.
Option Explicit
Sub AllNonEmptyCells()
Dim rngRow As Range
Dim rngCell As Range
Dim wksItem As Worksheet
Set wksItem = ThisWorkbook.Worksheets(1)
On Error GoTo EmptySheet
For Each rngRow In wksItem.Cells.SpecialCells(xlCellTypeConstants).EntireRow.Rows
Call ProcessARow(wksItem, rngRow.Row)
Next rngRow
Exit Sub
EmptySheet:
MsgBox "Sheet is empty." & Chr(10) & "Aborting!"
Exit Sub
End Sub
Sub ProcessARow(wksItem As Worksheet, lngRow As Long)
Dim rngCell As Range
Debug.Print "Cells to process in row " & lngRow & ": " & wksItem.Range(wksItem.Cells(lngRow, 1), wksItem.Cells(lngRow, wksItem.Columns.Count)).SpecialCells(xlCellTypeConstants).Count
For Each rngCell In wksItem.Range(wksItem.Cells(lngRow, 1), wksItem.Cells(lngRow, wksItem.Columns.Count)).SpecialCells(xlCellTypeConstants)
Debug.Print "Row: " & lngRow, _
"Column: " & rngCell.Column, _
"Value: " & rngCell.Value2, _
IIf(Left(rngCell.Formula, 1) = "=", "Formula", IIf(IsDate(rngCell.Value), "Date", IIf(IsNumeric(rngCell.Value2), "Number", "Text")))
Next rngCell
End Sub
Note, that you have to call the sub to call a row must also include the sheet on which a row should be processed.

Resources