删除 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
的输出)-它要更新什么列数据类型?
我需要清理一个定期接收的 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
的输出)-它要更新什么列数据类型?