【发布时间】:2015-04-20 22:35:59
【问题描述】:
我正在尝试修改可能在本地计算机上打开或未打开的 Excel 文件。机器可能有多个 Excel 实例正在运行,或者文件可能在网络上打开(在这种情况下不会进行任何修改)。根据我的理解,getObject(file_path) 将:
- 如果文件在本地计算机上打开,则获取工作簿的打开实例
- 如果文件未打开,则在已运行的 Excel 会话中打开该文件,或者
- 如果没有文件正在运行,请在新的 Excel 会话中打开文件。
在所有 3 种情况下,我都能以某些方式操作文档。但是,如果我使用getObject(file_path) 并且该文件尚未打开,我将无法调用工作簿的应用程序对象。任何带有getObject(file_path).application 的行都会给我错误:
“需要对象:'application.Evaluate(...)'”
在工作簿尚未打开的情况下。
我通过首先测试是否打开了任何 Excel 实例来解决此限制;如果没有,那么我手动创建一个实例,然后使用application.Workbooks.Open(to_filename,UpdateLinksCode) 打开工作簿。下面的代码适用于场景 1 和 3。我可以尝试在每个场景中使用“Workbooks.open”打开工作簿;但是重要的是,在执行结束时,Excel 实例和打开的工作簿与脚本启动时相同(因此,实际上,我可能需要确定我是处于方案 1 还是方案 2)。
就上下文而言,下面的程序旨在更新 Excel 2007 中的数据透视表范围。要进行测试,您需要一个带有数据透视表的工作簿,并将文件路径设置为 _filename,将 sheet_name 设置为带有透视数据。
Dim UpdateLinksCode, UpdateLinks, destsheet, excel_version, comma_delimit, tab_delimit, t, filename, sheet_name, to_filename, safepath, replacesheet, fso, sourcebook, destbook, objExcel, readfile, filesys, updatepivotrange, please, chart, preserve_formats, live, dest_Excel
to_filename = "C:\Users\user\Desktop\this.xlsx"
'see if Excel is open
On error resume next
Set objExcel = GetObject(, "Excel.Application")
if Err.Number<>0 then
Set dest_Excel = CreateObject("Excel.Application")
Set destbook = dest_Excel.Workbooks.Open(to_filename,UpdateLinksCode)
live = false
else:
Set destbook = GetObject(to_filename)
Set dest_Excel = destbook.application
live = true
end if
On error goto 0
sheet_name = "Sheet1"
dest_Excel.DisplayAlerts = false
'Loop through sheets
for I = 1 To destbook.Worksheets.Count
'loop through pivot tables
for J = 1 to destbook.Worksheets(I).PivotTables.Count
Set pt = destbook.Worksheets(I).PivotTables(J)
'Error in attempting to get Pivot data source range
Set rangeobj = dest_Excel.Evaluate(dest_Excel.ConvertFormula(pt.SourceData, -4150, 1))
Set datasheet = destbook.Worksheets(rangeobj.Parent.Name)
'only update pivot tables that have the sheet being updated referenced
if sheet_name = datasheet.name then
With datasheet
If dest_Excel.WorksheetFunction.CountA(.Cells) <> 0 Then
lastrow = .Cells.Find("*", dest_Excel.Range("A1"), -4123, 2, 1, 2, False).Row
lastcol = .Cells.Find("*", dest_Excel.Range("A1"), -4123, 2, 2, 2, False).Column
Else
lastrow = 1
lastcol = 1
End If
End With
Set sheet_range = datasheet.Range(datasheet.Cells(1, 1), datasheet.Cells(lastrow, lastcol))
With pt
.ChangePivotCache destbook.PivotCaches.Create(1, sheet_range, 3)
.PivotCache.Refresh
.HasAutoFormat = False
.SaveData = True
.PivotCache.RefreshOnFileOpen = True
.InGridDropZones = True
.RowAxisLayout 1
End with
End if
destbook.Worksheets(I).PivotTables(J).RefreshTable
Next
Next
if not live then
destbook.save
destbook.close
dest_Excel.quit
end if
【问题讨论】: