VBA 不需要的工作表循环

标签 vba excel loops

我经常使用这个网站,但这是我发布的第一个问题,希望我能提供足够的细节。我找不到任何相关的答案,因为无论我搜索什么,我都会得到与循环代码相关的各种答案。

一些背景: 我设计了一个Excel文档来跟踪我工作场所中的一些项目(以下简称主文档)。由于以前的跟踪器允许用户随时编辑任何内容,因此我使用了表单来确保所有信息都正确输入并安全存储。主文档中的每个项目都有一个单独的 Excel 工作簿(以下简称项目文档)。

主文档中有许多工作表,每次激活时都会运行代码(因为它们需要更新)。

由于每个项目文档中都有一些 VBA 代码,这对于与主文档同步数据至关重要,因此我添加了一个警告工作表,在没有宏的情况下打开项目文档时会显示该工作表。这涉及使用工作簿打开、保存前和保存后事件来确保仅显示警告而不显示宏。这是每个事件的代码(显然放置在 ThisWorkbook 模块中)

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

    Auto_Open

    'This is for sync (Master Document checks for text file to see if any changes have been made to Item Document)
    If booChange = True Then
        Dim oFile As Object
        Set oFile = fso.CreateTextFile(strTextFile)
        SetAttr strTextFile, vbHidden
        booChange = False
    End If

    'Turn off Screen Updating
    Application.ScreenUpdating = False

    'Show warning sheet
    Sheets("Warning").Visible = xlSheetVisible

    'Hide all sheets but Warning sheet
    For Each sh In ThisWorkbook.Worksheets
        If Not sh.Name = "Warning" Then sh.Visible = xlVeryHidden
    Next sh

End Sub

Private Sub Workbook_AfterSave(ByVal Success As Boolean)

    'Show all sheets
    For Each sh In ThisWorkbook.Worksheets
        sh.Visible = xlSheetVisible
    Next sh

    'Hide the warning sheet
    Sheets("Warning").Visible = xlVeryHidden

    'Return focus to the main page
    ThisWorkbook.Worksheets(1).Activate

    'Turn on Screen Updating
    Application.ScreenUpdating = True

    ThisWorkbook.Saved = True

End Sub

Private Sub Workbook_Open()

    'Turn off Screen Updating
    Application.ScreenUpdating = False

    'Show all sheets
    For Each sh In ThisWorkbook.Worksheets
        sh.Visible = xlSheetVisible
    Next sh

    'Hide the warning sheet
    Sheets("Warning").Visible = xlVeryHidden

    'Return focus to the main page
    ThisWorkbook.Worksheets(1).Activate

    'Turn on Screen Updating
    Application.ScreenUpdating = True

    ThisWorkbook.Saved = True

End Sub

为了完整起见,这里是项目文档 Module1 中的所有代码

'Declarations
'Strings
Public strSourceFolder As String
Public strTextFile As String

'Other
Public fso As FileSystemObject
Public booChange As Boolean
Public wsFlow As Worksheet

'Constants
Public Const strURNSheetName = "Part 1 Plant Flow Out Summ"

Sub Auto_Open()

    Set fso = CreateObject("Scripting.FileSystemObject")
    Set wsFlow = ThisWorkbook.Worksheets(strURNSheetName)
    strSourceFolder = fso.Getfile(ThisWorkbook.FullName).ParentFolder.Path
    strTextFile = fso.BuildPath(strSourceFolder, ThisWorkbook.Worksheets(strURNSheetName).Range("W2").Value & ".txt")

End Sub

当使用“frmNewEntry”表单在主文档中创建项目时,将检查信息并将其输入到主文档中,然后打开模板项目文档并使用新的唯一文件名保存。然后,它不 protected ,使用新信息进行更新, protected ,保存并关闭。然后保存主文档。代码如下(经过编辑以省略冗长的格式设置和数据输入):

表单代码:

