-2

如何绕过 MSAccess autoexec 宏和启动表单,对具有数百个表单和报告的大型 MS Access 2003 应用程序进行深度遗留代码升级?

它是从 Access 2003 升级到 Access 2016、2019 或 365。

这是一个任务关键型系统,在没有任何 VBA 代码更新的情况下保持活力并依靠拐杖运行了 15 年。

  • 应用程序中的文件
    • MDB 和 ACCDB 格式的多个 MSAccess 文件
    • 没有带有已编译 VBA 代码的 MDE 或 ACCDE 格式的 MSAccess 文件
    • 没有 MSAccess 其他文件,例如 mdw 安全文件
  • 我为数据库运行一个 dos 命令 - PATH_TO_MSACCESS.exe DB_NAME.mdb
  • 我正在使用 Office 365 中的 32 位 MSAccess.exe。
    • 请注意,如果在 64 位 MSAccess.exe 上运行 VBA 调用 Windows 操作系统 Win32 API 方法,则会出现兼容性和 VBA 编译器错误。此应用程序调用了几 (5) 个 Win32 API 调用。从技术上讲,MS Access 64 位会将一些从 Win32 API 发送/返回的 32 位数据视为 64 位,从而导致错误。

最困难的部分是许多网页以及与此相关的几乎所有 Microsoft 页面都已从网络上删除。


  • 试过但没用
    • 打开 MSAccess 数据库时按住 shift 键
    • 按 F11 打开 Access 中的导航窗格(不打开)。如果导航窗格打开,我可以编辑 AutoExec 宏或启动表单的 Form_Open 代码
  • 尝试过,不完美,并且有效
    • 运行 MSAccess.exe 命令行上不存在的宏,在错误消息上多次单击转义,单击 MSAccess 功能区以获取 VBA 代码。凌乱,但它让我进入了 VBA 代码。
      • 添加了一个“Stop”作为名为“autoexec”的宏的第一行以及启动表单的“Form_Open()”方法的第一行。我必须为表单添加一个空的“Form_Open()”事件处理程序

当前状态:

  • 该应用程序在 2016 年之前使用 MS Access 版本的机器上运行正常
  • 当机器上仅安装 32 位 MS Access 365/2019 时,它会以多种方式失败。
    • 我一直在查找和修复错误的配置文件条目、不正确的安装路径等问题,但需要在 VBA 调试器中调试 VBA 启动代码和初始表单加载。
      • 我无法在 AutoExec 宏的第一行直接进入 VBA 调试器或启动表单的 Form_Open 函数。MSAccess 始终运行 autoexec 宏并显示启动窗体。
        • 我可以通过运行 MSaccess.exe 命令行并指定它运行一个不存在的宏来进入 VBA。

以下是基于 Google 搜索的可能解决方案,按 Access 版本细分,因为相关代码/数据库设置可能特定于 95 至 2010 年的任何 Access 版本。


Access 2007:从命令行打开 MS-Access 数据库而不运行任何启动 vba 代码? 打开MDB数据库时按住shift键


Access XP 无需执行脚本或表单即可打开访问数据库

  • 打开Access数据库时按住shift键
  • 删除 AutoExec 宏
  • 从数据库中删除启动表单设置

Access 2007: 使用 VBA 打开由 mdw 文件保护的 ms-access 数据库时模拟 SHIFT 键按下?

  • Access 数据库由 MDW 安全文件保护的情况略有不同
  • 相同的答案

访问 XP/2003/2007? 从 MSAccess 打开 MSAccess 时如何跳过 Autoexec 宏?

  • 方法一:
  • 方法二:
    • 从数据库中提取 Autoexec 宏,将其替换为空白 AutoExec 宏
    • 使用 DoCmd.DatabaseTransfer acImport 和 DoCmd.DatabaseTransfer acExport
  • 方法三:
    • 使用 VBA 代码重命名 AutoExec 宏
    • OpenCurrentDatabase(“您的数据库”)
    • DoCmd.Rename "Autoexec", acMacro, "tmp_Autoexec"
    • 关闭当前数据库

