Reputation: 95
I've written code to loop through a folder of workbooks and extract certain columns from their worksheets then paste the data onto a single worksheet
This code was working well until the 29th workbook, where the data that I wanted pasted at the bottom of my ExtractedColumns worksheet was instead pasted at the top. The same happened for the remaining workbooks- it overwrites the data that is at the top.
This problem occurs after 60,000 rows have been pasted into the ExtractedColumns worksheet, which is well below the limit on row numbers for an Excel worksheet.
I can't figure out why this is happening, especially because it's working fine for the first 28 workbooks.
Here's my code for copying and pasting (I'm not posting the code to loop through the folder and open each workbook, because I feel like that code isn't causing the problem):
Sub extract()
Dim curr As Range
Dim cell As Range
Dim lastRow As Variant
Dim n As Long
Dim found As Boolean
Dim FirstRow As Range
Dim wbOpen As Object
found = False
Set wbOpen = Workbooks("ExtractedColumns")
'finds where data starts
For i = 3 To 50
If Not IsEmpty(Cells(i, "E")) Then
Exit For
End If
Next
' Next
'Par B name: if there is a header with one of these names, then it extracts those
For Each curr In Range("A" & i, "Z" & i)
If InStr(1, curr.Value, "Protein name", vbTextCompare) > 0 Or InStr(1, curr.Value, "description", vbTextCompare) > 0 Or InStr(1, curr.Value, "Common name", vbTextCompare) > 0 Then
lastRow = wbOpen.Sheets("Sheet1").Cells(Rows.Count, "D").End(xlUp).Row
Range(curr.Offset(1), Cells(Rows.Count, curr.Column).End(xlUp)).Copy Destination:=wbOpen.Sheets("Sheet1").Range("D" & lastRow + 1)
found = True
Exit For
End If
Next
'If there isn't a header with one of the above names, then see if there is one with the name "protein"
If Not found Then
For Each curr In Range("A" & i, "Z" & i)
If InStr(1, curr.Value, "protein", vbTextCompare) > 0 Then
lastRow = wbOpen.Sheets("Sheet1").Cells(Rows.Count, "D").End(xlUp).Row
Range(curr.Offset(1), Cells(Rows.Count, curr.Column).End(xlUp)).Copy Destination:=wbOpen.Sheets("Sheet1").Range("D" & lastRow + 1)
Exit For
End If
Next
End If
'Par B accession
For Each curr In Range("A" & i, "Z" & i)
If InStr(1, curr.Value, "accession", vbTextCompare) > 0 Or InStr(1, curr.Value, "Uniprot", vbTextCompare) > 0 Or InStr(1, curr.Value, "IPI") > 0 Then
lastRow = wbOpen.Sheets("Sheet1").Cells(Rows.Count, "E").End(xlUp).Row
Range(curr.Offset(1), Cells(Rows.Count, curr.Column).End(xlUp)).Copy Destination:=wbOpen.Sheets("Sheet1").Range("E" & lastRow + 1)
found = True
Exit For
End If
Next
'Par B site
For Each curr In Range("A" & i, "Z" & i)
If (UCase(curr.Value) = "RESIDUE" Or UCase(curr.Value) = "POSITION" Or UCase(curr.Value) = "POSITIONS" Or InStr(1, curr.Value, "Positions within protein", vbTextCompare) > 0 Or InStr(1, curr.Value, "Position in peptide", vbTextCompare) Or InStr(1, curr.Value, "Site", vbTextCompare) > 0) And (InStr(1, curr.Value, "modification", vbTextCompare) = 0 And InStr(1, curr.Value, "ERK") = 0 And InStr(1, curr.Value, "class", vbTextCompare) = 0) Then
lastRow = wbOpen.Sheets("Sheet1").Cells(Rows.Count, "G").End(xlUp).Row
Range(curr.Offset(1), Cells(Rows.Count, curr.Column).End(xlUp)).Copy Destination:=wbOpen.Sheets("Sheet1").Range("G" & lastRow + 1)
Exit For
End If
Next
'puts dashes in any blank cells in the columns (so spreadsheet isn't ragged)
n = wbOpen.Sheets("Sheet1").UsedRange.Rows(wbOpen.Sheets("Sheet1").UsedRange.Rows.Count).Row
For Each curr In wbOpen.Sheets("Sheet1").Range("D2:D" & n)
If curr.Value = "" Then curr.Value = " - "
Next
For Each curr In wbOpen.Sheets("Sheet1").Range("E2:E" & n)
If curr.Value = "" Then curr.Value = " - "
Next
For Each curr In wbOpen.Sheets("Sheet1").Range("G2:G" & n)
If curr.Value = "" Then curr.Value = " - "
Next
'puts "x" in first empty row (filename will go in column A in this row)
n = wbOpen.Sheets("Sheet1").UsedRange.Rows(wbOpen.Sheets("Sheet1").UsedRange.Rows.Count + 1).Row
For Each curr In wbOpen.Sheets("Sheet1").Range("D2:D" & n)
If curr.Value = "" Then curr.Value = "x"
Next
For Each curr In wbOpen.Sheets("Sheet1").Range("E2:E" & n)
If curr.Value = "" Then curr.Value = "x"
Next
For Each curr In wbOpen.Sheets("Sheet1").Range("G2:G" & n)
If curr.Value = "" Then curr.Value = "x"
Next
End Sub
Upvotes: 1
Views: 1094
Reputation: 23974
If you are opening up some old format workbooks (which have a limit of 65536 rows) then your unqualified Rows.Count
in
lastRow = wbOpen.Sheets("Sheet1").Cells(Rows.Count, "D").End(xlUp).Row
is making that line equivalent to
lastRow = wbOpen.Sheets("Sheet1").Cells(65536, "D").End(xlUp).Row
So, once you have more than 65536 rows in your "ExtractedColumns" worksheet, the End(xlUp)
is moving all the way up to the top of the file and probably setting lastRow
to 1 (unless you have some empty cells below row 1 in column D).
That line should be
lastRow = wbOpen.Sheets("Sheet1").Cells(wbOpen.Sheets("Sheet1").Rows.Count, "D").End(xlUp).Row
Always qualify Range
, Cells
, Rows
, etc, unless you know that you want to refer to the ActiveSheet
.
Upvotes: 3