【发布时间】:2021-05-06 12:22:57
【问题描述】:
我每月收到 100 多个 Excel 电子表格,我从中选取固定范围并粘贴到其他电子表格中以制作报告。
我正在尝试编写一个 VBA 脚本来迭代我的 Excel 文件并将范围复制到一个电子表格中,但我无法做到。
有没有简单的方法可以做到这一点?
【问题讨论】:
-
问题:1) 你目前有什么? 2)如何知道要打开哪些文件? 3) 你遇到了什么问题?
我每月收到 100 多个 Excel 电子表格,我从中选取固定范围并粘贴到其他电子表格中以制作报告。
我正在尝试编写一个 VBA 脚本来迭代我的 Excel 文件并将范围复制到一个电子表格中,但我无法做到。
有没有简单的方法可以做到这一点?
【问题讨论】:
这里有一些 VBA 代码演示了遍历目录中的一堆 Excel 文件并打开每个文件:
Dim sourcePath As String
Dim curFile As String
Dim curWB As Excel.Workbook
Dim destWB As Excel.Workbook
Set destWB = ActiveWorkbook
sourcePath = "C:\files"
curFile = Dir(sourcePath & "\*.xls")
While curFile <> ""
Set curWB = Workbooks.Open(sourcePath & "\" & curFile)
curWB.Close
curFile = Dir()
Wend
希望这将是您处理现有宏代码的一个足够好的起点。
【讨论】:
这是我几年前写的,但也许它会对你有所帮助。我为最新版本的 Excel (xlsx) 添加了扩展。似乎有效。
Sub MergeExcelDocs()
Dim lastRow As Integer
Dim docPath As String
Dim baseCell As Excel.range
Dim sysObj As Variant, folderObj As Variant, fileObj As Variant
Application.ScreenUpdating = False
docPath = Application.GetOpenFilename(FileFilter:="Text Files (*.txt),*.txt,Excel Files (*.xls),*.xls,Excel 2007 Files (*.xlsx),*.xlsx", FilterIndex:=2, Title:="Choose any file")
Workbooks.Add
Set baseCell = range("A1")
Set sysObj = CreateObject("scripting.filesystemobject")
Set fileObj = sysObj.getFile(docPath)
Set folderObj = fileObj.ParentFolder
For Each fileObj In folderObj.Files
Workbooks.Open Filename:=fileObj.path
range(range("A1"), ActiveCell.SpecialCells(xlLastCell)).Copy
lastRow = baseCell.SpecialCells(xlLastCell).row
baseCell.Offset(lastRow, 0).PasteSpecial (xlPasteValues)
baseCell.Copy
ActiveWindow.Close SaveChanges:=False
Next
End Sub
编辑:
我应该提到它是如何工作的。当您启动宏时,它会弹出一个打开文件对话框。双击列表中的第一个文件(或任何文件)。它将创建一个新工作簿,然后遍历文件夹中的所有文件。对于每个文件,它会复制第一个工作表中的所有内容并将其粘贴到新工作簿的末尾。这就是它的全部内容。
【讨论】:
另一种解决方案是让您的汇总电子表格按文件名访问其他电子表格并获取数据本身。
为此,您需要同时打开所有电子表格,以便它可以更新链接,但这仍然可能比一次打开和复制/粘贴一个更快,即使使用宏也是如此。每个电子表格都需要有一个唯一的文件名。
如果在您收到电子表格之前不知道它们的名称,或者它们会定期更改,请在汇总表中创建一个列来存储工作表的文件名,然后使用字符串操作和使用 INDIRECT() 获取数据。
从一个特定文件中获取一个单元格数据的示例:
=INDIRECT("'[C:\path\workbook.xls]MyWorksheet'!$A$2")
为您想要获取的每个电子表格的每个单元格冲洗并重复上述操作。
你应该很聪明地知道如何让字符串传递给 INDIRECT()。将其构建为公式,这样您就可以对需要检索的每个单元格使用相同的公式。
例子:
= INDIRECT("'[" & $A2 & "]MyWorksheet'!$" & ADDRESS(3, COL()))
上面的公式会转到文件名在 $A2 中的电子表格(注意“2”之前缺少 $,因此您可以将相同的公式粘贴到其他文件的其他行),并获取单元格的值第三行的 MyWorksheet 工作表和 current 列(因此,如果它在您汇总的 B2 中,它会从另一个文件中获取 B3)。
调整 ADDRESS 函数,为所需的行和列添加偏移量。
上述解决方案的优点是可以在需要填充的行和列之间复制和粘贴相同的公式,Excel 会根据需要调整 $A2 和 COL()。非常易于维护。
编辑曾经遇到类似的情况,我无法一次加载所有电子表格(超过 200 个)。我想我最终编写了 VBA,所以它确实没有真正打开并读取 Excel 文件。相反,我让它遍历文件名,打开到每个文件名的 ODBC 连接,并使用 ADO 从指定的命名范围(在 ODBC 中显示为“表”——工作表也显示为“表”)读取我需要的值“但有关于允许名称的规则)。这比打开和关闭 Excel 文件要快得多,而且还具有不会导致 Excel 崩溃的额外优势。
【讨论】:
你试过了吗
Tools->Macro->Record New Macro
创建maco来做同样的事情
【讨论】:
罗德里戈,
我猜您的意思是 100 多个工作簿,您需要单独打开并复制并粘贴到一个工作簿中?听起来很有趣:)
如果您可以将它们全部放在一个目录中,那么打开每个文件相当容易,请先搜索一下。 (@Mark Biek 为您发布了一个很好的例子)
打开文件后,我会将数据复制到 ADO 记录集中,然后将其附加到该记录集中。我有 posted some code 正在做一些与在一个工作簿中合并多张工作表非常相似的事情。
这并不完全是您所需要的,但它应该会有所帮助。如果没有,请发布您的进度,我会在一周内再看一次。
【讨论】:
这可以通过在 Access 中使用 TransferSpreadsheet 来实现。 看这个链接:
此解决方案不需要任何 VBA。
【讨论】:
过去,我使用 VBA 创建外部引用(链接)。
我在这里发布了它(参见示例 2):
Best short examples of the need for Excel VBA
它类似于使用 INDIRECT,但不需要打开 excel 工作簿。
唯一的缺点是旧电脑或旧版本的 excel,不确定是哪个,会使这个过程变慢。我相信这是因为每次添加新的外部引用时,所有其他外部引用都会更新。为了让它运行得更快,我将 Calculation 设置为 Manual,添加了外部引用,并将 Calculation 设置为 Automatic 以更新它们。
之后,如果您只想要这些值,您可以使用断开链接,或复制和粘贴特殊值。
【讨论】: