Sua última linha não é a última linha da tabela, mas há 3 linhas vazias incluídas na parte inferior, que são preenchidas por; porque sua macro contém esta linha:
Cells(RowNum, 10) = Cells(RowNum, 10) & ";" & Cells(RowNum + 1, 10)
Este comando basicamente diz: junte a linha vazia com a linha vazia e separe com
Mas você não quer verificar se há linhas vazias. Então o seu sub deve ser o seguinte:
Sub merge_dupes_and_comments()
'define variables
Dim RowNum As Integer, LastRow As Integer, EmptyCells as Integer
Application.ScreenUpdating = False
RowNum = 2
LastRow = Cells.SpecialCells(xlCellTypeLastCell).row
Range("A2", Cells(LastRow, 10)).Select
For Each row In Selection
'Do we have am empty row? If so exit the loop.
'Lets count the amount of empty cells on the row.
EmptyCells=0
For c = 1 to 10
if Cells(RowNum,c) = "" then EmptyCells = EmptyCells+1
Next c
'If we find more than 9 empty cells, assume the row is empty, and exit the loop.
if EmptyCells > 9 then exit for
'Lets continue the duplicate checking
'if OC number matches
'and if position and material match
If Cells(RowNum, 2) = Cells(RowNum + 1, 2) AND _
Cells(RowNum, 4) = Cells(RowNum + 1, 4) AND _
Cells(RowNum, 5) = Cells(RowNum + 1, 5) Then
'move updated comments up next to the old comment and delete empty line
Cells(RowNum, 10) = Cells(RowNum, 10) & ";" & Cells(RowNum + 1, 10)
Rows(RowNum + 1).EntireRow.Delete
End If
RowNum = RowNum + 1
Next row
Application.ScreenUpdating = True
End Sub
Eu também alterei a declaração de suas variáveis de longs para inteiros, porque você está trabalhando com números inteiros que não excedam os limites de um inteiro, portanto, consome menos memória.