从受保护的视图中“启用编辑”时,Excel VBA ActiveWorkbook为“无”

您所在的位置:网站首页 Excel如何设置启用编辑 从受保护的视图中“启用编辑”时,Excel VBA ActiveWorkbook为“无”

从受保护的视图中“启用编辑”时,Excel VBA ActiveWorkbook为“无”

2024-06-16 10:28| 来源: 网络整理| 查看: 265

我有一个从电子表格功能(用户定义的功能,UDF)调用的VBA宏。当从互联网上下载电子表格并且用户相应地设置了"信任中心"设置时,电子表格将以这样的方式打开,即所谓的"保护视图"。该函数将不会被调用。显示一个按钮"启用编辑"。 如果按下该按钮,则电子表格将被"信任"并正常重新打开,开始计算,从而调用用户定义的函数。

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

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

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

Question: Is there a way to get hold of properties of the active workbook after it has been enabled for editing?

PS:作为对Siddharth Rout的很好观察的结果," ThisWorkbook"可能有效:就我而言,该宏不属于开放式工作簿的一部分。 UDF在XLA中定义。因此,ThisWorkbook将引用XLA。我确实需要获得ActiveWorkbook(=调用UDF的工作簿)而不是ThisWorkbook(=运行UDF的工作簿)。

重要要求:

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

该功能不是正在打开的工作簿的一部分。它是XLA的一部分。

我无法将任何代码添加到打开的工作簿中。

相关讨论 是在浏览器中还是从Excel应用程序中打开了工作簿? 我只有在浏览器中打开它时才遇到此问题。 试试这个实验。 在Excel中打开URL。 该工作簿是ZIP文件的一部分。 该zip文件已下载到Windows 7主机。 压缩文件被解压缩到目录中。 然后,Windows 7将"标记"为从互联网上获取的文件,Excel 2013将在"受保护的视图"中打开XLS文件。 这是Windows 7 / Excel的默认行为。 而且大多数"用户"都将以这种方式下载并打开它(不是我,而是打开文件的我的用户)。

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

我能够重现问题。

我试过了

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

我得到了True

但是,然后我尝试了一下,它给了我False

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

现在回答您的问题...

Question: Is there a way to get hold of properties of the workbook after it has been enabled for editing?

是。使用ThisWorkbook代替ActiveWorkbook

评论的跟进

退出Protected Mode后,一旦工作簿完全加载,便可以访问ActiveWorkbook对象。要对此进行测试,请将此代码放在受保护的文件中。

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

您会发现得到一个False

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

这是另一个测试

123Private Sub Workbook_Activate()     MsgBox ActiveWorkbook.Path End Sub

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

聊天的跟进

使用ActiveWindow.Parent.Path代替ActiveWorkbook.Path将解决此问题。

相关讨论 有趣。但是,这不能解决我的问题:宏不在工作簿中。它在XLA中。 ThisWorkbook给出了宏所在的工作簿。我确实希望活动的工作簿。 但是,一旦打开XLA,您应该能够从XLA访问该工作簿。我将上面的代码CStr(Application.ActiveWorkbook Is Nothing)放在Private Sub Workbook_Activate()中,它给了我False :) 这也很有趣。我说对了吗:您建议将Workbook_Activate放在XLA(宏所在的位置)中?是否为XLA(即在激活时)仅调用一次。但是,当(另一个)受保护的工作表进行了"启用编辑"功能时,又没有了? (请注意,启用的工作簿根本不包含任何宏-因此,此工作表中的Workbook_Activate将不是选项。 不,我不是说您必须在工作簿或加载项中插入Workbook_Activate`。我试图用Workbook_Activate演示的是,一旦完成工作簿的加载,您就可以使用ActiveWorkbook了。因此,您的外接程序在使用ActiveWorkbook时不会遇到任何困难。但是,您的XLA到底在做什么?如果您可以给我更多的见解,那么我可以给您直接的答案,即我是否知道。 如前所述,该插件仅提供了其他电子表格的功能。因此,我被叫时无法控制。该功能需要推断ActiveWorkbooks文件夹的路径,即ActiveWorkbook.Path。实际上是此加载项:obba.info。我找到了解决该问题的方法-但它很"脏"。我正在检查" Application.RecentFiles(1)"。 但是就像我提到的,一旦退出Protected Mode后加载了工作簿,就可以使用ActiveWorkbook。要测试您是否可以使用ActiveWorkbook,只需将Private Sub Workbook_Activate()放入受保护的文件中即可。您会注意到,退出保护模式的那一刻,您将得到一个False 在上述答案中也进行了更新。见Followup From Comments 我了解工作簿一旦加载," ActiveWorkbook"就可用。但是我的函数在那之前被调用了!执行顺序是Excel更新单元格的"从动"。此时,ActiveWorkbook无效。另外:我应该注册哪个事件,而不将代码添加到将打开的工作簿中? But my function was called before that!您能解释一下这部分吗?我确实问过你这个问题,但似乎没有引起注意... 同样:很明显," ActiveWorkbook"在以后的某个时间点可用。您可以通过运行宏,在"启用"工作表后手动触发宏来进行检查。这不是重点。关键是当Excel调用UDF时" ActiveWorkbook"不可用。 让我们继续聊天中的讨论 感谢您的聊天。我假设您找到了一个好的解决方法(ActiveWindow.Parent) 我编辑了您的答案,并在顶部总结了最有希望的解决方案。如果您不喜欢它,请重新编辑它。再次感谢您的聊天。

我今天也遇到了同样的问题,无论是接受的答案还是我在此页面上或通过搜索Google-verse找不到的其他答案都对我没有帮助。我使用的是Office 365中的Excel版本,我认为这是问题的根源。

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

123456789101112131415161718192021222324252627282930Option 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年要好。

最好。

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

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

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

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

12Dim wsh As Worksheet Set wsh = wbk.Worksheets(index) 相关讨论 嗨,我仅在Excel 2016中有此问题,您能告诉我"索引"的作用是什么,我们定义它吗? @raphuket,是的,您必须传递一个数字(index),该数字与集合中工作簿的顺序相对应,或者传递一个名称,与工作簿名称相对应。 看看MSDN文档。 啊,那行得通。 加上您给我的链接:这是起作用的代码:Dim WbProtected as Workbook如果Application.ProtectedViewWindows.Count> 0然后设置WbProtected = Application.ProtectedViewWindows(2).Workbook WbProtected.Sheet2.Activate其他:Sheet2.Activate结束 我很高兴我可以提供帮助;)

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

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

使用ActiveWorkbook.Path的替代方法是检查Application.RecentFiles(1).Path,它是最近打开的文件的路径。在许多情况下,这将是用户仅对其具有"启用的编辑"功能的工作簿。但是,当然,此方法可能会失败:如果使用者打开了另一个工作表,则启用了先前打开的工作表。

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

相关讨论 我不确定您为什么要采取这种解决方法。看到我更新的帖子。

尝试使用Application.Caller.Parent.Parent而不是Application.Activeworkbook

相关讨论 我创建了一个包含2个UDF的文件,但我无法复制您的问题-我在做什么不同?:您可以从此处下载它skydrive.live.com/redir?resid=B4A055A3ADB4DC8C!282

尝试使用此代码即可。

1234If (UCase(ActiveWorkbook.Name) = ucase("")) Then     End End If Set wbObj = ActiveWorkbook

第一次运行宏时,它什么也不做就结束了。第二次选择正确的文件。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3