【问题标题】:How can I determine if an Excel workbook is open on local machine given that there may be multiple instances of Excel running?鉴于可能有多个 Excel 实例正在运行,如何确定 Excel 工作簿是否在本地计算机上打开?
【发布时间】:2015-04-20 22:35:59
【问题描述】:

我正在尝试修改可能在本地计算机上打开或未打开的 Excel 文件。机器可能有多个 Excel 实例正在运行,或者文件可能在网络上打开(在这种情况下不会进行任何修改)。根据我的理解,getObject(file_path) 将:

  1. 如果文件在本地计算机上打开,则获取工作簿的打开实例
  2. 如果文件未打开,则在已运行的 Excel 会话中打开该文件,或者
  3. 如果没有文件正在运行,请在新的 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

【问题讨论】:

    标签: vba excel


    【解决方案1】:
    set x = GetObject("c:\file.xls")
    

    做你想做的。

    你的方法是错误的。您使用的是文件而不是应用程序。使用文件 COM 规则适用,一切正常。请注意,过去,有人确实可以在 COM 中使用应用程序,但现在没有了。

    【讨论】:

    • 但是有没有一种方法可以调用应用程序方法,即 Application.Evaluate(...) 仅在文件尚未打开时才使用 GetObject(file) ?我的脚本中有几个实例依赖 Excel 应用程序,但我不确定如何围绕它们编写代码。
    • workbook.application 就这么简单。所以set x = createObject("c:file.xls"):x.application.displayalerts
    • 我不确定你的意思。首先,我收到set x = createObject(file) 的运行时错误,大概这应该是getObject?其次,我尝试使用workbook.application,然后使用application.evaluate 之类的函数,但它仅在文件已在Excel 中打开或我打开它(即使用Workbooks.Open(file))时才有效;这是我问题的症结所在,为什么只使用GetObject 不起作用。
    • 设置 xlBook = GetObject("C:\Users\David Candy\Documents\Super.xls"):对于 xlbook.worksheets:msgbox wsheet.name:mext:msgbox xlbook.application 中的每个 wsheet。显示警报。这允许应用 COM 规则。
    • 所以这个问题的重点是我正在调用我的工作簿的应用程序对象,并且至少这两个命令导致Object required 错误我首先打开工作簿(例如Workbooks.Open ),如果尚未打开:.ChangePivotCache destbook.PivotCaches.Create(1, sheet_range, 3), dest_Excel.Evaluate(dest_Excel.ConvertFormula(pt.SourceData, -4150, 1))
    【解决方案2】:

    这是一个我并不完全满意的解决方法,但它似乎有效。在测试 Excel 是否打开后,我测试工作簿窗口是否可见。同样,这不是一个完全强大的解决方案,但可能足以满足我的需求。

    在下面的代码中,live = "true" 对应场景 1,"somewhat" 对应场景 2,"false" 对应场景 3。

    On error resume next
        Set dest_Excel = GetObject(, "Excel.Application")
         if Err.Number<>0 then live = "false"
         Set destbook = GetObject(to_filename)
         Set dest_Excel = destbook.application
        'if workbook is visible and has the right path
        if dest_excel.Windows(destbook.name).visible = -1 and dest_excel.Windows(destbook.name).activesheet.parent.fullname = to_filename then
             live = "true"
        else
            if live <> "false" then live = "somewhat"
            set destbook = dest_Excel.Workbooks.Open(to_filename,UpdateLinksCode)
        end if
    On error goto 0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-27
      • 2016-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多