Private Sub btnSave_Click()
    'Values on form are verified
    'Master Document sheet is unprotected, formatted and data entry occurs

    'Clear Userform and close
    For Each C In frmNewEntry.Controls
        If TypeOf C Is MSForms.ComboBox Then
            C.ListIndex = -1
        ElseIf TypeOf C Is MSForms.TextBox Then
            C.Text = ""
        ElseIf TypeOf C Is MSForms.CheckBox Then
            C.Value = False
        End If
    Next
    frmNewEntry.Hide

    'Create filepaths
    Create_Filepath

    'Some hyperlinks are added and the Master Document worksheet is protected again

    'Create Flowout Summary
    Create_Flowout_Summary

    'Update Flowout Summary
    Update_Flowout_Summary

    'Turn on screen updating
    Application.ScreenUpdating = True

    'Update Activity Log
    Update_Log ("New: " & strNewURN)

    Debug.Print "Before Save Master"

    'Save tracker
    ThisWorkbook.Save

    Debug.Print "After Save Master"

End Sub

模块1代码:

Public Sub Create_Flowout_Summary()
'Create a new flowout summary from the template

    'Turn off screen updating
    Application.ScreenUpdating = False

    'Check if workbook is already open
    If Not Is_Book_Open(strTemplate) Then
        Application.Workbooks.Open (strTemplatePath)
    End If

    Debug.Print "Before SaveAs Create"

    'Save as new flowout summary
    Application.Workbooks(strTemplate).SaveAs fileName:=strFilePath

    Debug.Print "After SaveAs Create"

    'Close Document Information Panel
    ActiveWorkbook.Application.DisplayDocumentInformationPanel = False  'Doesn't seem to work

    'Turn on screen updating
    Application.ScreenUpdating = True

End Sub

Public Sub Update_Flowout_Summary()
'Update the flowout summary for current call

    Dim wsURN As Worksheet

    Set wsURN = Workbooks(strFileName).Worksheets(strWsURNName)

    'Unprotect Flowout Summary worksheet
    wsURN.Unprotect "Flowout Summary"

    'Write values to flowout summary

    'Protect Flowout Summary worksheet
    wsURN.Protect "Flowout Summary", False, True, True, True, True

    Debug.Print "Before Save Update"

    'Save flowout summary
    Application.Workbooks(strFileName).Save

    Debug.Print "After Save Update"

    'Close Document Information Panel
    ActiveWorkbook.Application.DisplayDocumentInformationPanel = False

    'Turn on screen updating
    Application.ScreenUpdating = True

End Sub

问题详细信息: 当我创建一个新条目时,需要很长时间,我意外地发现主文档正在每个工作表激活事件中运行代码(如上所述)(我在其中一张工作表中有一个诊断消息框,当我创建了一个新条目) 因此,我得出的结论是,代码以某种方式激活了每个工作表,但不知道为什么......

任何帮助将不胜感激,如果我错过了任何可能有助于诊断的内容,请告诉我。

编辑:另一个奇怪的现象是,当我尝试单步执行代码以准确找到激活事件被触发的位置时,这种情况不会发生。

编辑:工作表中的代码激活事件

Private Sub Worksheet_Activate()

    'Turn off Screen Updating
    Application.ScreenUpdating = False

    'Simply writes data to the sheet (excluded because it is lengthy)

    'Turn on Screen Updating
    Application.ScreenUpdating = True

    wsMyCalls.Protect Password:=strPassword

    Debug.Print "wsMyCalls"

    MsgBox "This sheet uses your username to display any calls you own." & vbNewLine & _
    "It relies on the correct CDSID being entered for owner." & vbNewLine & vbNewLine & _
    "Regards" & vbNewLine & _
    "Your friendly spreadsheet administrator", vbOKOnly, "Information"

End Sub

编辑:我在代码中添加了一些 Debug.Prints(上面),这就是我得到的。

  • 创建另存为之前
  • 另存为创建后
  • 保存更新之前
  • 保存更新后
  • 拯救大师之前
  • 保存大师后
  • wsMyCalls

这表明代码正在 Debug.Print“After Save Master”和 End Sub 之间执行。里面没有代码???

谢谢

最佳答案

我相信我们在这里没有看到您的完整代码。考虑到我们没有自己调试的工作簿,很难诊断。但是,我有一个类似的“欢迎”页面,每次打开我的一本工作簿时都会显示该页面,要求用户激活宏。我确实将 EnableEvents 设置为 false,并在保存之前将工作表置于某种状态,并在保存后将其放回原处。

我将向您详细展示我是如何做到这一点的,因为我感觉您的问题与未在正确的时间禁用 EnableEvents 有关。由于提到的代码不完整,我不确定如何根据您的工作簿的功能来计时。

该工作表称为 f_macros。这是阻止进一步导航的工作表激活事件:

