【发布时间】:2019-06-14 14:39:30
【问题描述】:
编写此脚本是为了访问一个目录并从多个 .xlsm 文件中提取数据并将其传递到目标文件中。我遇到的问题是代码想要单独打开每个,提取数据,然后关闭。这导致操作极其缓慢。有没有办法加快这个速度或改变我的代码结构来加快操作?
我有这段工作代码,但它非常慢。
Option Explicit
Const FOLDER_PATH = "C:\Users\maxd\OneDrive - Nortek, Inc\Coil Test Data\coils_35_and_36\36\WET\Testing\" 'REMEMBER END BACKSLASH
Sub ImportWorksheets()
'=============================================
'Process all Excel files in specified folder
'=============================================
Dim sFile As String 'file to process
Dim wsTarget As Worksheet
Dim wbSource As Workbook
Dim wsSource As Worksheet
Dim rowTarget As Long 'output row
rowTarget = 11
'check the folder exists
If Not FileFolderExists(FOLDER_PATH) Then
MsgBox "Specified folder does not exist, exiting!"
Exit Sub
End If
'reset application settings in event of error
On Error GoTo errHandler
Application.ScreenUpdating = False
'set up the target worksheet
Set wsTarget = Sheets("Sheet1")
'loop through the Excel files in the folder
sFile = Dir(FOLDER_PATH & "*.xlsm*")
Do Until sFile = ""
'open the source file and set the source worksheet - ASSUMED WORKSHEET(1)
Set wbSource = Workbooks.Open(FOLDER_PATH & sFile)
Set wsSource = wbSource.Worksheets("Report")
'import the data
With wsTarget
.Range("A" & rowTarget).Value = wsSource.Range("E9").Value 'Year
.Range("B" & rowTarget).Value = wsSource.Range("D30").Value 'CFM
'.Range("D" & rowTarget).Value = wsSource.Range("D30/(30*30/144)").Value 'Face Velocity
.Range("E" & rowTarget).Value = wsSource.Range("D36").Value 'AVG Capacity
.Range("F" & rowTarget).Value = wsSource.Range("D29").Value 'APD
.Range("G" & rowTarget).Value = wsSource.Range("D34").Value 'WPD
.Range("H" & rowTarget).Value = wsSource.Range("D22").Value 'Inlet db
.Range("I" & rowTarget).Value = wsSource.Range("D23").Value 'Inlet wb
'.Range("J" & rowTarget).Value = wsSource.Range("").Value 'Inlet dp
.Range("K" & rowTarget).Value = wsSource.Range("L16").Value 'Inlet WT
.Range("L" & rowTarget).Value = wsSource.Range("L17").Value 'Outlet WT
.Range("M" & rowTarget).Value = wsSource.Range("L22").Value 'Heat Balance
'optional source filename in the last column
.Range("N" & rowTarget).Value = sFile
End With
'close the source workbook, increment the output row and get the next file
wbSource.Close SaveChanges:=False
rowTarget = rowTarget + 1
sFile = Dir()
Loop
'Loop for face velocity
Dim r As Integer
Dim i As Integer
i = Cells(Rows.Count, 1).End(xlUp).Row
For r = 11 To i
Cells(r, 4) = "=RC[-2]/(30*30/144)"
Next r
errHandler:
On Error Resume Next
Application.ScreenUpdating = True
'tidy up
Set wsSource = Nothing
Set wbSource = Nothing
Set wsTarget = Nothing
End Sub
Private Function FileFolderExists(strPath As String) As Boolean
If Not Dir(strPath, vbDirectory) = vbNullString Then FileFolderExists = True
End Function
此代码导致操作成功,但对于 10 个 .xlsm 文件,处理它们大约需要 20 - 30 秒,如果不是更长的话。
【问题讨论】:
-
您可以使用
.visible = false打开每个文件以节省一点;甚至可以一次打开所有文件并循环遍历每个未命名为目标工作簿的打开文件,然后关闭非目标工作簿。 -
有趣。我会在哪里坚持
.visible = false? -
正在打开的图书中有
Workbook_Open事件宏吗? -
以只读方式打开文件并将计算设置为手动可能会稍微快一些。
-
@tigeravatar 我认为主要瓶颈是打开和关闭工作簿。文件 I/O 总是一个瓶颈,在问题上投入更多的内存、CPU 或线程并不能加快速度。解决方案是找出一种减少 I/O 的方法。这些书都有一个“报告”表,听起来也许有一个可以查询的基础数据源,而不是打开 20 个工作簿。否则,打开工作簿会花费打开工作簿所需的时间。