MS Access 键盘快捷键,用于获取 Access 数据库中的 VBA 代码或对象。从https://support.microsoft.com/en-us/office/keyboard-shortcuts-for-access-70a673e4-4f7b-4300-b8e5-3320fa6606e2 我没有尝试过 MSAccess 键盘快捷键,看看他们是否让我打开并查看 Access VBA 代码、工具栏、表格/表单设计查看器,或切换到代码编辑模式。为了完整起见,我将它们包括在这里。

  • F2 - 在数据表或设计视图中的编辑模式(显示插入点)和导航模式之间切换
  • F4 - 打开对象的属性窗格
  • F5 - 从表单设计视图切换到表单视图
  • F6 - 在 MS Access 界面中的窗格之间切换
  • F10 (?) 取消隐藏功能区
  • F11 - 显示或隐藏导航窗格
  • Alt-X、Alt-X、1 - 打开功能区中的外部数据选项卡
  • Alt-Y - 打开功能区中的数据库工具选项卡
  • Alt-J,T - 打开功能区中的表格选项卡
  • Alt-X,2 - 打开功能区中的加载项选项卡
  • Control-F1 - 展开/折叠功能区
  • Alt-F11 - 切换到/从 VBA 编辑器

在 VBA 代码中显示或隐藏 MSAccess 功能区工具栏。为了完整起见,包括在此处。此应用程序在应用程序启动时隐藏功能区栏。 MSAccess - 最小化工具栏功能区 OnLoad()?

  • MSAccess 2010 及更高版本。acToolbarNo 在此应用程序的 VBA 代码中
    • DoCmd.ShowToolbar "Ribbon", acToolbarNo '隐藏整个工具栏
    • DoCmd.ShowToolbar "Ribbon", acToolbarYes '显示
  • 2010 年,2013 年 MSACcess
    • CommandBars.ExecuteMso“最小化功能区”
  • 在 MSAccess 2010 之前
    • 发送键“^{F1}”,假

特殊情况:如果 Access 启动表单的记录源有错误,您可能会在 Access 启动表单上收到错误消息。这不是我的应用程序的情况,但包括在这里完整性 困难跟踪微软访问 VBA 代码


特殊情况:您从启动表单中获得无限循环的对话框提示或错误。按住“Control-Break”键,同时单击“确定”以使错误消息跳出错误循环。https://bettersolutions.com/vba/debugging/index.htm


通过右键单击启动表单的标题栏或右键单击启动表单的主体,可以将主启动表单中断到 MS Access 对象资源管理器。

  • 右键单击启动窗体的标题栏有这些菜单命令
    • 节省
    • 关闭并关闭所有
    • 表单视图
    • 布局视图
    • 设计视图
  • 右键单击启动窗体的主体有这些菜单命令
    • 表单视图
    • 布局视图
    • 设计视图
    • 剪切、复制、过去(禁用)
    • 表单属性(禁用)
    • 属性(已禁用)
4

6 回答 6

2

另一件事要检查?你在使用快捷方式吗?如果它有 /runtime 开关,那么无论您做什么,都会忽略 shift 键,即使没有 shfit 键旁路代码(禁用) shift 键也意味着 shift 键仍将被忽略。因此,您要确保不启动/使用快捷方式。

您还想检查/确保/了解/了解应用程序是否具有工作组安全性。同样,在 100 个案例中的 99 个中,快捷方式将显示这一点。

接下来:这是 mdb 还是 mde 文件?mde 文件是编译后的版本。不存在源代码,不能修改 mde。因此,再次确保您有一个用于前端的 mdb 文件,而不是 mde。如果你没有那个 mdb,那么你就有大麻烦了——你没有源代码。

您的帖子中包含所有这些信息,但您忽略了最重要的问题。那么,这是 mde 还是 mdb?你需要知道这一点。链接中是否指定了通常用于启动应用程序的工作组安全文件 (mdw)。如果涉及工作组安全,那么您使用的登录 id 可能会让您通过 shift 键,但是该用户可能没有被授予设计权限,因此此时,shify 键绕过将零使用进入代码。

我的意思是,启动您的 access 2016 或其他副本。然后尝试从该数据库导入对象。这样您就不必使用或担心 shfit 键,而是将表单、报告和代码简单地导入到全新的数据库中。

所以,另一个问题:不要费心启动应用程序——创建一个空白的新数据库,然后从现有数据库中导入——你能做到吗?(这样做不会复制原始数据库的 shift 键设置)。

于 2020-09-04T01:16:32.363 回答
1

