我有一个VBA宏,它是从电子表格函数(用户定义函数,UDF)调用的。当从互联网下载电子表格并且用户相应地设置了“信任中心”设置时,电子表格将打开,因此称为“受保护的视图”。该函数不会被调用。显示“启用编辑”按钮。 如果按下该按钮,电子表格将“受信任”并正常重新打开,开始计算,从而调用用户定义的函数。
但是,在该VBA函数中,Application.ActiveWorkbook
的值为Nothing
。这可以在调试器中验证。
由于我只需要阅读电子表格的一些属性(如路径名称),我可以选择检查Application.ActiveProtectedViewWindow
的可用性,它应该引用工作簿的受保护版本。在调试器中,可以检查此对象。但是,在发布(不调试)中运行Application.ActiveProtectedViewWindow
的值也是Nothing
。
这两种行为 - 特别是第一种 - 似乎是Excel 2010和2013中存在的错误(另请参阅a post at the MSDN forum)。
PS:作为对Siddharth Rout的良好观察的后续行动,“ThisWorkbook”可能会起作用:在我的情况下,宏不是正在开放的工作簿的一部分。 UDF在XLA中定义。因此,ThisWorkbook将引用XLA。我需要获取ActiveWorkbook(=调用UDF的工作簿)而不是ThisWorkbook(=运行UDF的工作簿)。问题:在启用编辑后,有没有办法获取活动工作簿的属性?
重要要求:
我的函数被称为用户定义的函数,即执行顺序由Excel更新单元格确定。
该函数不是正在打开的工作簿的一部分。它是XLA的一部分。
我无法将任何代码添加到已打开的工作簿中。
答案 0 :(得分:6)
摘要: 可以复制问题并且有一些可能的解决方法。最有希望的一个 - 由聊天产生 - 是使用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
从CHAT跟进
使用ActiveWindow.Parent.Path
代替ActiveWorkbook.Path
可以解决问题。
答案 1 :(得分:1)
尝试使用Application.Caller.Parent.Parent而不是Application.Activeworkbook
答案 2 :(得分:1)
这不是原始问题的完整答案,而是与此相关的问题的(脏)解决方法。
我需要ActiveWorkbook来推断工作簿路径,即ActiveWorkbook.Path。
使用ActiveWorkbook.Path的另一种方法是检查Application.RecentFiles(1).Path
哪个是最近打开的文件的路径。在许多情况下,这将是用户刚刚“启用编辑”的工作簿。但是,当然,此方法可能会失败:在使用的情况下打开另一张纸,然后启用先前打开的纸张。
(注意:ActiveWorkbook.Path给出了文件夹的路径,而Application.RecentFiles(1).Path给出了文件的完整路径,因此必须进行一些后处理。)
答案 3 :(得分:1)
我知道它的旧线程,但我遇到了同样的问题,我找到了解决方案;)
解决它的唯一方法是使用变量类型工作簿
Dim wbk as Workbook
Set wbk = Application.ProtectedViewWindows(index).Workbook
警告:
当活动窗口受到保护时, ActiveSheet 会返回 Nothing 。
Dim wsh As Worksheet
Set wsh = wbk.Worksheets(index)
答案 4 :(得分:1)
我今天也遇到了同样的问题,无论是接受的答案还是我在本页上或通过搜索Google-verse找不到的其他答案都对我没有帮助。我使用的是Office 365中的Excel版本,我认为这是问题的根源。
我找到一个Microsoft Excel 2010 resource并尝试了几个小时的旧尝试-失败周期后终于找到了解决方案。这是我得到的:
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年要好。
最好。
答案 5 :(得分:0)
尝试使用此代码。
If (UCase(ActiveWorkbook.Name) = ucase("<YOUR XLA NAME WITH EXTENSION>")) Then
End
End If
Set wbObj = ActiveWorkbook
第一次运行宏时,它只是在没有做任何事情的情况下结束。第二次它拿起正确的文件。