当前位置: 首页 > news >正文

VBA 中使用 ADODB 操作 SQLite 插入中文乱码问题

问题

使用 VBA 的 ADODB 对象的 command 对象、parameter 对象,插入的中文数据为乱码

使用的 ODBC 驱动(需要梯子才能下载)

http://www.ch-werner.de/sqliteodbc/

基础配置

  1. 在 VBA 代码编辑器中,点击“工具” --> “引用”在这里插入图片描述

  2. 勾选 ActiveX Data Object (若有多个版本建议选最新的) 、Scripting Runtime在这里插入图片描述

示例代码

Function demo(dbPath as string) As BooleanOn Error GoTo errorHandler' 初始化变量Dim conn As ADODB.ConnectionDim cmd As ADODB.CommandDim wb As WorkbookDim ws As WorksheetDim lastrow As LongDim stationName As String' ------------------------------- 业务相关逻辑 ------------------------------- ' 打开工作簿,工作簿文件绝对路径(包含文件名+后缀) = FilePathSet wb = Workbooks.Open(FilePath, ReadOnly:=True)' 获取第二个sheetSet ws = wb.Worksheets(2)stationName = ws.Name'获取表格行数lastrow = ws.Cells(ws.Rows.count, "C").End(xlUp).row'总数减去标题行totalCount = lastrow - 2' ---------------------------- 业务相关逻辑 - 结束 ---------------------------- ' 建立连接' dbpath = SQLite 数据库文件的绝对路径Set conn = New ADODB.Connectionconn.Open "DRIVER={SQLite3 ODBC Driver};Database=" & dbPath & ""' 建立指令对象Set cmd = New ADODB.Command' 指令语句 ? 为占位符,之后调用 parameter 方法进行替换sql = "INSERT INTO devList (deviceNumber, deviceIdentifier, deviceChineseName, " & _"deviceDrawingCode, moduleBoxNumber, stationName) VALUES (?, ?, ?, ?, ?, ?)"With cmd.ActiveConnection = conn.CommandText = sql.CommandType = adCmdText' 数据集对象:清除之前的参数While .Parameters.count > 0.Parameters.Delete 0Wend'创建参数域.Parameters.Append .CreateParameter("p1", adVarChar, adParamInput, 255, "P1")  'C  设备编号.Parameters.Append .CreateParameter("p2", adVarChar, adParamInput, 255, "P2")  'G  设备标识.Parameters.Append .CreateParameter("p3", adVarChar, adParamInput, 255, "P3")  'J  设备中文名.Parameters.Append .CreateParameter("p4", adVarChar, adParamInput, 255, "P4")  'L  设备图纸代码.Parameters.Append .CreateParameter("p5", adVarChar, adParamInput, 255, "P5")  'N  模块箱编号.Parameters.Append .CreateParameter("p6", adVarChar, adParamInput, 255, "P6")  '站点名.Parameters.Append .CreateParameter("p7", adVarChar, adParamInput, 255, "P7")  'H  设备安装分区End With' 开启事务,批量插入conn.BeginTrans' 各行数据批量插入For i = 3 To lastrow' ------------------------------- 业务相关逻辑 --------------------------' 每行各列数据与数据集对象绑定cmd("p1") = CStr(ws.Cells(i, "C").Value)cmd("p2") = CStr(ws.Cells(i, "G").Value)cmd("p3") = CStr(ws.Cells(i, "J").Value)cmd("p4") = CStr(ws.Cells(i, "L").Value)cmd("p5") = CStr(ws.Cells(i, "N").Value)cmd("p6") = stationName' ---------------------------- 业务相关逻辑 - 结束 ----------------------' 执行插入cmd.ExecuteprogressCount = progressCount + 1Application.StatusBar = "处理进度... " & progressCount & "/" & totalCountDoEventsNext i'提交事务conn.CommitTranserrorHandler:demo_dbProcess = FalseMsgBox "数据导入 SQLite 错误:" & Err.Description, vbCritical'回滚 -> 数据库断开 -> 对象释放If Not conn Is Nothing Thenconn.RollbackTransIf conn.State = adStateOpen Thenconn.CloseEnd IfSet conn = NothingEnd IfExit FunctionCleanup:'正常执行完成的清理工作demo_dbProcess = Trueconn.CloseSet conn = NothingIf Not wb Is Nothing Then wb.Close FalseApplication.StatusBar = False
End Function

插入时发现中文变成了乱码

问题解决

