从用户窗体中隐形激活工作簿

时间:2020-05-03 09:16:32

标签: excel vba

我一直在考虑这个问题超过两个星期,包括在这里提出一个问题,但是我都认为问题及其解决方案都是错误的。所以我想再试一次。

我有一个在Excel中打开的用户表单。它列出了所有当前打开的工作簿,并允许我打开其他工作簿。我的程序将在任何工作簿中添加,修改或删除表。表格必须位于程序生成的名称的工作表中。如果不存在此类工作表,则会添加它们。添加工作表后,将根据其名称将其排序到选项卡序列中的特定位置。这些操作均可以在ThisWorkbook上使用。我很难确定其中的某些条件不能在其他工作簿上使用,因此找不到解决方法。

从表格开始。从ThisWorkbook的工作表中调用它。我有模态。现在,它是无模式的。我没有发现任何区别。但是,由于数量众多,我很难为综合测试创造一个好的方法。我正在寻找可以节省大量反复试验时间的知识。

工作簿中添加了此代码。顺便说一句,据我所知,在此过程中暂停ScreenUpdating是无效的。它将窗口设置为不可见,从而产生效果。

Dim Fltr As String
Dim Ffn As Variant
Dim Fn() As String
Dim Wb As Workbook
Dim i As Long

Fltr = "Excel Workbooks|*.xls*||All Excel files|*.xl*"
Ffn = FileOpenName("Select a Target Document", Fltr, , True)
If Not IsEmpty(Ffn) Then
    Application.ScreenUpdating = False
    For i = 1 To UBound(Ffn)
        Fn = Split(Ffn(i), "\")
        On Error Resume Next
        Set Wb = Workbooks(Fn(UBound(Fn)))
        If Err Then
            Set Wb = Workbooks.Open(Ffn(i))
            ActiveWindow.Visible = False
        End If
    Next i
    ThisWorkbook.Activate
    Application.ScreenUpdating = True

加载表单后,此工作簿处于活动状态。所有其他打开的工作簿都是不可见的。上面的代码的作用是,新工作簿也将不可见,并且ThisWorkbook仍处于活动状态。表面上没有区别,但这似乎只是表面上的。

当我要将工作表添加到另一个工作簿时,该工作簿显然必须处于活动状态。我已经使用模式形式和无模式形式成功地完成了此操作,但是现在我的代码拒绝激活工作簿({Wb.Activate被忽略而没有通知),并且工作表被添加到ThisWorkbook中。这是添加工作表的代码。

Private Function CreateLibrary(Wb As Workbook, _
                               Frm As Modifier) As Worksheet
    ' SSY 052 ++ 26 Apr 2020

    Dim ClmWidth As Variant                     ' default column widths
    Dim C As Long

'    Windows(Wb.Name).Visible = True
    With Wb.Worksheets.Add
        With .Cells
            .HorizontalAlignment = xlLeft
            .VerticalAlignment = xlTop
            .WrapText = True

            ' Library font = Arial / Table font = Calibri
            With .Font
                .Name = "Arial"
                .Size = 10
            End With
        End With

        ' set default widths
        ClmWidth = Array(8.43, 10.57, 52, 24, 24)
        For C = 0 To UBound(ClmWidth)
            .Columns(C + 1).ColumnWidth = ClmWidth(C)
        Next C

        .Rows.RowHeight = 12.75
        .Name = Frm.TbxLib.Value
    End With

    Set CreateLibrary = ActiveSheet
End Function

我认为原因是我无法在不可见的窗口中激活工作簿。我相信它之前起作用的原因是尽管该窗口的Visible属性设置为True,但该窗口是不可见的。我认为它在我没有打开的工作簿上,但是在调用表单时打开了。这些工作簿不在隐形窗口中。只是,窗户没有激活。问题之一是Excel将激活在其中打开新工作簿的窗口。因此,我上面的代码应该是错误的。我在SO上找到了方法。

在上一个关于此主题的问题中,我抱怨新工作表添加在错误的位置,有时是ThisWorkbook而不是指定的工作表。我认为该问题将通过更新屏幕来解决。那不是真的新的工作表将位于错误的工作簿中,具体取决于打开预期工作簿的方式。我的代码只是将其添加到ActiveWorkbook中。但是我仍然不知道为什么它总是排在倒数第二的位置。我发现我的代码在插入所有其他工作表之前先插入了该工作表,但此后立即运行了排序器,这可能会再次移动工作表,具体取决于工作簿中已经存在的其他工作表,并且可能将其移动到工作表中。 ActiveWorkbook也是如此。我怀疑排序器可能会出现问题,具体取决于工作簿是否处于活动状态以及其窗口是否可见。在正常情况下,分类器工作正常,但是这样做的结果是,我不知道工作表是否以正确的位置插入。现在,我没有分类器就进行测试,但是根本无法插入工作表。

我处在恶性循环中,找不到出路。我认为,表单本身是我问题的核心。 Excel的VBA(2013)默认情况下将激活表单的工作簿。不再有无模式的表单,无法浏览在该表单上选择的工作簿。但这也不是我想要的。我希望除ThisWorkbook之外的所有工作簿都保留在后台。我认为,如果我能找到一种方法来打开其他工作簿并将其强制为与打开表单时已经打开的工作簿相同的技术位置,那么我的难题就可以解决。我读了某人的建议,暂时关闭表格并重新加载它,但这似乎就像用锤子拍打苍蝇一样。

编辑:- 同时,我在上面的过程中添加了以下代码。

    ThisWorkbook.Activate
    Dim Win As Window
    For Each Win In Application.Windows
        Debug.Print Win.Index, Win.Caption,
        Debug.Print Win Is ActiveWindow,
        Debug.Print Win.Visible
    Next Win
    Application.ScreenUpdating = True

它产生以下令人惊讶的结果。

enter image description here

  • Windows(1)是ThisWorkbook
  • 加载表单时Windows(2)已打开
  • 使用上面的代码添加了另外3个,其中我将ActiveWindow.Visible = False更改为Windows(1).Visible = False Windoes(1)应该是ActiveWindow,而不是(2)。实际上,Windows(1)和Windows(3)在Excel应用程序底部的选项卡行中可见,而其他3个窗口则不可见,其中包括#2以前在此处可见。观察这些窗口没有设置可见属性。当我关闭表格时,所有这些都改变了。我运行了相同的代码并获得了此打印输出,这也没有意义。但是,所有5个窗口现在都包含在Excel窗口底部的标签栏中,显然与它们的可见性状态无关。

enter image description here

我还想知道在我的上下文中无模式形式的意义何在。它似乎旨在允许切换其自己的工作簿的工作表。因此,保持差异是最好的情况。最糟糕的是什么?

2 个答案:

答案 0 :(得分:0)

不管我的问题是否有解决方案,现在看来我都找不到。因此,我做出了以下决定。

  1. 当用户单击“确定”按钮时,我将关闭并卸载用户表单。我希望这将消除可见窗口和不可见窗口之间存在的任何差异,并允许我激活所需的任何窗口。
  2. 我将激活用户在表单中选择的工作簿,并使其窗口处于活动状态和可见状态,希望在用户表单关闭和卸载后不会在该过程中受到干扰。
  3. 我将停止使用无模式的用户表格。它的方式似乎对我访问工作簿的功能没有影响。它看起来和闻起来像红鲱鱼。

========编辑2020年5月18日 我已经实现了上述步骤,并使项目按预期工作。我对该问题的最终结论是,这是由于存在开放用户表单而导致无法激活其他工作簿引起的。所有其他问题都是这种情况的副作用。

答案 1 :(得分:0)

对于它的价值,我可能会进行以下更改:

代替With Wb.Worksheets.Add 我会做的: wb.sheets.add.name = "bob" 要么 wb.sheets.add (before:=wb.sheets(1)).name = "bob" 或将sheets(1)替换为sheets(“ neil”)

那么您可以with wb.sheets("bob")-远离activeworkbook和activesheet。

我很确定if Err then不能正常工作-Err是一个对象,而不是布尔变量。因此也许应该是If Err.Number <> 0 then,您需要在循环之前和之后的任何时间出现错误时都包含Err.Clear,否则每次循环都会进入If语句

相关问题