删除 Access 数据库中所有表的所有字符串字段中的所有控制字符

Remove All Control Characters In All String Fields In All Tables In Access Database

我需要清理一个定期接收的 Access 数据库,以便它的所有 table 可以导出到 "clean" CSV,然后由 Base SAS 通过 PROC IMPORT 导入。

我没有使用 Access VBA 或一般编程的经验,但我尝试 kitbash 一个脚本来遍历每个 table 中的每个字段并替换某些字符。它似乎不起作用,并且在 运行 时出现了几个 "Type Conversion Failure" 错误。

Public Sub ReplaceCharAllTables()

Dim strSQL As String
Dim fld As DAO.Field
Dim db As DAO.Database

Set db = CurrentDb()

Dim obj As AccessObject, dbs As Object
Set dbs = Application.CurrentData



' Cycle through all tables in database
For Each obj In dbs.AllTables

    ' Cycle through all fields in the table
    For Each fld In db.TableDefs("[" & obj.Name & "]").Fields

        If fld.Type = dbText And Not IsNull(fld) Then

            strSQL = "Update [" & obj.Name & "] Set [" & fld.Name & "]= Replace([" & fld.Name & "],Chr(10),'. ')"
            DoCmd.RunSQL strSQL

            strSQL = "Update [" & obj.Name & "] Set [" & fld.Name & "]= Replace([" & fld.Name & "],Chr(13),'. ')"
            DoCmd.RunSQL strSQL

        End If

    Next

Next obj

End Sub

请注意,此特定代码当前仅尝试删除两个字符。这只是一个临时试验台。

编辑 2016.11.30:只想说安德烈的解决方案是完美的。我最终需要做一些小的调整,特别是除了文本字段之外还要查看 "memo" 字段,并将有用的调试信息写入文本文件而不是大小受限的立即 Window.循环遍历一组字符代码看似很聪明。

Public Sub ReplaceCharAllTables()

Dim strSQL As String
Dim fld As DAO.Field
Dim db As DAO.Database
Dim td As DAO.TableDef
Dim strFld As String
Dim arCharCodes As Variant
Dim code As Variant
Dim strFolder As String
Dim n As Integer
Dim strUpdate As String

' Get stuff setup save debug.print log file
strFolder = Application.CurrentProject.Path & "\" & Application.CurrentProject.Name & "_RemoveCharLog.txt"
n = FreeFile()
Open strFolder For Output As #n

' all charcodes to replace
arCharCodes = Array(10, 13, 44)

Set db = CurrentDb()

' Cycle through all tables in database
For Each td In db.TableDefs

    ' Ignore system tables
    If Not (td.Name Like "MSys*" Or td.Name Like "USys*") Then

        ' Cycle through all fields in the table
        For Each fld In td.Fields

            If fld.Type = dbText Or fld.Type = dbMemo Then       ' Check if field is text or memo

                ' Cycle through all character codes to remove
                For Each code In arCharCodes

                    strFld = "[" & fld.Name & "]"

                    strSQL = "UPDATE [" & td.Name & "] " & _
                             "SET " & strFld & " = Replace(" & strFld & ", Chr(" & code & "), '. ') " & _
                             "WHERE " & strFld & " LIKE '*" & Chr(code) & "*'"

                    db.Execute strSQL
                    strUpdate = "Updated " & db.RecordsAffected & " records."

                    'Start printing logs
                    Debug.Print strSQL
                    Debug.Print strUpdate

                    Print #n, strSQL
                    Print #n, strUpdate

                Next code

            End If

        Next fld

    End If

Next td

End Sub

据我所知,原则上您的代码没有任何问题。主要问题可能是它还尝试更新所有系统 tables - 在导航窗格的导航选项中检查 "System objects" 以查看它们。
他们以 MSys 或 USys 开头。

其他一些需要改进的地方:

  • 无论如何你都需要 TableDef 对象,所以你可以直接循环它们而不是 AllTables
  • table 字段不能为 Null,因此不需要此检查
  • 为了提高效率,您只想更新列实际包含搜索字符的行,因此我添加了一个 WHERE 子句
  • 为避免重复代码,将所有要替换的字符代码放在一个数组中以进行额外循环。
  • 使用 db.Execute 而不是 DoCmd.RunSQL:它避免了对 DoCmd.SetWarnings False 的需要,并为您提供受影响的记录数。

我的建议:

Public Sub ReplaceCharAllTables()

    Dim strSQL As String
    Dim fld As DAO.Field
    Dim db As DAO.Database
    Dim td As DAO.TableDef
    Dim strFld As String
    Dim arCharCodes As Variant
    Dim code As Variant

    ' all charcodes to replace
    arCharCodes = Array(10, 13)

    Set db = CurrentDb()

    ' Cycle through all tables in database
    For Each td In db.TableDefs

        ' Ignore system tables
        If Not (td.Name Like "MSys*" Or td.Name Like "USys*") Then

            ' Cycle through all fields in the table
            For Each fld In td.Fields

                If fld.Type = dbText Then

                    For Each code In arCharCodes

                        strFld = "[" & fld.Name & "]"

                        strSQL = "UPDATE [" & td.Name & "] " & _
                                 "SET " & strFld & " = Replace(" & strFld & ", Chr(" & code & "), '. ') " & _
                                 "WHERE " & strFld & " LIKE '*" & Chr(code) & "*'"
                        Debug.Print strSQL

                        db.Execute strSQL
                        Debug.Print "Updated " & db.RecordsAffected & " records."

                    Next code

                End If

            Next fld
        End If
    Next td

End Sub

如果仍然报错,检查具体的SQL(Ctrl+g显示Debug.Print的输出)-它要更新什么列数据类型?