使用 SQLite ODBC 注意以下问题,才能防止中文等非英文字符操作错误

  1. 在 ODBC 连接字中使用以下参数

    1. OEMCP=1:数据库驱动会自动处理字符的编码,保证写入正确
    2. NOWCHAR=0:(这是驱动的默认值,可以不加)设置允许使用 WCHAR 数据类型,保证上面插入的数据在 SQLite 中显示正确
    3. 最终的连接字如下
      "DRIVER={SQLite3 ODBC Driver};Database=<数据库路径>;OEMCP=1;"
      
  2. ADODB 的 parameter 对象,对应 SQLite 中 varchar 类型的变量,应定义为宽字型adVarWChar而不是adVarChar,保证 parameter 对象传入驱动的数据字符是正确的

    .Parameters.Append .CreateParameter("p1", adVarWChar, adParamInput, 255, "P1")  
    .Parameters.Append .CreateParameter("p2", adVarWChar, adParamInput, 255, "P2") 
    .Parameters.Append .CreateParameter("p3", adVarWChar, adParamInput, 255, "P3") 
    .Parameters.Append .CreateParameter("p4", adVarWChar, adParamInput, 255, "P4")  
    .Parameters.Append .CreateParameter("p5", adVarWChar, adParamInput, 255, "P5")  
    .Parameters.Append .CreateParameter("p6", adVarWChar, adParamInput, 255, "P6") 
    .Parameters.Append .CreateParameter("p7", adVarWChar, adParamInput, 255, "P7")
    

上面的示例代码改进后如下

Function demo_dbProcess(dbPath as string) As Boolean' 初始化变量Dim conn As ADODB.ConnectionDim cmd As ADODB.CommandDim wb As WorkbookDim ws As WorksheetDim lastrow As LongDim stationName As String' ------------------------------- 业务相关逻辑 ------------------------------- ' 打开工作簿,工作簿文件绝对路径(包含文件名+后缀) = FilePathSet wb = Workbooks.Open(FilePath, ReadOnly:=True)' 获取第二个sheetSet ws = wb.Worksheets(2)stationName = ws.Name'获取表格行数lastrow = ws.Cells(ws.Rows.count, "C").End(xlUp).row'总数减去标题行totalCount = lastrow - 2' ---------------------------- 业务相关逻辑 - 结束 ---------------------------- ' 建立连接' dbpath = SQLite 数据库文件的绝对路径Set conn = New ADODB.Connectionconn.Open "DRIVER={SQLite3 ODBC Driver};Database=" & dbPath & ";OEMCP=1;"' 建立指令对象Set cmd = New ADODB.Command' 指令语句 ? 为占位符,之后调用 parameter 方法进行替换sql = "INSERT INTO devList (deviceNumber, deviceIdentifier, deviceChineseName, " & _"deviceDrawingCode, moduleBoxNumber, stationName) VALUES (?, ?, ?, ?, ?, ?)"With cmd.ActiveConnection = conn.CommandText = sql.CommandType = adCmdText' 数据集对象:清除之前的参数While .Parameters.count > 0.Parameters.Delete 0Wend'创建参数域.Parameters.Append .CreateParameter("p1", adVarWChar, adParamInput, 255, "P1")  'C  设备编号.Parameters.Append .CreateParameter("p2", adVarWChar, adParamInput, 255, "P2")  'G  设备标识.Parameters.Append .CreateParameter("p3", adVarWChar, adParamInput, 255, "P3")  'J  设备中文名.Parameters.Append .CreateParameter("p4", adVarWChar, adParamInput, 255, "P4")  'L  设备图纸代码.Parameters.Append .CreateParameter("p5", adVarWChar, adParamInput, 255, "P5")  'N  模块箱编号.Parameters.Append .CreateParameter("p6", adVarWChar, adParamInput, 255, "P6")  '站点名.Parameters.Append .CreateParameter("p7", adVarWChar, adParamInput, 255, "P7")  'H  设备安装分区End With' 开启事务,批量插入conn.BeginTrans' 各行数据批量插入For i = 3 To lastrow' ------------------------------- 业务相关逻辑 ------------------------------- ' 每行各列数据与数据集对象绑定cmd("p1") = CStr(ws.Cells(i, "C").Value)cmd("p2") = CStr(ws.Cells(i, "G").Value)cmd("p3") = CStr(ws.Cells(i, "J").Value)cmd("p4") = CStr(ws.Cells(i, "L").Value)cmd("p5") = CStr(ws.Cells(i, "N").Value)cmd("p6") = stationName' ---------------------------- 业务相关逻辑 - 结束 ---------------------------- ' 执行插入cmd.Execute'进度输出progressCount = progressCount + 1Application.StatusBar = "处理进度... " & progressCount & "/" & totalCountDoEventsNext i'提交事务conn.CommitTranserrorHandler:demo_dbProcess = FalseMsgBox "数据导入 SQLite 错误:" & Err.Description, vbCritical'回滚 -> 数据库断开 -> 对象释放If Not conn Is Nothing Thenconn.RollbackTransIf conn.State = adStateOpen Thenconn.CloseEnd IfSet conn = NothingEnd IfExit FunctionCleanup:'正常执行完成的清理工作demo_dbProcess = Trueconn.CloseSet conn = NothingIf Not wb Is Nothing Then wb.Close FalseApplication.StatusBar = False
End Function

