简体   繁体   English

带有SendKeys的VBA项目密码保护无法正常工作

[英]VBA Project Password-Protect with SendKeys not Working Correctly

I've spent the last two days working on this problem. 我花了最后两天的时间来解决这个问题。 Most of the content I've found on this topic doesn't address the issue I'm having, so I'm hopeful that someone here can help me. 我在该主题上找到的大多数内容都无法解决我遇到的问题,因此我希望这里有人可以帮助我。

I've been working on some code that does the following from a "master scorecard" workbook: 我一直在研究一些代码,这些代码可以从“主记分卡”工作簿中执行以下操作:

  1. Takes each "student" sheet in the workbook and copies the sheet into a new workbook, 获取工作簿中的每个“学生”工作表,然后将其复制到新的工作簿中,
  2. Does a few minor manipulations of the new workbook, 对新工作簿做了一些小的操作,
  3. Imports a module of code into the new workbook, 将代码模块导入新工作簿中,
  4. Adds a Workbook_Open event and a Workbook_BeforeClose event to the new workbook (to make certain sheets xlVeryHidden depending on level of access), Workbook_Open事件和Workbook_BeforeClose事件添加到新工作簿中(根据访问级别将某些工作表设为xlVeryHidden ),
  5. Runs a subprocedure from the newly imported module, 从新导入的模块运行子过程,
  6. Saves and closes the workbook. 保存并关闭工作簿。

Each scorecard uses code to ensure that only the person whose name is on the scorecard can access it. 每个计分卡都使用代码来确保只有名称在计分卡上的人才能访问它。 I've used Environ("username") in the workbook events to ensure security, but as you well know, if one and understands how to run macros, he/she could merely open the VBEditor and unhide the xlVeryHidden sheets in the workbook very easily. 我已经在工作簿事件中使用Environ("username")来确保安全性,但是众所周知,如果一个人知道如何运行宏,他/她只能打开VBEditor并取消隐藏工作簿中的xlVeryHidden工作表。容易。

So, my thought was to password protect the new workbook's VBAProject programmatically (see above: step number five). 因此,我的想法是以编程方式用密码保护新工作簿的VBAProject (请参见上文:第五步)。 I found a few sources online of how to use SendKeys to achieve this goal (see below), but SendKeys is unreliable (at best) and isn't cooperating with my code. 我在线上找到了一些有关如何使用SendKeys实现此目标的资源(请参阅下文),但是SendKeys不够可靠(充其量),并且与我的代码不配合。 The code works like a charm if I run it by itself, but if I call it from another project using Run Macro:="filename!macroname" it doesn't set the protection. 如果我自己运行该代码,则它的工作方式就像一个Run Macro:="filename!macroname" ,但是如果我使用Run Macro:="filename!macroname"从另一个项目中调用它,则不会设置保护。 After the code has run and all the workbooks have been created, the VBAProject properties window(s) from the earlier code are all open and try to execute at the same time which crashes Excel. 运行代码并创建所有工作簿后,先前代码中的VBAProject属性窗口将全部打开,并尝试同时执行,这会使Excel崩溃。

Sub LockVBAProject()

Const VBAProjectPassword As String = "123"
Dim VBP As VBProject, openWin As VBIDE.Window
Dim wbActive As Workbook
Dim i As Integer
    Set wbActive = ActiveWorkbook
    Set VBP = wbActive.VBProject
    Application.ScreenUpdating = False
        ' close any code windows to ensure we hit the right project
        For Each openWin In VBP.VBE.Windows
            If InStr(openWin.Caption, "(") > 0 Then openWin.Close
        Next openWin
        wbActive.Activate
