【问题标题】:How to open document from Macro without Activating如何在不激活的情况下从宏打开文档
【发布时间】:2020-10-03 11:52:10
【问题描述】:

我一直在处理宏,有时我需要打开一个文档,复制和编辑一些数据,然后返回到上一个文档以继续使用宏。我有一个 fileDialog,我运行它让用户选择文档,但问题是这会激活文档,即使在 ScreenUpdating 关闭的情况下也会导致屏幕闪烁。是否有替代 Workbooks.Open 我可以使用它不会激活新文档? Workbooks.Open 中的一项设置我可以更改以阻止它激活吗?一种在文档激活时阻止屏幕闪烁的方法?下面是 fileDialog 的代码和每边的几行代码:

Set fileDialog = Application.fileDialog(msoFileDialogFilePicker)
Application.ScreenUpdating = False
With fileDialog
    .InitialFileName = "C:\Users\User\Documents"
    .AllowMultiSelect = False
    .Filters.Clear
    .Title = dialogTitle
    If .Show = False Then
        Application.ScreenUpdating = True
        MsgBox "No file chosen. Click Import Contact List to try again."
        Exit Sub
    End If
    strPathFile = .SelectedItems(1)
End With
Set wbSource = Workbooks.Open(Filename:=strPathFile)

任何解决方案将不胜感激。

【问题讨论】:

  • 目标文档中是否有宏?如果是这样,使用 Application.EnableEvents = False / True (就像 ScreenUpdating 一样)可能会有所帮助。我正在专门考虑目标文档中的 Workbook_Open;如果您自己的工作簿侦听应用程序级事件,这也是您自己的工作簿可能会拦截的内容。
  • 文档中没有宏,似乎 Workbooks.Activate 覆盖了 Application.ScreenUpdating = False。我刚刚创建了一个示例来测试它:`Sub News() Application.ScreenUpdating = False Workbooks("Hours.xlsx").Activate Workbooks("Book1.xlsm").Activate Application.ScreenUpdating = True End Sub` 其中 Book1 .xlsm 是我刚刚创建的文档,而“Hours.xlsx”只是一个文档,我必须在没有任何方程式或宏或任何东西的情况下记录小时数。但即便如此,屏幕还是会闪烁。
  • 您的代码中没有Activate...我也刚刚创建了一个示例,ScreenUpdating = False 没有任何闪烁。
  • 如何调用 News() 子程序并看到闪烁?
  • Workbooks.Open 自动激活现在打开的文档。我添加了 Application.EnableEvents = False,但这似乎并没有解决它。我已经在更多的测试文档上进行了尝试,当 Workbooks.Activate 发生时,似乎没有什么可以阻止它闪烁。这不是特别明显,但我将目标文档中的一行单元格突出显示为黄色以使其更加明显。基本上,它会在返回之前闪烁到另一个文档的几分之一秒。知道是什么原因造成的,是否可以修复?

标签: vba excel excel-2016


【解决方案1】:

我的假设是你想让用户打开一个文件,让它保持打开状态,但之后让你的工作簿处于活动状态,以便打开的文件保持“在后台”供用户稍后导航。您已经注意到一些烦人的闪烁并来这里寻求答案。

我可以使用与您的代码相似的代码重现您描述的行为的唯一方法是,当我打开一个文件时已在同一 Excel 会话中打开(请参阅下面的第 3 个用例)。请注意,您的代码不会关闭刚刚打开的工作簿,因此第一次运行时,您处于下面的用例 2 中,第二次运行时,您处于下面的用例 3 中。

但是,如果您可以在流程结束时关闭工作簿,那么您将处于下面的第一个用例中,一切都应该没问题。

让我们看看是否有人能提出用例 2 和 3 的解决方案。

这个第一个用例通常不会引入闪烁:

Application.ScreenUpdating = False
Application.EnableEvents = False 'For good measure.
Set myWb = Application.Workbooks.Open("... path of some workbook that's not already open ...")
'... Do stuff ...
myWb.Close
Application.EnableEvents = True
Application.ScreenUpdating = True

我无法让下面的其他 2 个用例按预期运行。

第二个用例是当工作簿必须在上述过程结束时保持打开,但不是活动的,所有这些都没有任何闪烁。 无论我尝试了什么,打开的工作簿在离开代码后会变成活动的工作簿

Application.ScreenUpdating = False
Application.EnableEvents = False 'For good measure.
Set myWb = Application.Workbooks.Open("... path of some workbook that's not already open ...")
'... Do stuff ...
'myWb.Close 'Here, the workbook is left opened.
ThisWorkbook.Activate 'Trying...
Application.EnableEvents = True
Application.ScreenUpdating = True
ThisWorkbook.Activate 'Trying harder...
'Be my guest...
'Note: Application.OnTime eventually calling ThisWorkbook.Activate doesn't count!