文章转载自:

http://pgF9To0J.hpgdz.cn
http://WmBb4kUI.hpgdz.cn
http://XD5yBahn.hpgdz.cn
http://anzgDPbF.hpgdz.cn
http://BM02jCg6.hpgdz.cn
http://jvek6fpI.hpgdz.cn
http://bxyrUMXX.hpgdz.cn
http://s1FKaUJf.hpgdz.cn
http://r4G3qgIX.hpgdz.cn
http://b4XNvf1G.hpgdz.cn
http://CM7GxeBL.hpgdz.cn
http://lhRgEncL.hpgdz.cn
http://Jy93CA56.hpgdz.cn
http://3nAYWZkZ.hpgdz.cn
http://PBJDHgdk.hpgdz.cn
http://uudsfDYu.hpgdz.cn
http://VSysYMYX.hpgdz.cn
http://TiCeKHqM.hpgdz.cn
http://nZhzktGi.hpgdz.cn
http://Sy7YFNEO.hpgdz.cn
http://vSYWKbuj.hpgdz.cn
http://bUOiPPXZ.hpgdz.cn
http://GlT87lU1.hpgdz.cn
http://rygBnbrg.hpgdz.cn
http://Ro86Q6Tz.hpgdz.cn
http://mKRzlL1o.hpgdz.cn
http://bmUaBtvu.hpgdz.cn
http://opPDeFsG.hpgdz.cn
http://vLZqa3T3.hpgdz.cn
http://l3U5NiyW.hpgdz.cn
http://www.dtcms.com/a/368071.html

相关文章:

  • Python 实现 Markdown 与 Word 高保真互转(含批量转换)
  • 如何在 C# 中将文本转换为 Word 以及将 Word 转换为文本
  • 电商企业如何选择高性价比仓储系统?专业定制+独立部署,源码交付无忧
  • Mysql:由逗号分隔的id组成的varchar联表替换成对应文字
  • Windows环境下实现GitLab与Gitee仓库代码提交隔离
  • PXM的JAVA并发编程学习总结
  • Cursor Pair Programming:在前端项目里用 AI 快速迭代 UI 组件
  • java面试中经常会问到的集合问题有哪些(基础版)
  • 23种设计模式——桥接模式 (Bridge Pattern)详解
  • AI日报 - 2025年09月05日
  • 23ai数据库通过SQLcl生成AWR报告
  • 销量骤降、降价自救,新别克GL8能否成为上汽通用救星?
  • 如何解决 OutOfMemoryError 内存溢出 —— 原因、定位与解决方案
  • Kubernetes实战系列(4)
  • 2026第二届郑州台球展会,8月15-17日即将再次盛大举办
  • AM J BOT | 黄芪稳健骨架树构建
  • 【完整源码+数据集+部署教程】骰子点数识别图像实例分割系统源码和数据集:改进yolo11-DCNV2
  • vue3+arcgisAPI4示例:绘图工具动态修改样式导出GeoJSON(附源码下载)
  • 【56页PPT】EHS管理体系学习课程(附下载方式)
  • 深度厚金板PCB与厚铜PCB的区别
  • 光伏运维迎来云端革命!AcrelCloud-1200如何破解分布式光伏四大痛点?
  • 5分钟征服Linux:20个神级命令+系统架构解密,让命令行恐惧症瞬间治愈!
  • 一文了解太阳光模拟器的汽车材料老化测试及标准解析
  • 笔记:现代操作系统:原理与实现(2)
  • 核心高并发复杂接口重构方案
  • java log相关:Log4J、Log4J2、LogBack,SLF4J
  • 计算机网络7 第七章 网络安全
  • python + flask 3 简单的授权验证(基于文件)
  • Spark面试题及详细答案100道(56-70)-- 性能优化
  • 高级RAG策略学习(五)——llama_index实现上下文窗口增强检索RAG