MSAccess 命令行让您告诉它在启动时要执行什么宏。

我运行了以下 cmd.exe 命令行,它会生成多个错误,并允许您使用导航器进入 Access 数据库并进入 VBA 代码。不是最好的解决方案,而是一种可能性。

MSAccess.exe DB /X ADEEERETDEREAR

DB 是 Access 数据库的完整路径 ADEERETDEREAR 是一个不存在的宏

于 2020-09-03T23:46:28.393 回答
0

访问 2007? 如何在打开 MS Access DB 时禁用宏和启动值

访问 2003?

访问 2007:

访问 2010?

使用权 ?

使用权 ?

  • https://bytes.com/topic/access/answers/211664-programatically-set-startup-form
  • 猜测你可以在一个 Access 数据库中使用 VBA 来打开目标数据库
  • 获取启动表单的名称
  • 更改启动表单的名称,或者可能空白启动表单的名称
  • VBA 代码类似于 CurrentDB.Properties("StartupForm") = "MyForm"
  • 另一种猜测是在数据库属性中清除启动表单的名称
  • 同样可能适用于 autoexec 宏
于 2020-09-03T23:35:56.553 回答
0

访问 2010?

  • 在 VBA 代码中将启动表单重置为空

  • 2012 年的代码在这里:https ://www.tek-tips.com/viewthread.cfm?qid=1673392

  • 第一种方式

    Dim strOriginalForm as String
    Dim db as Database
    
    Sub RemoveStartup()
      Set db = OpenDatabase(yourdatabase)
      strOriginalForm = db.Properties("StartUpForm") 
      db.Properties("StartUpForm") = "(none)"
      db.Close
      set db = Nothing
    End Sub
    
    Sub ResetStartup()
      Set db = OpenDatabase(yourdatabase)
      db.Properties("StartUpForm") = strOriginalForm
      db.Close
      Set db = Nothing
    End Sub
    

第二种方式

Set prp = db.CreateProperty("AllowByPassKey", dbBoolean, True)
db.Properties.Append prp

第三种方法使用 - database.properties.delete propertyname 删除属性

存在来自同一页面的更完整示例。

于 2020-09-03T23:40:40.227 回答
0

访问 2010?

上面提到的第四种方式

来自同一页面的更完整示例。

Public Sub GetCBs()
Dim db As DAO.Database
Dim strPath As String
Dim startUpform As String
Dim app As Access.Application
Dim custBars As Collection
Dim custShortCutBars As Collection
Dim custNonShortCutBars As Collection
Dim i As Integer
Dim blnAutoexec As Boolean
strPath = GetOpenFile()
'Get the db without opening in application
Set db = getDb(strPath)
'Get startupform
startUpform = getStartUp(db)
'Turn off the start up form
TurnOffStartUp db
'Check for and auto exec. If exists import and replace
If hasAutoexec(db) Then
blnAutoexec = True
ImportAutoExec (strPath)
End If
Set app = New Access.Application
'Open safely
app.OpenCurrentDatabase (strPath)
'Read command bars
Set custBars = getCustBars(app)
Set custShortCutBars = getCustShortCutBars(app)
Set custNonShortCutBars = getCustNonShortCutBars(app)
app.CloseCurrentDatabase
Set db = app.CurrentDb
Set db = getDb(strPath)
'Return start up form
TurnOnStartUp db, startUpform
db.Close
'Return auto exec
If blnAutoexec Then
    ReturnAutoExec (strPath)
End If
Debug.Print "all custom bars:"
'All bars
For i = 1 To custBars.Count
    Debug.Print custBars(i)
Next i
'Do something with the command bars
Debug.Print "all shortcut bars:"
'Short cut only
For i = 1 To custShortCutBars.Count
    Debug.Print custShortCutBars(i)
Next i
'Not short cut
Debug.Print "Non shortCut"
For i = 1 To custNonShortCutBars.Count
    Debug.Print custNonShortCutBars(i)
Next i
End Sub

Public Function getDb(strPath As String) As DAO.Database
Set getDb = DBEngine(0).OpenDatabase(strPath)
End Function

Public Function getCustBars(app As Access.Application) As Collection
' all bars
Dim col As New Collection
Dim cb As Object
For Each cb In app.CommandBars
    If cb.BuiltIn = False Then
        col.Add (cb.Name)
    End If