第三个用例很奇怪,可能发生在 OP 上。以上面的第二个用例为例,但打开一个工作簿已经在同一个 Excel 实例中打开。即使ScreenUpdating = False在操作期间闪烁(不酷),代码也会以ThisWorkbook作为活动代码离开(酷!)。

我试过玩myWb.Windows(1).Visible = FalseDoEvents,你说的,但无济于事。欢迎您的 cmets。

编辑(3 年后)

一个肮脏的解决方法是打开工作簿,然后立即将其IsAddin 属性设置为True。这将把它从 Excel 的 UI 中删除,并让工作簿在前面执行代码,无论如何。需要注意的是,您现在必须管理打开的工作簿的可见性(例如,当用户希望看到它时设置 IsAddin = False)和生命周期(例如,在退出应用程序的工作簿时关闭它)。但这是可行的。

【讨论】:

  • 哇,老实说,我很高兴你发现了问题,我几乎放弃了希望。事实上,我确实仍然打开了文档,因为宏要求稍后在用户输入工作表名称后打开文档。知道它保持打开是问题所在,我稍微修改了代码,现在我只是在用户输入之前关闭它,然后重新打开。非常感谢您的帮助!
  • @Excelosaurus - 我似乎已经在我对 OP 问题here 的评论中发现了这个问题。当你有时间时,请你回顾和分享你的观察/cmets。
  • @Karthick Ganesan - 打开工作簿,而 Application.ScreenUpdating = True 违背了 OP 的零闪烁目标。
  • @Excelosaurus - 没错,我意识到我的错误。现在,我进行了进一步深入研究,发现 wb_Ref_Opened.Windows(1).WindowState = xlMinimized 之类的内容接近 OP 的预期。
【解决方案2】:

在打开工作簿时,您可以隐藏工作簿或激活 ThisWorkbook 以免显示刚刚打开的工作簿。

Sub OpenAndHide() 将 wbSource 调暗为工作簿 将 FileDialog 调暗为 FileDialog Dim dialogTitle As String 将 strPathFile 调暗为字符串

Set FileDialog = Application.FileDialog(msoFileDialogFilePicker)
dialogTitle = "Open And Hide"

With FileDialog
    .InitialFileName = "C:\Users\User\Documents"
    .AllowMultiSelect = False
    .Filters.Clear
    .Title = dialogTitle
    If .Show = False Then
        Application.ScreenUpdating = True
        MsgBox "No file chosen. Click Import Contact List to try again."
        Exit Sub
    End If
    strPathFile = .SelectedItems(1)
End With
Set wbSource = Workbooks.Open(Filename:=strPathFile)
ThisWorkbook.Activate

'// Hide the workbook
'strPathFile = GetFilenameFromPath(strPathFile)
'Windows(strPathFile).Visible = False

结束子

函数 GetFilenameFromPath(ByVal strPath As String) As String ' 返回字符串最右边的字符,但不包括最右边的 '\' '例如'c:\winnt\win.ini' 返回 'win.ini'

If Right$(strPath, 1) <> "\" And Len(strPath) > 0 Then
    GetFilenameFromPath = GetFilenameFromPath(Left$(strPath, Len(strPath) - 1)) + Right$(strPath, 1)
End If

结束函数

【讨论】:

  • 吉姆,问题是即使关闭屏幕更新,当我打开文档然后返回并激活原始文档时,屏幕会闪烁。我找不到任何办法让那部分消失。
【解决方案3】:

你可以试试

Set wbSource = Workbooks.Open(Filename:=strPathFile)
Workbooks(name of users workbook).Activate

Set wbSource = Workbooks.Add(trPathFile)

希望对你有帮助。

【讨论】:

  • 我尝试了第一个,即使屏幕更新设置为 false,它仍然会快速闪烁到文档中。我刚刚尝试了第二个,现在遇到了“编译错误:未找到命名参数”错误。
  • 我编辑了第二个选项。对了,应用闪退是怎么回事?
  • 刚刚测试了编辑后的第二个选项,现在没有错误了,但遗憾的是它仍然没有解决问题;文档最终仍然被激活,导致屏幕闪烁。应用程序闪烁的唯一问题是,这将是我给老板的最终产品,我知道他会抱怨它。
猜你喜欢
  • 2010-10-16
  • 2014-11-25
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-23
相关资源
最近更新 更多