With Application
    '//execute the controls to lock the project\\
    .VBE.CommandBars("Menu Bar").Controls("Tools") _
        .Controls("VBAProject Properties...").Execute
    '//activate 'protection'\\
    .SendKeys "^{TAB}"
    '//CAUTION: this either checks OR UNchecks the\\
    '//"Lock Project for Viewing" checkbox, if it's already\\
    '//been locked for viewing, then this will UNlock it\\
    .SendKeys "{ }"
    '//enter password\\
    .SendKeys "{TAB}" & VBAProjectPassword
    '//confirm password\\
    .SendKeys "{TAB}" & VBAProjectPassword
    '//scroll down to OK key\\
    .SendKeys "{TAB}"
    '//click OK key\\
    .SendKeys "{ENTER}"
    'the project is now locked - this takes effect
    'the very next time the book's opened...
    End With


ThisWorkbook.SaveAs Filename:=Sheets(Sheets.Count).Name, FileFormat:=xlOpenXMLWorkbookMacroEnabled

Debug.Print "It Worked " & Now()

End Sub

I'm not sure why this is happening; 我不确定为什么会这样。 like I said, the code works fine when run on its own. 就像我说的那样,代码单独运行时效果很好。 I found this post where this link to a non- SendKeys approach was outlined, but it was written several years ago and I'm not sure how I'd need to modify it for my purposes since I've never coded in VB6... 我找到了这篇文章 ,其中概述了与非SendKeys方法的链接 ,但是它是几年前编写的,由于我从未在VB6中编写过代码,因此我不确定出于我的目的需要对其进行修改。 。

Are there any thoughts as to why the SendKeys method is bunching up after the code has already run instead of executing when it's supposed to during the code? 关于为什么在代码已经运行之后而不是在代码执行期间应该执行的情况下,为什么SendKeys方法会堆积起来,是否有任何想法? Should I abandon SendKeys in favor of this other method? 我应该放弃SendKeys来支持其他方法吗? I'm at a loss, so any help will be much appreciated! 我很茫然,所以任何帮助将不胜感激!

EDIT: I think the reason the code isn't working is because the correct project isn't activated at the time the SendKeys code is executed. 编辑:我认为代码不起作用的原因是因为执行SendKeys代码时未激活正确的项目。 I had hoped that activating the proper workbook would solve the issue, but it doesn't appear to have helped. 我曾希望激活适当的工作簿能够解决此问题,但似乎没有帮助。

Ok, so after another couple of hours of searching the web for alternative methods to achieve my goal, I stumbled across this post . 好的,因此在经过两个小时的网络搜索以实现我的目标的替代方法之后,我偶然发现了这篇文章

I created a template workbook (with the event code already in ThisWorkbook ), password protected the project, and modified my code to use the template workbook for each new sheet. 我创建了一个模板工作簿(事件代码已经在ThisWorkbook ),用密码保护了该项目,并修改了我的代码以将模板工作簿用于每个新工作表。 Now when the sheets are created, the project is already locked for viewing and requires a password. 现在,在创建图纸后,该项目已被锁定以供查看,并且需要密码。 While I realize the security under this approach isn't very secure, it will help "keep honest people honest" as they say. 尽管我意识到这种方法下的安全性不是很安全,但可以帮助他们“诚实地诚实”。

For those who stumble across this post and still wish to programmatically lock/unlock their VBA Project, see these resources: 对于那些偶然发现这篇文章但仍希望以编程方式锁定/解锁其VBA项目的人,请参阅以下资源:

This SO post 这样的帖子
This blog 这个博客

Both are great resources that walk through a way to do it in VBA. 两者都是很好的资源,它们都介绍了在VBA中进行操作的方法。

To add a nuance to the otherwise fine piece of code originally posted here: If you change the Project Name for the workbook within the VBE, you'll need to change one line of code to: 要为原本发布在此处的精美代码增加一些细微差别:如果您在VBE中更改工作簿的项目名称,则需要将一行代码更改为:

   .VBE.CommandBars("Menu Bar").Controls("Tools") _
        .Controls(VBP.Name & " Properties...").Execute

(sigh) (叹)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM