8

我有一个从电子表格函数(用户定义函数,UDF)调用的 VBA 宏。当从互联网下载电子表格并且用户已相应地设置“信任中心”设置时,电子表格将在所谓的“受保护视图”中打开。该函数将不会被调用。显示“启用编辑”按钮。如果按下按钮,则电子表格是“受信任的”并正常重新打开,开始计算,因此调用用户定义的函数。

但是,在该 VBA 函数中, 的Application.ActiveWorkbook值为Nothing。这可以在调试器中验证。

由于我只需要读取电子表格的一些属性(如路径名),因此我可以选择检查Application.ActiveProtectedViewWindow哪些属性应引用工作簿的受保护版本的可用性。在调试器中,可以检查此对象。但是,在发行版中运行(没有调试)的值Application.ActiveProtectedViewWindow也是Nothing.

这两种行为——尤其是第一种——似乎是 Excel 2010 和 2013 中存在的错误(另请参见MSDN 论坛上的帖子)。

问题:有没有办法在启用编辑后获取活动工作簿的属性?

PS:作为对 Siddharth Rout 的良好观察的后续,“ThisWorkbook”可能会起作用:在我的情况下,宏不是开放式工作簿的一部分。UDF 在 XLA 中定义。因此,ThisWorkbook 将引用 XLA。我确实需要获取 ActiveWorkbook(= 调用 UDF 的工作簿)而不是 ThisWorkbook(= 运行 UDF 的工作簿)。

重要要求:

  1. 我的函数被称为用户定义函数,即执行顺序由 Excel 更新单元格确定。

  2. 该函数不是正在打开的工作簿的一部分。它是 XLA 的一部分。

  3. 我无法向打开的工作簿添加任何代码。

4

6 回答 6

8

摘要: 该问题可以复制,并且有一些可能的解决方法。最有希望的一个(来自聊天)是使用ActiveWindow.Parent而不是ActiveWorkbook.


我能够复制这个问题。

我试过了

Private Sub Workbook_Open()
    MsgBox "Application.ActiveWorkbook Is Nothing = " & _
    CStr(Application.ActiveWorkbook Is Nothing)
End Sub

我得到了True

但是,然后我尝试了这个,它给了我False

Private Sub Workbook_Open()
    MsgBox "Application.ActiveWorkbook Is Nothing = " & _
    CStr(Application.ThisWorkbook Is Nothing)
End Sub

现在回答你的问题...

问题:有没有办法在启用编辑后获取工作簿的属性?

是的。使用ThisWorkbook代替ActiveWorkbook

评论跟进

退出 后工作簿完全加载后Protected Mode,您将能够访问该ActiveWorkbook对象。要对此进行测试,请将此代码放入受保护的文件中。

Private Sub Workbook_Activate()
    MsgBox "Application.ActiveWorkbook Is Nothing = " & _
    CStr(Application.ActiveWorkbook Is Nothing)
End Sub

你会注意到你得到一个False

因此,一旦您的工作簿加载,您​​的加载项就可以ActiveWorkbook用来与打开的文件进行交互。

这是另一个测试

Private Sub Workbook_Activate()
    MsgBox ActiveWorkbook.Path
End Sub

这就是我得到的那一刻,我退出Protected Mode

在此处输入图像描述

聊天跟进

使用ActiveWindow.Parent.Path而不是ActiveWorkbook.Path可以解决问题。

于 2013-10-13T13:24:18.310 回答
2

我今天遇到了同样的问题,我在此页面上或通过搜索 Google-verse 找到的已接受答案或任何其他答案都对我不起作用。我在 Office 365 中使用 Excel 版本,我认为这是问题的根源。

在找到Microsoft Excel 2010 资源并在旧的尝试失败周期中运行了几个小时后,我最终找到了解决方案。这是我得到的:

Option Explicit
Public WithEvents oApp As Application
Private bDeferredOpen As Boolean
Private Sub Workbook_Open()
    Set oApp = Application
End Sub
Private Sub oApp_WorkbookActivate(ByVal Wb As Workbook)
    If bDeferredOpen Then
        bDeferredOpen = False
        Call WorkbookOpenHandler(Wb)
    End If
End Sub
Private Sub oApp_WorkbookOpen(ByVal Wb As Workbook)
    Dim oProtectedViewWindow As ProtectedViewWindow
    On Error Resume Next
    'The below line will throw an error (Subscript out of range) if the workbook is not opened in protected view.
    Set oProtectedViewWindow = oApp.ProtectedViewWindows.Item(Wb.Name)
    On Error GoTo 0
    'Reset error handling
    If oProtectedViewWindow Is Nothing Then
        bDeferredOpen = False
        Call WorkbookOpenHandler(Wb)
    Else
        'Delay open actions till the workbook gets activated.
        bDeferredOpen = True
    End If
End Sub
Private Sub WorkbookOpenHandler(ByVal Wb As Workbook)
    'The actual workbook open event handler code goes here...
End Sub

2010 解决方案与我的解决方案之间的区别在于,我必须调用 Workbook_Open 并在那里显式设置 oApp 变量,因为没有该分配,当我打开文件时,oApp_WorkbookActivate 和 oApp_WorkbookOpen 函数都不会触发。

认为其他人可能会从中受益,所以我发布了它,尽管这个线程的最新更新比 2 岁要好。

最好的。

于 2018-07-12T22:25:13.923 回答
1

Try using Application.Caller.Parent.Parent instead of Application.Activeworkbook

于 2013-10-13T13:16:26.130 回答
1

这不是对原始问题的完整答案,而是与此相关的问题的(肮脏)解决方法。

我需要 ActiveWorkbook 来推断工作簿路径,即 ActiveWorkbook.Path。

使用 ActiveWorkbook.Path 的替代方法是检查Application.RecentFiles(1).Path哪个是最近打开的文件的路径。在许多情况下,这将是用户刚刚“启用编辑”的工作簿。但是,当然,这种方法可能会失败:在使用打开另一个工作表的情况下,然后启用之前打开的工作表。

(注意:ActiveWorkbook.Path 给出了文件夹的路径,而 Application.RecentFiles(1).Path 给出了文件的完整路径,所以必须进行一些后期处理)。

于 2013-10-13T16:12:06.843 回答
1

我知道这是旧线程,但我遇到了同样的问题,我找到了解决方案;)

解决它的唯一方法是使用变量类型Workbook

Dim wbk as Workbook
Set wbk = Application.ProtectedViewWindows(index).Workbook

警告: 当活动窗口也受到保护时,
ActiveSheet不返回任何内容。

Dim wsh As Worksheet
Set wsh = wbk.Worksheets(index)
于 2014-06-25T17:46:43.863 回答
0

试试这个代码,它可以工作。

If (UCase(ActiveWorkbook.Name) = ucase("<YOUR XLA NAME WITH EXTENSION>")) Then 
    End
End If
Set wbObj = ActiveWorkbook

第一次运行宏时,它只是结束而没有做任何事情。第二次拾取正确的文件。

于 2014-05-12T12:36:18.633 回答