Edit: I found a potential solution. Changing all of the Dim as Long
to Dim as Integer
allows the scripts to run smoother. However, there is a potential that the number of rows in some instances will exceed 32767. Is there a way I can put a condition on the first few statements, to use integer
only if there are less than 30k rows?
The following script works to take a large dataset from this form in the Worksheet "List"
1 David
Eve
Freya
Sam
Yarra
2 Brian
David
Eva
Harry
Paul
3 Charlie
David
4 Eva
Harry
Paul
And paste it into another worksheet, "Library," like this:
1 2 3 4
David Brian Charlie Eva
Eve David David Harry
Freya Eva Paul
Sam Harry
Yarra Paul
While generating a singleton list of one of each name in the worksheet "List".
The (long) code is pasted below. As I said before, it works fine with shorter lists, but not with larger ones (over 20,000), as it gives me a "Not responding" message where I'm forced to End Task. Is there anything else I can do to fix this? It has been suggested that I add DoEvents, but I'm not sure how I could implement this into the current script. Also, it taking long wouldn't bother me too much if I could have some sort of Progress Bar that updates at each step. Would that work as a DoEvent? All suggestions are welcome.
Sub RunAH_KeyWordLibrary()
Call PrepareKeywords
Call PrepareLibrary
End Sub
Private Sub PrepareKeywords()
Application.ScreenUpdating = False
Application.Calculation = xlManual
Application.DisplayStatusBar = False
Application.EnableEvents = False
Application.ScreenUpdating = False
ActiveSheet.DisplayPageBreaks = False
Dim Library As Worksheet
Dim List As Worksheet
Set Library = Sheets("Library")
Set List = Sheets("List")
Dim Rng As Range
Dim i As Long
Dim lastRow As Long
i = 1
lastRow = Library.Range("A1").SpecialCells(xlCellTypeLastCell).row
While i <= lastRow
Set Rng = Library.Range("A" & i)
If Application.WorksheetFunction.CountA(Rng.Offset(0, 1)) = 1 Then
Rng.Offset(0, 1).Cut
Rng.Offset(1, 0).Insert Shift:=xlDown
Rng.Offset(0, 1).Insert Shift:=xlDown
ElseIf Application.WorksheetFunction.CountA(Rng.Offset(0, 1)) = 0 Then
i = i + 1
End If
Wend
Application.Calculation = xlAutomatic
Application.EnableEvents = True
Application.DisplayStatusBar = True
Application.EnableEvents = True
End Sub
Private Sub PrepareLibrary()
Application.ScreenUpdating = False
Dim Library As Worksheet
Set Library = Sheets("Library")
Dim lastRow As Long
Dim results As Variant
Dim resultsIndex As Long
Dim currentRow As Long
Dim currentColumn As Integer
currentColumn = 1
lastRow = Library.Range("A" & Rows.Count).End(xlUp).row
ReDim results(1 To lastRow)
results = Library.Range("A1:A" & lastRow).Value
For resultsIndex = 1 To lastRow
If IsNumeric(results(resultsIndex, 1)) Then
currentColumn = currentColumn + 1
Library.Cells(1, currentColumn) = results(resultsIndex, 1)
currentRow = 2
Else:
Library.Cells(currentRow, currentColumn) = results(resultsIndex, 1)
currentRow = currentRow + 1
End If
Next
Sheets("Library").Select
Cells.Replace What:="~*", Replacement:="", LookAt:=xlPart, SearchOrder _
:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
Columns("A:A").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("List").Select
Range("A1").PasteSpecial
Cells.Replace What:="~*", Replacement:="", LookAt:=xlPart, SearchOrder _
:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
Application.Calculation = xlAutomatic
Call Order
Call RemoveNumber
Call MakeUpper
Call RemoveDuplicates
Columns("B:B").Select
Selection.ClearContents
End Sub
Private Sub Order()
Columns("A:A").Select
ActiveWorkbook.Worksheets("list").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("list").Sort.SortFields.Add Key:=Range( _
"A1:A30000"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("list").Sort
.SetRange Range("A1:A30000")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Private Sub RemoveNumber()
Dim Rng As Range
Dim i As Long
i = 1
Application.ScreenUpdating = False
Dim lastRow As Long
i = 1
lastRow = List.Range("A1").SpecialCells(xlCellTypeLastCell).row
While i <= lastRow
Set Rng = Range("A" & i)
If IsNumeric(Rng.Value) = True And Len(Rng.Value) > 0 Then
Rng.Delete Shift:=xlUp
ElseIf IsNumeric(Rng.Value) = False Then
i = i + 1
Else: i = i + 1
End If
Wend
End Sub
Private Sub MakeUpper()
Dim C As Long
Dim List As Worksheet
Set List = Sheets("List")
C = List.Cells(Rows.Count, "A").End(xlUp).row
Range("B1").FormulaR1C1 = "=UPPER(RC[-1])"
Range("B1").Select
Selection.AutoFill Destination:=Range("B1:B" & C), Type:=xlFillDefault
Columns("B:B").Select
Selection.Copy
Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Columns("B:B").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlToLeft
End Sub
Private Sub RemoveDuplicates()
Application.EnableEvents = False
Application.Calculation = xlManual
Application.DisplayStatusBar = False
Application.EnableEvents = False
Application.ScreenUpdating = False
Dim Rng As Range
Dim i As Long
i = 2
Dim lastRow As Long
lastRow = List.Range("A1").SpecialCells(xlCellTypeLastCell).row
While i <= lastRow
Set Rng = List.Range("A" & i)
If Rng = Rng.Offset(1, 0) And IsEmpty(Rng.Value) = False Then
Rng.Delete Shift:=xlUp
ElseIf Rng <> Rng.Offset(1, 0) And IsEmpty(Rng.Value) = False Then
i = i + 1
Else: i = i + 1
End If
Wend
Application.Calculation = xlAutomatic
Application.EnableEvents = True
Application.DisplayStatusBar = True
Application.EnableEvents = True
End Sub
Integer
vsLong
concern: you have much bigger performance issues than the size of an integer. UseLong
for row numbers, regardless of how many rows you're dealing with. \$\endgroup\$