I have two sheets sheet1 "kintai_demo" [having 3 columns 'employeid' 'date' 'attendence' ) and sheet2 "kintai_test"(having 1st column 'employeid'[F8:F26] and dates[H6:AL6(2020/dec/21-2021/jan/20)].
I transfer data from kintai_demo to kintai_test by matching employeid and dates so their attendence shows in the sheet2 employid on the left dates on top left to right like [P, A, off, HD, etc.].
Doing it with lookat works till dec 31 and stops at 1st jan and gives error 91.
Private Sub CommandButton1_Click()
'????
Dim myRange As Range
Dim myRange_day As Range
Dim myObj As Range
Dim myObj_day As Range
Dim myObj_emply As Range
Dim keyWord As String
Dim keyWord_day As String
Dim date_range As Range
Dim emplyObj As Range
Dim keyWord_emply As String
Set myRange = Sheets("kintai_test").Range("F8:F26")
Set myRange_day = Sheets("kintai_test").Range("H6:AL6")
Set myObj_emply = Sheets("kintai_test").Range("F8:F26")
'For loop variable
Dim i As Integer
Dim a As Integer
Dim j As Integer
For i = 2 To 14
'??????
'Set myObj = myRange.Find(keyWord, LookAt:=xlWhole)
For a = 8 To 36
For j = 8 To 15
keyWord = Sheets("kintai_demo").Cells(i, 1).Value
keyWord_day = Sheets("kintai_demo").Cells(i, 2).Value
keyWord_emply = Sheets("kintai_demo").Cells(i, 1).Value
'(????)date search
Set myObj_day = myRange_day.Find(What:=keyWord_day, LookIn:=xlFormulas, LookAt:=xlWhole)
'(????)employe id search
Set myObj_emply = myObj_emply.Find(What:=keyWord_emply, LookIn:=xlFormulas, LookAt:=xlWhole)
'this line shows error 91
Sheets("kintai_test").Cells(myObj_emply.Row, myObj_day.Column).Value = Sheets("kintai_demo").Cells(i, 3).Value
i = i + 1
Next j
Next a
Next i
End Sub
I add conditions after each rng.find method. If range not found msgbox will be shown
Private Sub CommandButton1_Click()
'????
Dim myRange As Range
Dim myRange_day As Range
Dim myObj As Range
Dim myObj_day As Range
Dim myObj_emply As Range
Dim myObj_emply_found As Range
Dim keyWord As String
Dim keyWord_day As String
Dim date_range As Range
Dim emplyObj As Range
Dim keyWord_emply As String
Set myRange = Sheets("kintai_test").Range("F8:F26")
Set myRange_day = Sheets("kintai_test").Range("H6:AL6")
Set myObj_emply = Sheets("kintai_test").Range("F8:F26")
'For loop variable
Dim i As Integer
Dim a As Integer
Dim j As Integer
For i = 2 To 14
'??????
'Set myObj = myRange.Find(keyWord, LookAt:=xlWhole)
For a = 8 To 36
For j = 8 To 15
keyWord = Sheets("kintai_demo").Cells(i, 1).Value
keyWord_day = Sheets("kintai_demo").Cells(i, 2).Value
keyWord_emply = Sheets("kintai_demo").Cells(i, 1).Value
'(????)date search
Set myObj_day = myRange_day.Find(What:=keyWord_day, LookIn:=xlFormulas, LookAt:=xlWhole)
If myObj_day Is Nothing Then MsgBox "not found myObj_day ", vbCritical, ""
'(????)employe id search
' you cant use same variable to set range where you lookup and assign to him range found
' i add new variable myObj_emply_found
Set myObj_emply_found = myObj_emply.Find(What:=keyWord_emply, LookIn:=xlFormulas, LookAt:=xlWhole)
If myObj_emply_found Is Nothing Then MsgBox "not found myObj_emply_found ", vbCritical, ""
'this line shows error 91
'AND CONDITION TO DO IF BOTH FOUND
If Not myObj_day Is Nothing And Not myObj_emply_found Is Nothing Then
Sheets("kintai_test").Cells(myObj_emply_found .Row, myObj_day.Column).Value = Sheets("kintai_demo").Cells(i, 3).Value
End If
i = i + 1
Next j
Next a
Next i
End Sub
Related
I currently have the following VBA Code:
Sub SearchProjects()
Dim Ws As Worksheet
Dim NewSheet As Worksheet
Set NewSheet = Worksheets("Sheet1")
Dim Rng As Range, rng2 As Range
Dim myCell As Object
Dim cell2 As Object
Dim proj As String, d As Date
Dim m As Variant
Set Ws = Worksheets("Project tasks")
Ws.Activate
Set Rng = Ws.Range("D:D")
Set rng2 = Range("DatesByWeek").EntireRow 'row 4 of my "Sheet1"
searchString = "Lisa"
For Each Cell In Rng
If InStr(Cell, searchString) > 0 Then
proj = Cells(Cell.Row, Range("ProjectName").Column)
'so here d is a date found that corresponds to Lisa's project name, e.g. d = "25/07/2022"
d = Format(Cells(Cell.Row, Range("StartDate").Column), "dd/mm/yyyy")
m = WorksheetFunction.Match(d, rng2, 1) 'Searches Row 4 for any matches to the date d
msgbox(m)
End If
Next Cell
End Sub
When I do in normal excel function =MATCH("25/07/2022", 4:4, 1) it does return the correct column number, however the vba code continues to get the error:
Unable to get the match property of the WorksheetFunction class.
I'm not sure why it is an error in VBA?
Any help appreciated
Maybe you could try: (Just from the top of my head, have not been able to replicate the error)
Dim res As Variant
res = WorksheetFunction.Match(d, rng2, 1)
If Not IsError(res) Then
Msgbox res
End If
I would like to have up to 6 records which will be based on the answers located in the row beneath.
My code so far looks like this:
Sub Copy_Data_Correctly(ByRef datSource As Worksheet, datTarget As Worksheet)
'QUESTION 1
Const TM_PM As String = "*PM is required*"
Dim que1 As Range
Dim ans1 As Range
Set que1 = Sheets("Sheet1").Range("A1:A100").Find(What:=TM_PM, _
Lookat:=xlPart, LookIn:=xlValues)
If Not que1 Is Nothing Then
'MsgBox ("The question about PM or TM wasn't found")
End If
Set ans1 = que1.Offset(1)
'QUESTION 2
Const LID_LIFTED As String = "*be lifted*"
Dim que2 As Range
Dim ans2 As Range
Set que2 = Sheets("Sheet1").Range("A1:A100").Find(What:=LID_LIFTED, _
Lookat:=xlPart, LookIn:=xlValues)
If Not que2 Is Nothing Then
End If
Set ans2 = que2.Offset(1)
'EXTRACTING THE DATA
Dim lrow1 As Long, lrow2 As Long, lrow3 As Long, lrow4 As Long, lrow5 As Long, lrow6 As Long
lrow1 = datTarget.Range("E" & datTarget.Rows.Count).End(xlUp).Row + 1
lrow2 = datTarget.Range("F" & datTarget.Rows.Count).End(xlUp).Row + 1
que1.Copy
datTarget.Range("E1").PasteSpecial xlPasteValuesAndNumberFormats
ans1.Copy
datTarget.Range("E" & lrow1).PasteSpecial xlPasteValuesAndNumberFormats
que2.Copy
datTarget.Range("F1").PasteSpecial xlPasteValuesAndNumberFormats
ans2.Copy
datTarget.Range("F" & lrow2).PasteSpecial xlPasteValuesAndNumberFormats
End Sub
If I have the second question & answer standalone, then it works. Unfortunately after adding the Q&A1 the error:
Object variable or with variable not set
occurs at the line:
Set ans1 = que1.Offset(1)
why the code behaves like that?
Copy Conditionally
Using the Find method, it will attempt to find each string, containing wild characters, from a list in range A1:A100 of one worksheet (source), then take this matching value (which is different (no wild characters)), and by using Application.Match, it will attempt to find a match in the headers of another worksheet (destination). If a match is found, then the result, the value of the cell below the previously found cell, will be written into the first available row. If no match is found, a new header will be created from the value of the found cell, and the value below the found cell will be written into the first available row.
Option Explicit
Sub CopyData( _
ByVal wsSource As Worksheet, _
ByVal wsDestination As Worksheet)
' Add more: comma separated, no spaces
Const sCriteriaList As String = "*PM is required,*be lifted*"
Const sCriteriaListDelimiter As String = ","
Const sAddress As String = "A1:A100"
Const dfhCellAddress As String = "E1"
Dim sCriteria() As String
sCriteria = Split(sCriteriaList, sCriteriaListDelimiter)
Dim srg As Range: Set srg = wsSource.Range(sAddress)
Dim dfhCell As Range: Set dfhCell = wsDestination.Range(dfhCellAddress)
Dim dfRow As Long: dfRow = dfhCell.Row
Dim dfCol As Long: dfCol = dfhCell.Column
Dim dlhCell As Range: Set dlhCell = _
wsDestination.Cells(dfRow, wsDestination.Columns.Count).End(xlToLeft)
Dim dhrg As Range
If dlhCell.Column < dfCol Then
Set dhrg = dfhCell
Else
Set dhrg = wsDestination.Range(dfhCell, dlhCell)
End If
Dim dlCol As Long: dlCol = dhrg.Columns(dhrg.Columns.Count).Column
Dim dlCell As Range
Set dlCell = _
wsDestination.Cells.Find("*", , xlFormulas, , xlByRows, xlPrevious)
Dim dRow As Long
If Not dlCell Is Nothing Then
If dlCell.Row <= dfhCell.Row Then
dRow = dfhCell.Row + 1
Else
dRow = dlCell.Row + 1
End If
Else
dRow = dfhCell.Row + 1
End If
Dim sCell As Range
Dim sQuestion As String
Dim sAnswer As String
Dim drrg As Range
Dim dhIndex As Variant
Dim n As Long
For n = 0 To UBound(sCriteria)
Set sCell = srg.Find( _
sCriteria(n), srg.Cells(srg.Cells.Count), xlValues, xlWhole)
If Not sCell Is Nothing Then
sQuestion = sCell.Value
sAnswer = CStr(sCell.Offset(1).Value)
dhIndex = Application.Match(sQuestion, dhrg, 0)
If IsNumeric(dhIndex) Then
wsDestination.Cells(dRow, dhIndex + dfCol - 1).Value = sAnswer
Else
Set dhrg = dhrg.Resize(, dhrg.Columns.Count + 1)
dlCol = dlCol + 1
wsDestination.Cells(dfRow, dlCol).Value = sQuestion
wsDestination.Cells(dRow, dlCol).Value = sAnswer
End If
End If
Next n
End Sub
I'm trying to compare column A in sheet2 to column A in sheet1 and when there's a match, copy the row from sheet1 to sheet3 with the same order. And if there is a repetition, it should be included too. I also need it to show the mismatching values empty. I did this macro but I can not allow the duplicates to be included.
Sub compareAndCopy()
Dim lastRowE As Long
Dim lastRowF As Long
Dim lastRowM As Long
Dim foundTrue As Boolean
' stop screen from updating to speed things up
Application.ScreenUpdating = False
lastRowE = Sheets("Sheet2").Cells(Sheets("Sheet2").Rows.Count, "A").End(xlUp).Row
lastRowF = Sheets("Sheet1").Cells(Sheets("Sheet1").Rows.Count, "A").End(xlUp).Row
lastRowM = Sheets("Sheet3").Cells(Sheets("Sheet3").Rows.Count, "B").End(xlUp).Row
For i = 1 To lastRowE
foundTrue = False
For j = 1 To lastRowF
If Sheets("Sheet2").Cells(i, 1).Value = Sheets("Sheet1").Cells(j, 1).Value Then
lastRowM = lastRowM + 1
Sheets("Sheet1").Rows(i).Copy Destination:= _
Sheets("Sheet3").Rows(lastRowM)
foundTrue = True
Exit For
End If
Next j
'If Not foundTrue Then
' MsgBox ("didn't find string: " & Sheets("Sheet2").Cells(i, 2).value)
'End If
Next i
' allow screen updating
Application.ScreenUpdating = True
End Sub
Group Data
Loops through probably unique values in column A of Sheet2.
For each cell value, it uses the Find and FindNext methods to find all the matching cells in column A of Sheet1.
Then it writes each of the cell values to a key, and using Union, combines each matching cell to a range object in the corresponding item.
Then it loops through the dictionary and copies the entire rows of each item (range) to Sheet3.
Finally, it clears the newly added values in column A of Sheet3.
The result in Sheet3 is data from Sheet1 grouped by the values in column A of Sheet2.
Option Explicit
Sub CompareAndCopy()
Const eName As String = "Sheet2"
Const eCol As String = "A"
Const efRow As Long = 1 ' don't you have headers?
Const fName As String = "Sheet1"
Const fCol As String = "A"
Const ffRow As Long = 1 ' don't you have headers?
Const mName As String = "Sheet3"
Const mCol As String = "B" ' "A" is empty!
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ews As Worksheet: Set ews = wb.Worksheets(eName)
Dim elRow As Long: elRow = ews.Cells(ews.Rows.Count, eCol).End(xlUp).Row
If elRow < efRow Then Exit Sub ' no data
Dim erg As Range: Set erg = ews.Cells(efRow, eCol).Resize(elRow - efRow + 1)
'Debug.Print erg.Address
Dim fws As Worksheet: Set fws = wb.Worksheets(fName)
Dim flRow As Long: flRow = fws.Cells(fws.Rows.Count, fCol).End(xlUp).Row
If flRow < ffRow Then Exit Sub ' no data
Dim frg As Range:
Set frg = fws.Cells(ffRow, fCol).Resize(flRow - ffRow + 1)
'Debug.Print frg.Address
Dim mws As Worksheet: Set mws = wb.Worksheets(mName)
Dim mifCell As Range
Set mifCell = mws.Cells(mws.Rows.Count, mCol).End(xlUp).Offset(1) _
.EntireRow.Columns("A") ' entire rows
Dim mfCell As Range: Set mfCell = mifCell
'Debug.Print mfCell.Address
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Application.ScreenUpdating = False
Dim frCount As Long: frCount = frg.Rows.Count
Dim eCell As Range
Dim eValue As Variant
Dim fCell As Range
Dim FirstAddress As String
For Each eCell In erg.Cells
eValue = eCell.Value
Set fCell = frg.Find(eValue, frg.Cells(frCount), xlFormulas, xlWhole)
If Not fCell Is Nothing Then
FirstAddress = fCell.Address
Do
If dict.Exists(eValue) Then
Set dict(eValue) = Union(dict(eValue), fCell)
Else
Set dict(eValue) = fCell
End If
Set fCell = frg.FindNext(fCell)
Loop Until fCell.Address = FirstAddress
End If
Next eCell
If dict.Count = 0 Then Exit Sub ' no data¸
Dim rg As Range
Dim Item As Variant
Dim irCount As Long
For Each Item In dict.Items
irCount = Item.Cells.Count
'Debug.Print Item.Address, irCount
Item.EntireRow.Copy mfCell.EntireRow
Set mfCell = mfCell.Offset(irCount)
Next Item
mifCell.Resize(mfCell.Row - mifCell.Row).ClearContents ' or .Clear
Application.ScreenUpdating = True
MsgBox "Data grouped.", vbInformation
End Sub
I am trying to does the following:
Compare the value (a string of characters) that is stored in column B of worksheet "State = Closed", to all the values in column A of another worksheet called "Match List".
Delete any row in the "State = Closed" that does not have a match to the corresponding "Match List" value.
The code needs to work with any length (as the number of rows will change) list in "Match List", as well as any length "State = Closed" worksheet.
Sub ListRemove()
Application.ScreenUpdating = False
Dim i As Integer
Dim b As Integer
Dim Lastrow As Long
Dim Lastrowb As Long
Dim Del As Variant
Worksheets("Match List").Activate
Set Del = Range("A1:A67") '<--- This needs to be modified to work with any length Match List
Lastrowb = Worksheets("State = Closed").Cells(Rows.Count, "A").End(xlUp).Row
Lastrow = Cells(Rows.Count, "A").End(xlUp).Row
For i = 1 To Lastrow
For b = 1 To Lastrowb
If Worksheets("State = Closed").Cells(i, 2).Value <> Del(b) Then
Worksheets("State = Closed").Rows(i).EntireRow.Delete
End If
Next
Next
Application.ScreenUpdating = True
Worksheets("State = Closed").Activate
End Sub
This deletes every row in the "State = Closed" worksheet instead of just the rows that do not contain a corresponding value in the Match List worksheet.
Find my code below. Two for-loops to check for each value if there is an identical entry in any cell of the second sheet.
Sub List_Remove()
Dim i As Integer
Dim j As Integer
Dim k As Boolean
Dim shA As Worksheet
Dim shB As Worksheet
Set shA = Sheets("Sheet1") 'Worksheet that you want to compare with
Set shB = Sheets("Sheet2") 'Worksheet you want to delete rows from
For i = shB.UsedRange.Rows.Count To 1 Step -1
k = False
For j = 1 To shA.UsedRange.Rows.Count
If shB.Cells(i, 1).Value = shA.Cells(j, 1).Value Then
k = True
End If
Next
If k = False Then
shB.Rows(i).Delete
End If
Next
EndSub
This code is tested. Note use of working directly with objects.
Option Explicit
Sub ListRemove()
Application.ScreenUpdating = False
Dim matchList As Worksheet
Set matchList = Worksheets("Match List")
Dim matchRange As Range
Set matchRange = matchList.Range("A1:A" & matchList.Cells(matchList.Rows.Count, 1).End(xlUp).Row)
Dim closedList As Worksheet
Set closedList = Worksheets("State = Closed")
Dim searchRows As Long
searchRows = closedList.Cells(closedList.Rows.Count, 1).End(xlUp).Row
Dim i As Long
For i = searchRows To 1 Step -1
If IsError(Application.Match(closedList.Cells(i, 1).Value, matchRange, 0)) Then
closedList.Cells(i, 1).EntireRow.Delete
End If
Next
End Sub
Delete Rows (Union)
The Code
Option Explicit
Sub ListRemove()
Application.ScreenUpdating = False
' Constants
Const mlName As String = "Match List"
Const mlFR As Long = 1
Const mlCol As Variant = "A" ' e.g. 1 or "A"
Const scName As String = "State = Closed"
Const scFR As Long = 1
Const scCol As Variant = "B" ' e.g. 1 or "A"
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook
' Match List
Dim ml As Worksheet: Set ml = wb.Worksheets(mlName)
Dim mlLR As Long: mlLR = ml.Cells(ml.Rows.Count, mlCol).End(xlUp).Row
Dim Del As Variant
Del = ml.Range(ml.Cells(mlFR, mlCol), ml.Cells(mlLR, mlCol)).Value
' State = Closed
Dim sc As Worksheet: Set sc = wb.Worksheets(scName)
Dim scLR As Long: scLR = sc.Cells(sc.Rows.Count, scCol).End(xlUp).Row
Dim rng As Range
Set rng = sc.Range(sc.Cells(scFR, scCol), sc.Cells(scLR, scCol))
' Collecting Cells
Dim cel As Range, URng As Range
For Each cel In rng.Cells
If IsError(Application.Match(cel.Value, Del, 0)) Then
GoSub collectCells
End If
Next
' Deleting Rows
'If Not URng Is Nothing Then URng.EntireRow.Delete
' First test with Hiding Rows.
If Not URng Is Nothing Then URng.EntireRow.Hidden = True
Application.ScreenUpdating = True
sc.Activate
Exit Sub
collectCells:
If Not URng Is Nothing Then
Set URng = Union(URng, cel)
Else
Set URng = cel
End If
Return
End Sub
My code currently searches through Sheet1 and copies rows into Sheet2 if it matches the array of strings in strSearch. How can I make it so that it outputs "No Search Found" as a row on Sheet2 if there are no rows that contain the strSearch?
Dim ws1 As Worksheet, ws2 As Worksheet
Dim firstRowWs1 As Long
Dim lastRowWs1 As Long
Dim lastRowWs2 As Long
Dim searchColumnWs1 As Integer
Dim i As Integer
Dim check As Variant
Dim strSearch As Variant
Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")
With ws2
lastRowWs1 = ws1.UsedRange.Rows.Count
lastRowWs2 = ws2.UsedRange.Rows.Count
firstRowWs1 = 1
searchColumnWs1 = 10
strSearch = Array("John", "Jim")
For i = firstRowWs1 To lastRowWs1
For Each check In strSearch
If check = ws1.Cells(i, searchColumnWs1).Value Then
ws1.Rows(i).Copy (ws2.Rows(lastRowWs2 + 1))
ws2.Rows(lastRowWs2 + 1).Columns("A:B").Insert xlToRight
lastRowWs2 = lastRowWs2 + 1
ws1.Rows(i).Delete shift:=xlUp
i = i - 1
Exit For
End If
Next check
Next i
End With
Keep track of whether or not you found matches, and add the text after your loop.
Eg:
Dim foundMatches as Boolean
foundMatches = False
For i = firstRowWs1 To lastRowWs1
For Each check In strSearch
If check = ws1.Cells(i, searchColumnWs1).Value Then
foundMatches = True
... etc
End If
Next check
Next i
If Not foundMatches then
' print "no rows found" somewhere
end if