Hi Rafa - love your forehand.
Nice code. You obviously have programming experience, but the Excel MacroRecorder has led you astray on how VBA can be written more efficiently.
'Select' causes code to run slower, and is not needed a great percentage of the time.
I was able to get your code to work with the small change in red below. Please NOTE that your sort does not work, because there is some code missing. However, when the proper sort code is added and the sort works, the workbook finishes with rows in the wrong place.
See the attached file that contains several different versions of Sub Main().
Sub MainOriginalNewDotFindWithRgSearch()
Dim lrow As Long
Dim LastRow As Long
Dim t As Long
Dim t1 As Long
Dim a As Variant
Dim b As Variant
Dim rgSearch As Range
Dim cell As Range
Dim cell1 As Range
Dim firstCellAddress As String
'delete old data at sheet 2
Sheets("Sheet34").Select
Columns("H:BP").Select
Selection.Delete Shift:=xlToLeft
'return to sheet 1
Sheets("TASK CARD").Select
ActiveSheet.AutoFilterMode = False
'create 2 cloumns
Columns("C:C").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Columns("C:C").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
'copy data to 2 columns
Columns("A:B").Select
Selection.Copy
Range("C1").Select
ActiveSheet.Paste
Application.CutCopyMode = False
'find last row
lrow = Cells(Rows.Count, 10).End(xlUp).Row
'add full data to 2 columns
Cells(1, 3).Select
For t = 1 To lrow - 1
If IsEmpty(ActiveCell.Offset(t, 0).Value) = False Then
a = Cells(1 + t, 3).Value
b = Cells(1 + t, 4).Value
Else
Cells(1 + t, 3).Value = a
Cells(1 + t, 4).Value = b
End If
Next t
'trim the key data
Cells(1, 6).Select
For t = 1 To lrow - 1
a = Trim(Cells(1 + t, 6).Value)
Cells(1 + t, 6).Value = a
Next t
Cells(1, 7).Select
For t = 1 To lrow - 1
a = Trim(Cells(1 + t, 7).Value)
Cells(1 + t, 7).Value = a
Next t
Cells(1, 8).Select
For t = 1 To lrow - 1
a = Trim(Cells(1 + t, 8).Value)
Cells(1 + t, 8).Value = a
Next t
'apply filter
Range(Cells(1, 3), Cells(lrow, 11)).AutoFilter
'filter at AK column
Columns("J:J").Copy
Range("AK1").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
ActiveSheet.Columns("AK:AK").RemoveDuplicates Columns:=1, Header:=xlNo
'get data and add to sheet 2
Set rgSearch = ActiveSheet.AutoFilter.Range
Range("AK1").Select
LastRow = Cells(Rows.Count, 37).End(xlUp).Row
For t = 2 To LastRow - 1
a = Cells(1 + t, 37).Value
rgSearch.AutoFilter Field:=8, Criteria1:=a
ActiveWorkbook.Worksheets("TASK CARD").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("TASK CARD").AutoFilter.Sort.SortFields.Add Key:= _
Range(Cells(1, 4), Cells(lrow, 4)), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption _
:=xlSortTextAsNumbers
'Set cell = rgSearch.Find(a)
Set cell = rgSearch.Find(What:=a, LookIn:=xlValues)
Debug.Print cell.Address
firstCellAddress = cell.Address
t1 = 1
Do
b = cell.Offset(0, -1).Value & " " & cell.Offset(0, -7).Value
Sheets("Sheet34").Select
Set cell1 = Range("G1:G3000").Find(a)
If cell1 Is Nothing Then
Debug.Print a
GoTo abc
End If
Dim x As Long
x = x + 1
cell1.Offset(0, t1).Value = b
Debug.Print x, cell1.Address, a, b
abc:
t1 = t1 + 1
Sheets("TASK CARD").Select
Set cell = rgSearch.FindNext(cell)
Loop While firstCellAddress <> cell.Address
ActiveWorkbook.Worksheets("TASK CARD").AutoFilter.Sort.SortFields.Clear
Next t
Set rgSearch = Nothing
Set cell = Nothing
Set cell1 = Nothing
Sheets("TASK CARD").Select
ActiveSheet.AutoFilterMode = False
Columns("AK:AK").Select
Selection.Delete Shift:=xlToLeft
Columns("C:D").Select
Selection.Delete Shift:=xlToLeft
End Sub
To correct the sorting problem the following code has to be added:
Sub AutoFilterSortCorrection()
ActiveWorkbook.Worksheets("Task Card").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Task Card").AutoFilter.Sort.SortFields.Add _
Key:=Range("B1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption _
:=xlSortTextAsNumbers
With ActiveWorkbook.Worksheets("Task Card").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
The following suggestions may help you in the future:
a. Use 'Option Explicit'
To prevent typos from ruining days and weeks of work 'Option Explicit' is NEEDED at the top of each code module. This prevents errors caused by missspellings and FORCES every variable to be DECLARED (e.g. Dim i as Integer). https://www.excel-easy.com/vba/examp...-explicit.html
b. Use 'If then else' rather than 'goto abc' in most cases
c. Debug.Print (rather than MsgBox) outputs to the Immediate Window (Ctrl G in the debugger)
NOTE: Debug.Assert.False will act as a permanent breakpoint (often useful after a print)
d. Use Column Letters rather that Column Numbers (e.g. Cells(1, "D") is easier to read that Cells(1, 4) )
e. Qualify range to identify the worksheet (e.g. ws.Cells(1,4) rather than Cells(1,4) )
f. The .find routine can be hard to debug if all the parameters are not used, because the parameters are 'Sticky' if not explicitly named. See https://docs.microsoft.com/en-us/off...cel.range.find
Set rCellSource = rgSearch.Find(What:=a, _
After:=rgSearch(1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
g. Use of 'Select' slows down the code - especially inside of loops
Benchmark Times on my computer:
a. Original = 4.5 seconds
b. MainOriginalModified() average time = 3.0 seconds
c. MainOriginalOptimized() average time = 1.15 seconds
d. MainRewrite1() average time = 1.10 seconds
e. MainRewrite2() average time = 0.85 seconds
Changes:
MainOriginalModified() - Added/removed 'Task Card'/Dates in 'A' & 'B' white cells (instead of adding/deleting 2 columns). Implemented Sort. Added Temporary Use of Column 'Z' to contain original row numbers so original 'Task Card' row numbers can be restored.
MainOriginalOptimized() - Previous changes Plus - Removed Select where applicable. Added use of Worksheet Objects.
MainRewrite1() - Previous changes Plus - Replaced use of Column 'AK' with a 'Scripting Dictionary'. An Excel Scripting Dictionary is very good at identifying (and counting) unique items in a list.
Reference: http://www.experts-exchange.com/Soft...ss-in-VBA.html
Reference: http://www.snb-vba.eu/VBA_Dictionary_en.html
MainRewrite1() - Previous changes Plus - Replaced use of 'AutoFilter' with putting results in an array in memory and then sorting by date.
Lewis
Bookmarks