Private Sub Worksheet_Activate()
     ActiveWindow.DisplayHeadings = False
     ActiveWindow.DisplayWorkbookTabs = False
End Sub

在我的 Workbook_BeforeSave 中:

我首先记录 DisplayHeadings 的当前状态等:

Dim Displaytabs As Boolean
Dim DisplayHeadings As Boolean
Dim menu As CommandBar
Dim ligne As CommandBarControl

Displaytabs = ActiveWindow.DisplayWorkbookTabs
DisplayHeadings = ActiveWindow.DisplayHeadings

然后,我重置自定义右键单击,关闭 EnableEvents 和屏幕更新。为了更好地衡量,我将 DisplayWorkbookTabs 设置为 false。

Application.ScreenUpdating = False
Application.EnableEvents = False
Application.CommandBars("Cell").reset
ActiveWindow.DisplayWorkbookTabs = False

然后我运行 Cacherdata(HideData,下面附加的另一个模块中的子程序)保存,然后运行子 Macro_activees 以使工作簿恢复到用户的工作顺序。我重新打开 EnableEvents,并将标题恢复到原来的样子:

m_protection.Cacherdata
ThisWorkbook.Save
m_protection.macro_activees

Application.ScreenUpdating = True
Application.enableevents = True
ActiveWindow.DisplayWorkbookTabs = Displaytabs
ActiveWindow.DisplayHeadings = DisplayHeadings

我取消普通的保存(重要!)并指示工作簿已保存,以便他们可以正常退出而不会提示保存。

Cancel = True
ThisWorkbook.Saved = True

在BeforeClose中,它检查工作簿状态是否已保存。如果是,则退出。如果没有,它会执行类似的过程:

If Not (ThisWorkbook.Saved) Then


         rep = MsgBox(Prompt:="Save changes before exiting?", _
            Title:="---", _
            Buttons:=vbYesNoCancel)

    Select Case rep
        Case vbYes
            Application.ScreenUpdating = False
            Application.enableevents = False
            ActiveWindow.DisplayHeadings = True
            m_protection.Cacherdata

            ThisWorkbook.Save

        Case vbCancel
            Cancel = True
            Exit Sub
    End Select
End If

工作簿打开事件检查它是否是只读模式,但仅此而已。我没有 AfterSave 工作簿。

附件

CacherData 将每个工作表设置为 VeryHidden,这样用户就不会在不激活宏的情况下搞乱数据。它记录当前事件工作表,以便用户返回到原来的位置,取消对工作簿的保护,隐藏工作表,重新保护工作表,仅此而已:

Sub Cacherdata()
    Dim ws As Worksheet

    f_param.Range("page_active") = ActiveSheet.Name
    f_macros.Activate


    ThisWorkbook.Unprotect "-----"

    For Each ws In ThisWorkbook.Worksheets
        If ws.CodeName <> "f_macros" Then ws.visible = xlSheetVeryHidden
    Next
    ThisWorkbook.Protect "-----"

    Exit Sub

End Sub

macros_activees 的作用相反:

Sub macro_activees()
    Dim ws As Worksheet


    ThisWorkbook.Unprotect "-----"
    For Each ws In ThisWorkbook.Worksheets
        ws.visible = xlSheetVisible
    Next
    ThisWorkbook.Sheets(f_param.Range("page_active").Value).Activate
    ThisWorkbook.Unprotect "-----"
'it unportects twice because of the activate event of the worksheet, don't mind that
    Exit Sub
End Sub

错误处理已被删除,因为它对显示毫无用处,但其他所有内容都应该在那里。

编辑:如果这对您没有任何帮助,也许您的问题是因为您创建的工作簿中的代码(9据我收集)可能会影响运行代码所需的时间?如果他们自己有一个开放程序,可能就是这样吗?

关于VBA 不需要的工作表循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32245475/

相关文章:

arrays - 如何制作基于 1 索引的数组

c++ - 如何遍历 const 容器中的容器?

excel - 如何在不使用sendkeys的情况下登录网站?

arrays - VBA将数组缓慢写入Excel工作簿

运行宏后保存工作簿时 Excel 2007 崩溃

vba - 在 MS Word 中打印字体的所有字形

vba - 如何使用VBA将Excel中的数据以文本形式导出到Word

Excel - 查找列中的最大值

c - For 循环在 C 中产生意外结果

java - 如何在Android中获取HashMap在java上循环的内容?