我有一个宏在工作簿中(在两个表格之间)执行此操作。但现在我想在两本工作簿之间做到这一点。我认为逻辑很好,但我错过了什么?
它运行所有代码,但我没有收到任何错误,但同时它没有做任何事情。
Sub CTClearINCIDENTS()
Dim ws1 As Workbook
Dim ws1sheet As Worksheet
Dim ws2 As Workbook
Dim ws2sheet As Worksheet
Dim lastRow As Long
Set ws1 = ThisWorkbook
Set ws1sheet = ws1.Sheets("INCIDENTS")
ws1sheet.Rows(5 & ":" & ws1sheet.Rows.Count).ClearContents
Dim FilePath As String
File_Path = "C:\TEMP\TestExcel\Cambridge Daily Tracker " & Format(Now, "dd-MM-yyyy") & ".xlsx"
Set ws2 = Workbooks.Open(File_Path)
Set ws2sheet = ws2.Sheets("Page 1")
With ws2sheet
.AutoFilterMode = False
lastRow = .Range("A" & Rows.Count).End(xlUp).Row
.Range("A2" & lastRow).Copy
ws1sheet.Range("A5").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
End With
End Sub
edit1:minor xlPasteFormats> xlPasteValues我忘记了
答案 0 :(得分:1)
如果您只需要复制数据(即没有单元格格式化),那么最有效的方法是将工作表的范围值读入Variant
,然后将Variant
写入范围你的新工作表。
在定义范围时,您需要注意失去对工作表对象的控制,以及进行比您需要的选择更大的选择,或者依赖可能会让您感到困惑的范围定义。在您的代码中有一些例子。在这一行中:lastRow = .Range("A" & Rows.Count).End(xlUp).Row
您在ws2sheet
中定义范围,但计算活动工作表中的行数(无论是哪种工作表 - 在这种情况下,很可能是相同的)。在这一行中:ws1sheet.Rows(5 & ":" & ws1sheet.Rows.Count).ClearContents
您可以在第4行下方定义整个工作表以清除(即使您没有使用它们,也可以使用所有数百万行)。当然,使用ClearContents
Excel将比处理使用范围之外的单元格更加智能,但有一天你可能会陷入困境。
如果您使用字符串,最简单的方法是遵循Excel本身使用的相同地址约定。一旦你开始偏离这些约定,你就会得到一些意想不到的结果。只需尝试在代码的这些行上添加Select
,您就会惊讶于您所拥有的内容:
lastRow = .Range("A" & Rows.Count).End(xlUp).Row
.Range("2:2" & lastRow).Select
比方说,你的最后一行是23,你的代码实际上是选择“2:223”。
作为个人偏好,我希望将最后一行设为Range
而不是Long
,因为我可以完全避免您所犯的错误类型,如下所示:
set rng = .Range("A1", lastRow)
如果您需要跨越第一列以外的范围,可以逐列调整大小。这与您的情况相关,因为当您的数据可能只有几列左右时,您正在使用整行。同样,Excel可能会处理大多数保留在工作表使用范围内的情况,但为什么不自己控制范围呢?
我在下面给出了两个可能的编码解决方案示例。在这两种情况下,我都假设了最后一列“E”,但你会改变它以适应你的项目。版本1是Variant
,lastCell是Range
选项,版本2是粘贴,lastCell是Long
选项:
Dim fileName As String
Dim sourceBook As Workbook
Dim sourceSheet As Worksheet
Dim targetSheet As Worksheet
Dim sourceData As Variant
Dim rng As Range
Dim lastCell As Range
'Prepare the target sheet
Set targetSheet = ThisWorkbook.Sheets("INCIDENTS")
Set rng = targetSheet.Range("A5", _
targetSheet.UsedRange.Cells(sourceSheet.UsedRange.Cells.Count))
rng.ClearContents
'Open source workbook and find data range
fileName = "C:\TEMP\TestExcel\Cambridge Daily Tracker " & Format(Now, "dd-MM-yyyy") & ".xls"
Set sourceBook = Workbooks.Open(File_Path)
Set sourceSheet = sourceBook.Sheets("Page 1")
Set lastCell = sourceSheet.Cells(sourceSheet.Rows.Count, "A").End(xlUp)
'Resize by desired columns (I've used '5', ie up to "E" column)
sourceData = sourceSheet.Range("A2", lastCell).Resize(, 5).Value2
'Copy the data
targetSheet.Range("A5").Resize(UBound(sourceData, 1), UBound(sourceData, 2)) = sourceData
版本2,如果你觉得有必要使用粘贴:
Dim fileName As String
Dim sourceBook As Workbook
Dim sourceSheet As Worksheet
Dim targetSheet As Worksheet
Dim rng As Range
Dim lastRow As Long
'Clear below row 4 of sheets
Set targetSheet = ThisWorkbook.Sheets("INCIDENTS")
Set rng = targetSheet.Range("A5", _
targetSheet.UsedRange.Cells(sourceSheet.UsedRange.Cells.Count))
rng.ClearContents
'Open source workbook and remove auto filter
fileName = "C:\TEMP\TestExcel\Cambridge Daily Tracker " & Format(Now, "dd-MM-yyyy") & ".xls"
Set sourceBook = Workbooks.Open(File_Path)
Set sourceSheet = sourceBook.Sheets("Page 1")
sourceSheet.AutoFilterMode = False
'Copy the data
lastRow = sourceSheet.Cells(sourceSheet.Rows.Count, "A").End(xlUp).Row
Set rng = sourceSheet.Range("A2", sourceSheet.Cells(lastRow, "E")) ' whatever the last column is (I'ved used "E" as example)
rng.Copy
targetSheet.Range("A5").PasteSpecial xlPasteValues, xlPasteSpecialOperationNone, False, False
答案 1 :(得分:0)
Per @ Ambie的建议我改变了范围。起初(A2:A
)它只复制A列。但我发现(2:2
)会复制行。
现在正在运作:
Sub CTClearINCIDENTS()
Dim ws1 As Workbook
Dim ws1sheet As Worksheet
Dim ws2 As Workbook
Dim ws2sheet As Worksheet
Dim lastRow As Long
Set ws1 = ThisWorkbook
Set ws1sheet = ws1.Sheets("INCIDENTS")
ws1sheet.Rows(5 & ":" & ws1sheet.Rows.Count).ClearContents
Dim FilePath As String
File_Path = "C:\TEMP\TestExcel\Cambridge Daily Tracker " & Format(Now, "dd-MM-yyyy") & ".xls"
Set ws2 = Workbooks.Open(File_Path)
Set ws2sheet = ws2.Sheets("Page 1")
With ws2sheet
.AutoFilterMode = False
lastRow = .Range("A" & Rows.Count).End(xlUp).Row
.Range("2:2" & lastRow).Copy
ws1sheet.Range("A5").PasteSpecial Paste:=xlValues, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
End With
End Sub