如何使用VBA代码满足以下条件?
我想避免在本问题的底部列出的尝试解决方案。
详细信息:
该工作簿是在Windows 7计算机上使用Office 2007创建的。它是一个包含2个工作表的.xlsm工作簿,“Scheduler”和“Info”。工作表标签不可见。并非所有用户都会在打开工作簿时启用宏。
打开工作簿后,用户将只能按如下方式显示在一个工作表中:
“Info”必须首先显示。
尝试解决方案(我正在寻找更好的解决方案!):
Workbook.BeforeSave
事件中放置代码。这会保存并激活“信息”,以便在打开工作簿时显示。但是,如果用户在“调度程序”中并且没有完成,我在此事件中找不到一种方法可以在保存后重新激活“调度程序”。Application.OnKey
重新映射 Ctrl - s 和 Ctrl - S 击键。不幸的是,这省去了使用鼠标保存的用户(单击文件...保存或Office按钮...保存)。Workbook.SheetActivate
或.SheetChange
事件中插入代码以将“计划程序”放回在激活“信息”保存后进入焦点。这会不断地运行VBA代码,这让我觉得这是让工作簿中的其他代码陷入麻烦的好方法。Worksheet("Info").Activate
事件,将焦点更改回“计划程序”。这导致“调度程序”的结果,而不是“信息”,显示工作簿何时打开,即使禁用了宏。答案 0 :(得分:5)
这不起作用吗? 已更新以便妥善保存
Private Sub Workbook_Open()
ThisWorkbook.Worksheets("Scheduler").Activate
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ThisWorkbook.Worksheets("Info").Activate
If (ShouldSaveBeforeClose()) Then
Me.Save
Else
Me.Saved = True ' Prevents Excel Save prompt.
End If
End Sub
Private Function ShouldSaveBeforeClose() As Boolean
Dim workbookDirty As Boolean
workbookDirty = (Not Me.Saved)
If (Not workbookDirty) Then
ShouldSaveBeforeClose= False
Exit Function
End If
Dim response As Integer
response = MsgBox("Save changes to WorkBook?", vbYesNo, "Attention")
ShouldSaveBeforeClose= (response = VbMsgBoxResult.vbYes)
End Function
答案 1 :(得分:4)
我没有时间对此进行测试,但您可以在BeforeSave事件处理程序中使用Application.OnTime
执行此操作。类似的东西:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim objActiveSheet
Set objActiveSheet = Me.ActiveSheet
If objActiveSheet Is InfoSheet Then Exit Sub
If Module1.PreviousSheet Is Nothing Then
Set Module1.PreviousSheet = objActiveSheet
InfoSheet.Activate
Application.OnTime Now, "ActivatePreviousSheet"
End If
End Sub
然后在Module1中:
Public PreviousSheet As Worksheet
Public Sub ActivatePreviousSheet()
If Not PreviousSheet Is Nothing Then
PreviousSheet.Activate
Set PreviousSheet = Nothing
End If
End Sub
答案 2 :(得分:1)
编辑2:这是一个不使用AfterSave的重写。您可能需要根据需要调整从GetSaveAsFilename创建的对话框。
这取决于覆盖默认保存行为并自行处理保存。
Private actSheet As Worksheet
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Cancel = True
PrepareForSave
manualSave SaveAsUI
AfterSave ThisWorkbook.Saved
End Sub
Private Sub PrepareForSave()
Set actSheet = ThisWorkbook.ActiveSheet
ThisWorkbook.Sheets("Info").Activate
hidesheets
End Sub
Private Sub manualSave(ByVal SaveAsUI As Boolean)
On Error GoTo SaveError 'To catch failed save as
Application.EnableEvents = False
If SaveAsUI Then
If Val(Application.Version) >= 12 Then
sPathname = Application.GetSaveAsFilename(FileFilter:="Excel Files (*.xlsm), *.xlsm")
If sPathname = False Then 'User hit Cancel
GoTo CleanUp
End If
ThisWorkbook.SaveAs Filename:=sPathname, FileFormat:=52
Else
sPathname = Application.GetSaveAsFilename(FileFilter:="Excel Files (*.xls), *.xls")
If sPathname = False Then
GoTo CleanUp
End If
ThisWorkbook.SaveAs Filename:=sPathname, FileFormat:=xlNormal
End If
Else
ThisWorkbook.Save
End If
SaveError:
If Err.Number = 1004 Then
'Cannot access save location
'User clicked no to overwrite
'Or hit cancel
End If
CleanUp:
Application.EnableEvents = True
End Sub
Private Sub AfterSave(ByVal bSaved As Boolean)
showsheets
If actSheet Is Nothing Then
ThisWorkbook.Sheets("Scheduler").Activate
Else
actSheet.Activate
Set actSheet = Nothing
End If
If bSaved Then
ThisWorkbook.Saved = True
End If
End Sub
Private Sub hidesheets()
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> "Info" Then
ws.Visible = xlVeryHidden
End If
Next
End Sub
Private Sub showsheets()
For Each ws In ThisWorkbook.Worksheets
ws.Visible = True
Next
End Sub
Private Sub Workbook_Open()
AfterSave True
End Sub
在没有启用宏的情况下首先显示Info
的唯一方法是,这是否保存了工作簿。这是保存时最合理的处理方式。
除非我误解了你的问题,否则不使用BeforeSave似乎是错误的。只需确保使用AfterSave。这是一个例子:
Private actSheet As Worksheet
Private Sub Workbook_AfterSave(ByVal Success As Boolean)
showsheets
actSheet.Activate
Set actSheet = Nothing
Thisworkbook.Saved = true 'To prevent save prompt from appearing
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Set actSheet = ThisWorkbook.activeSheet
ThisWorkbook.Sheets("Info").Activate
hidesheets
End Sub
Private Sub Workbook_Open()
showsheets
ThisWorkbook.Sheets("Scheduler").Activate
End Sub
Private Sub hidesheets()
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> "Info" Then
ws.Visible = xlVeryHidden
End If
Next
End Sub
Private Sub showsheets()
For Each ws In ThisWorkbook.Worksheets
ws.Visible = True
Next
End Sub
使用私有对象actSheet允许在保存后重新选择“ActiveSheet”。
编辑:我注意到您在评论中有更多要求。代码已更新,现在保存后,只有信息表可见,但在打开或保存后,每张工作表都会重新出现。
这使得任何打开没有宏的文件的用户都无法使用激活的其他工作表进行保存,甚至无法查看其他工作表。这肯定有助于激励他们启用宏!
答案 3 :(得分:1)
这个问题在过去已经被扼杀,很难找到真正有效的解决方案。看看这个代码应该做你需要的。基本上它显示一个启动画面,如果用户不启用宏,则隐藏所有其他工作表。如果用户点击保存并且不会干扰他们的工作,它仍将正常保存。如果他们保存并打开工作表,它将在下次打开时仍然只显示启动画面。下载下面的示例文件,您可以自己测试,确保下载Reafidy发布的文件,它有超过400个视图。如果您需要进一步修改,请告诉我。
Private Sub Workbook_BeforeClose(Cancel As Boolean)
bIsClosing = True
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim wsArray() As Variant
Dim iCnt As Integer
Application.ScreenUpdating = 0
Splash.Visible = True
For Each wsSht In ThisWorkbook.Worksheets
If Not wsSht.CodeName = "Splash" Then
If wsSht.Visible = True Then
iCnt = iCnt + 1: Redim Preserve wsArray(1 To iCnt)
wsArray(iCnt) = wsSht.Name
End If
wsSht.Visible = xlSheetVeryHidden
End If
Next
Application.EnableEvents = 0
ThisWorkbook.Save
Application.EnableEvents = 1
If Not bIsClosing Then
For iCnt = 1 To UBound(wsArray)
Worksheets(wsArray(iCnt)).Visible = True
Next iCnt
Splash.Visible = False
Cancel = True
End If
Application.ScreenUpdating = 1
End Sub
Private Sub Workbook_Open()
Dim wsSht As Worksheet
For Each wsSht In ThisWorkbook.Worksheets
wsSht.Visible = xlSheetVisible
Next wsSht
Splash.Visible = xlSheetVeryHidden
bIsClosing = False
End Sub
可以找到示例文件here.
答案 4 :(得分:1)
如何使用'代理工作簿'。
'代理工作簿'
'目标工作簿'
我手边没有Office 2007来测试它,但认为应该这样做。