2015-08-27 57 views
5

我已經使用了這個站點,但這是我發佈的第一個問題,希望我可以提供足夠的細節。我無法找到任何相關答案,因爲不管我搜索什麼,我都會得到與循環代碼有關的各種答案。VBA通​​過工作表的不需要的循環

一些背景: 我設計了一個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 

而只是爲了完整,這裏是項目文檔

'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 

的模塊1的所有號碼時在主創建項目使用'frmNewEntry'形式的信息被檢查並輸入到主文檔中,然後打開模板項目文檔並使用新的唯一文件名保存。然後,它不受保護,隨新信息更新,受保護,保存並關閉。然後保存主文檔。代碼如下(編輯省去冗長的格式和數據錄入):

表格代號:

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 

問題的細節: 當我創建一個新條目它走很長一段時間,我意外發現主文檔正在運行每個表單激活事件(上面提到的)中的代碼(我在創建新條目時神奇地出現了一個表單中的診斷msgbox) 因此,我得出結論,代碼是以某種方式激活每個工作表,但不知道爲什麼......

任何幫助將不勝感激,如果我錯過了任何可能有助於診斷讓我知道。

編輯:另一個奇怪的現象是,當我試圖通過代碼來確切地找到激活事件被觸發的位置時,這不會發生。

編輯:代碼工作表中的激活事件

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「保存主文件」和End Sub之間執行。那裏沒有代碼?

謝謝

+1

在將工作簿保存在代碼中之前,您需要禁用事件。 – Rory

+0

我想到了這一點,但這將意味着項目文檔被保存而不顯示警告表。我需要這些活動是積極的。編輯:這也是爲什麼我將ThisWorkbook.Worksheets添加到循環隱藏和顯示項目文檔中的工作表。 – Nervix

+0

然後,您需要在隱藏/顯示所有工作表之前更改其他代碼以禁用事件,然後重新啓用事件。 – Rory

回答

1

我相信我們在這裏看不到您的整個代碼。考慮到我們沒有工作簿來調試自己,所以很難診斷。但是,我有一個類似的「歡迎」頁面,每次打開一個工作簿時都會顯示該頁面,要求用戶激活宏。我將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 

打開工作簿時檢查是否是隻讀的模式,但僅此而已。我沒有Workbook AfterSave。

附件

CacherData使得每片VeryHidden所以用戶不˚F***了數據,而無需激活宏。所以用戶回到原來的位置,取消保護工作簿,隱藏表記錄了當前的活動表,保護它回來,這一切:

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從我收集),可以影響運行你的代碼需要多長時間?如果他們自己有一個Open程序,那可能嗎?

+0

對於沒有看到工作簿中的所有代碼,您是正確的。但是,我忽略的任何代碼不會執行,或者我已經解釋了爲什麼它丟失。 (例如,將值寫入主工作簿,因爲它很長並且不相關)至於你可以收集什麼,我不知道有什麼比我更好的解釋方式。我在模板/項目文檔(我創建的)中包含了工作簿打開事件中的代碼,請參見上文。 – Nervix