Next cb
Set getCustBars = col
End Function

Public Function getCustShortCutBars(app As Access.Application) As Collection
' only short cut bars
Dim col As New Collection
Dim cb As commandbar
For Each cb In app.CommandBars
    If cb.BuiltIn = False Then
    If cb.Type = msoBarTypePopup Then
        col.Add (cb.Name)
    End If
    End If
Next cb
Set getCustShortCutBars = col
End Function

Public Function getCustNonShortCutBars(app As Access.Application) As Collection
' Menu bars that are not shortcut bars
Dim col As New Collection
Dim cb As commandbar
For Each cb In app.CommandBars
    If cb.BuiltIn = False Then
    If cb.Type <> msoBarTypePopup Then
        col.Add (cb.Name)
    End If
    End If
Next cb
Set getCustNonShortCutBars = col
End Function

Public Function getStartUp(db As DAO.Database) As String
Dim prp As DAO.Property
For Each prp In db.Properties
    If prp.Name = "startupform" Then
    getStartUp = prp.Value
    Exit For
    End If
Next
End Function

Public Sub TurnOffStartUp(db As DAO.Database)
Dim prp As DAO.Property
For Each prp In db.Properties
    If prp.Name = "startupform" Then
        prp.Value = "(None)"
    Exit For
    End If
Next
End Sub

Public Sub TurnOnStartUp(db As DAO.Database, strFrm As String)
Dim prp As DAO.Property
For Each prp In db.Properties
    If prp.Name = "startupform" Then
    prp.Value = strFrm
    Exit For
    End If
Next
End Sub

Public Sub ImportAutoExec(strPath As String)
    On Error GoTo errLbl
    DoCmd.TransferDatabase acImport, "Microsoft Access", strPath, acMacro, "AutoExec", "AutoExecBackup"
    DoCmd.TransferDatabase acExport, "Microsoft Access", strPath, acMacro, "TempAutoExec", "AutoExec"
    Exit Sub
errLbl:
If Err.Number = 7874 Then
        Debug.Print "Auto Exec macro does not exist"
    Else
    MsgBox Err.Number & " " & Err.Description
    End If
End Sub

Public Sub ReturnAutoExec(strPath As String)
On Error GoTo errLbl
    DoCmd.TransferDatabase acExport, "Microsoft Access", strPath, acMacro, "AutoExecBackup", "AutoExec"
    DoCmd.DeleteObject acMacro, "AutoExecBackup"
    Exit Sub
errLbl:
If Err.Number = 7874 Then
        Debug.Print "Auto Exec macro does not exist"
    Else
    MsgBox Err.Number & " " & Err.Description
    End If
End Sub

Public Function hasAutoexec(db As DAO.Database) As Boolean
Dim rs As DAO.Recordset
Dim strSql As String
strSql = "SELECT MSysObjects.Name FROM MSysObjects WHERE MSysObjects.Name = 'AutoExec' AND MSysObjects.Type = -32766"
Set rs = db.OpenRecordset(strSql)
If Not (rs.EOF And rs.BOF) Then
    hasAutoexec = True
End If
End Function

于 2020-09-04T18:06:32.580 回答
0

我没有尝试将 Access 对象导入新数据库。(感谢 Albert Kalal 提供的信息)

这将允许我查看 VBA 代码。它可能无法替代具有数据库内部所有设置的原始数据库。

如何从另一个 Access 数据库导入 Access 对象:https: //support.microsoft.com/en-us/office/import-database-objects-into-the-current-access-database-23aea08b-7487-499d-bdce -0c76bedacfdd

  • Access 365 步骤(可能适用于 Access 2016)
  • 功能区中的外部数据选项卡
  • 单击导入和链接功能区组中的新数据源 -> 从数据库 -> 访问
  • 获取外部数据 - 显示访问数据库窗口
  • 在文件名字段中浏览 MSAccess 数据库 MDB 或 ACCDB 文件
  • 显示导入对象窗口
  • 选择要导入的表、查询、表单、报表宏、模块
  • 在选项按钮对话框中,您可以选择要导入的菜单、工具栏等
  • 点击确定
  • 对于重复的名称,Access 将在导入对象名称的末尾附加 1、2、3
于 2020-09-04T17:50:37.953 回答