Excel只有在启用VBA时才可以保存文件,可能吗?

时间:2018-05-23 06:01:57

标签: excel vba excel-vba

我有一个我用三级权限制作的文件 系统会提示您在userform上输入密码,您将获得管理员权限,读/写权限或只有读取权限 除非您不启用宏,否则这样可以正常工作。

如果未启用宏提示,则不显示用户窗体且未设置权限,因此您具有完全访问权限。

我见过你可以使用启动画面,但为了工作,你需要保存工作簿,据我所知?
它们的基本概念是在关闭隐藏表并取消隐藏启动画面之前,然后保存工作簿。 但是,如果用户犯了一个错误并关闭了什么而没有保存并稍后重新打开怎么办?文件是否关闭,所有工作表都可见?

所以我想也许我可以使用“资源管理器 - >右键单击 - >属性 - >只读”属性作为额外的保护层吗?

我找到了这些功能。

ActiveWorkbook.ChangeFileAccess Mode:=xlreadonly
ActiveWorkbook.ChangeFileAccess Mode:=xlreadwrite 

但我尝试了readonly行,它确实设置了只读,无法保存文件 然后我关闭了工作簿而没有保存并再次打开。但似乎该属性未在文件的属性中设置,因为它没有标记,当我打开文件时我可以保存它。

还有其他方法可以解决这个问题吗? 我想对用户“强制”使用VBA,或者确保在没有VBA的情况下打开文件时他/她无法保存文件。

2 个答案:

答案 0 :(得分:2)

我找到了似乎有效的解决方案。

您可以在Workbook_BeforeClose中使用此行在文件属性中将文件设置为只读。

SetAttr Application.ActiveWorkbook.FullName, vbReadonly

这将在属性中设置tickmark,Excel将注意到该文件是写保护的。

然后在Workbook_Open() 中(或在我的情况下确定权利时)

SetAttr Application.ActiveWorkbook.FullName, vbReadwrite
ActiveWorkbook.ChangeFileAccess Mode:=xlReadWrite

第一行删除文件属性中的tickmark,但Excel仍然“记住”该文件为只读。
第二行将告诉Excel使其成为ReadWrite并且文件再次正常工作。

答案 1 :(得分:1)

这是Adreas'更复杂的方法,但不具备与温和技术娴熟的用户相同的风险,只需右键单击该文件并弹出“属性” “小组。

创建2个新工作表。其中一个设置为xlVeryHidden - 对于下面的示例,我将其称为hsSheetStatus。另一个,通过一个很好的通知告诉你的不幸的小兵同事启用宏,将改变可见性。我把这个称为hsEnableNotice

然后我有一个宏来显示hsEnableNotice隐藏所有其他工作表(在hsSheetStatus上存储它们的可见性和ActiveSheet),以及第二个宏来执行相反的操作(从中恢复可见性/ ActiveSheet hsSheetStatus)并将其设置为Workbook_BeforeSaveWorkbook_AfterSaveWorkbook_Open

Option Explicit

Private Sub Workbook_AfterSave(ByVal Success As Boolean)
    UnlockAndShow
End Sub

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

Private Sub Workbook_Open()
    UnlockAndShow
End Sub

Private Sub LockAndHide()
    Dim lSheet As Long, ActiveName As String
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    ActiveName = ThisWorkbook.ActiveSheet.Name
    hsEnableNotice.Visible = xlSheetVisible
    hsEnableNotice.Activate

    hsSheetStatus.Range(hsSheetStatus.Cells(1, 1), hsSheetStatus.Cells(hsSheetStatus.Rows.Count, 1)).EntireRow.Delete

    For lSheet = 1 To ThisWorkbook.Sheets.Count 'By using Sheets instead of Worksheets, we include Charts etc
        hsSheetStatus.Cells(lSheet, 1).Value = ThisWorkbook.Sheets(lSheet).Name
        hsSheetStatus.Cells(lSheet, 2).Value = ThisWorkbook.Sheets(lSheet).Visible
        If ThisWorkbook.Sheets(lSheet).Name = ActiveName Then hsSheetStatus.Cells(lSheet, 3).Value = 1
        If ThisWorkbook.Sheets(lSheet).Name <> hsEnableNotice.Name Then ThisWorkbook.Sheets(lSheet).Visible = xlSheetVeryHidden
    Next lSheet

    ThisWorkbook.Protect Password:="ThisIsMyPassword.ThereAreManyLikeIt,ButThisOneIsMine.", Structure:=True, Windows:=False
    Application.EnableEvents = True
End Sub

Private Sub UnlockAndShow()
    Dim WasSaved As Boolean, lSheet As Long, lMax As Long
    WasSaved = ThisWorkbook.Saved
    Application.ScreenUpdating = False
    Application.EnableEvents = False

    lMax = hsSheetStatus.Cells(hsSheetStatus.Rows.Count, 1).End(xlUp).Row

    ThisWorkbook.Unprotect Password:="ThisIsMyPassword.ThereAreManyLikeIt,ButThisOneIsMine."
    For lSheet = 1 To lMax
        ThisWorkbook.Sheets(hsSheetStatus.Cells(lSheet, 1).Value).Visible = hsSheetStatus.Cells(lSheet, 2).Value
        If hsSheetStatus.Cells(lSheet, 3).Value = 1 Then ThisWorkbook.Sheets(hsSheetStatus.Cells(lSheet, 1).Value).Activate
    Next lSheet

    hsSheetStatus.Visible = xlSheetVeryHidden
    hsEnableNotice.Visible = xlSheetVeryHidden

    Application.EnableEvents = True
    Application.ScreenUpdating = True
    ThisWorkbook.Saved = WasSaved
End Sub