Access「テーブル移行」按钮调查日志

| Work Notes | 1 Reads

摘要

本次调查对象是 Access 数据库 C:\Workspace_New\shori-jokyo-management-functions\処理状況等管理システム.accdb 中启动窗体 メインスイッチボード 上的按钮 テーブル移行

结论是:该按钮不是网页迁移时误造出来的,它是真实存在于 Access 窗体中的命令按钮。控件名为 dataConvert,标题为 テーブル移行。但是它不应该出现在普通第一画面中,因为原 Access 系统通过 autoexec 宏调用 proctest(),根据启动参数 Command 控制该按钮是否可见。

  • Command = 1 时,dataConvert.Visible = True,按钮显示。
  • Command 不是 1 时,dataConvert.Visible = False,按钮隐藏。
  • 普通启动 Access 时通常没有 /cmd 1 参数,所以原版第一画面不会显示该按钮。

该按钮有实际作用,而且是高风险维护功能:点击后会提示“全テーブルを削除します。よろしいですか?”,用户确认后会删除当前数据库中除 MSys 系统表以外的所有表,然后执行保存的导入任务 インポート-処理状況等管理システム(R020625) 重新导入数据。

网页迁移时的处理结论是:保留该按钮定义,但默认 visible: false,以匹配 Access 普通启动后的第一画面。

超具体的内容

1. 控件本身确实存在

通过 Access COM 打开数据库并枚举 メインスイッチボード 窗体控件后,确认存在如下控件:

Name        = dataConvert
Caption     = テーブル移行
ControlType = 104
Left        = 737
Top         = 8163
Width       = 1706
Height      = 397
OnClick     = [Event Procedure]

其中 ControlType = 104 表示 Access 的命令按钮。因此,テーブル移行 不是网页侧新增的按钮,而是原 Access 窗体中已有控件。

2. 为什么普通画面中不显示

数据库中存在 autoexec 宏。该宏启动时执行:

Action   = RunCode
Argument = proctest()

proctest() 位于标准模块 DataConvert,代码如下:

Option Compare Database

Function proctest()

    If Command = 1 Then
        Form_メインスイッチボード.dataConvert.Visible = True
    Else
        Form_メインスイッチボード.dataConvert.Visible = False
        
    End If

End Function

关键条件是 Command = 1。这对应 Access 启动参数。也就是说,只有类似下面这种启动方式才会显示按钮:

MSACCESS.EXE "処理状況等管理システム.accdb" /cmd 1

普通双击打开数据库,或没有指定 /cmd 1 时,Command 不等于 1,因此执行隐藏逻辑:

Form_メインスイッチボード.dataConvert.Visible = False

3. 按钮点击事件

dataConvert 的点击事件定义在 メインスイッチボード 窗体模块中:

Private Sub dataConvert_Click()

    If MsgBox("全テーブルを削除します。よろしいですか?", vbYesNo + vbExclamation + vbDefaultButton2, "データ取込") = vbYes Then
        Call FncDataConv
    End If
    
    Exit Sub
End Sub

点击按钮后,Access 先弹出确认框:

  • 消息:全テーブルを削除します。よろしいですか?
  • 标题:データ取込
  • 按钮:Yes / No
  • 默认按钮:No,因为使用了 vbDefaultButton2

只有用户选择 Yes 时,才会调用:

Call FncDataConv

4. FncDataConv 的核心逻辑

FncDataConv() 的核心代码如下:

Function FncDataConv()
On Error Resume Next
          
    Dim iCnt   As Integer         'レコード件数
    Dim Rst    As DAO.Recordset   'レコードセット
    Dim strSQL As String
          
    Dim var(10000) As String

    Dim dbs
    Dim i
    
    Set dbs = CurrentDb
    
    For i = dbs.TableDefs.Count - 1 To 0 Step -1
    
        If InStr(dbs.TableDefs(i).Name, "Msys") > 0 Then
    
        Else
             'テーブル削除
            dbs.TableDefs.Delete dbs.TableDefs(i).Name
            'var(i) = dbs.TableDefs(i).Name
        End If
    Next
    
    dbs.TableDefs.Refresh
    
    Set dbs = Nothing

    'データインポート
    Call FncDBImport

这段代码的实际行为非常明确:

  1. 取得当前数据库:Set dbs = CurrentDb
  2. 倒序遍历所有 TableDefs
  3. 如果表名包含 Msys,认为是系统表,跳过
  4. 否则执行 dbs.TableDefs.Delete dbs.TableDefs(i).Name 删除表
  5. 刷新表定义集合
  6. 调用 FncDBImport 执行数据导入

所以该按钮的实际作用不是普通“导入”,而是“删除所有非系统表后重新导入”。

5. FncDBImport 的实际导入任务

FncDBImport() 定义在标准模块 DBImport 中:

Option Compare Database

'------------------------------------------------------------
' DBImport
'
'------------------------------------------------------------
Function FncDBImport()
On Error GoTo FncDBImport_Err

    DoCmd.RunSavedImportExport "インポート-処理状況等管理システム(R020625)"


FncDBImport_Exit:
    Exit Function

FncDBImport_Err:
    MsgBox Error$
    Resume FncDBImport_Exit

End Function

实际执行的是 Access 保存的导入任务:

インポート-処理状況等管理システム(R020625)

这表示系统并不是在 VBA 中逐表写入导入逻辑,而是调用 Access 内部保存的 Import/Export 规范。

6. 完成后的统计和提示

导入完成后,FncDataConv() 会统计当前用户表数量:

strSQL = "SELECT Count(*) AS CNT FROM MSysObjects WHERE MSysObjects.Type=1 AND MSysObjects.Flags=0"

Set Rst = CurrentDb.OpenRecordset(strSQL)

iCnt = Rst![cnt]

随后显示完成消息:

MsgBox "データの取込を完了しました。" & vbCr & "テーブル移行件数は、" & iCnt & "件 です", vbInformation + vbOKOnly, "レコード移行"

显示内容为:

データの取込を完了しました。
テーブル移行件数は、{iCnt}件 です

7. 风险判断

该按钮是维护/迁移模式按钮,风险较高,原因如下:

  • 删除表阶段使用了 On Error Resume Next,错误可能被忽略。
  • 删除条件只排除了名称包含 Msys 的系统表。
  • 所有业务表、导入表、临时表,只要名称不包含 Msys,都会进入删除逻辑。
  • 删除后完全依赖保存的导入任务 インポート-処理状況等管理システム(R020625) 恢复数据。

8. 网页迁移处理

网页端应该模拟普通 Access 启动状态,也就是:

Form_メインスイッチボード.dataConvert.Visible = False

因此迁移后的网页实现保留按钮定义,但默认不渲染:

Button("テーブル移行", 737, 8163, 1706, 397, visible: false)

渲染按钮时只输出可见按钮:

@foreach (var button in Buttons.Where(button => button.Visible))
{
    <button type="button" class="@ButtonClass(button)" style="@ButtonStyle(button)">
        @HtmlText(button.Caption)
    </button>
}

这个处理同时满足两个目标:保留原 Access 系统中的真实维护功能信息,但普通第一画面不显示该维护按钮。

This article was last edited at