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

问题

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

驱动下载、安装、引用

驱动网址(下载路径)

使用的 ODBC 驱动(需要梯子才能下载,感谢大佬开源)
http://www.ch-werner.de/sqliteodbc/

版本选择

根据 Office 32/64 位选择对应版本的驱动
即:32/64 位的 Office 就安装 32/64 位的驱动

我的电脑是 32 位 Office,则下面以 32 位驱动的配置为例


基础配置

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

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

示例代码(出现乱码)

数据库定义(VBA 字符拼接的 SQL)
自增 ID 字段 + 其他 TEXT 类型数据

    sql = "CREATE TABLE devList (" & _"id INTEGER PRIMARY KEY AUTOINCREMENT, " & _"deviceNumber TEXT, " & _"deviceIdentifier TEXT, " & _"deviceChineseName TEXT, " & _"deviceDrawingCode TEXT, " & _"moduleBoxNumber TEXT, " & _"stationName TEXT)"

VBA 代码

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.CommitTrans'执行完成,清理收尾goto CleanuperrorHandler: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 = "导入完成,导入数据行数:" & totalCount
End Function

插入时发现中文变成了乱码(类似下面的样式,实际不是这个表,这里只是做个展示)
在这里插入图片描述

问题解决

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

解决方法

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

    1. OEMCP=1:数据库驱动会自动处理字符的编码,保证写入正确
    2. NoWCHAR=0:(这是驱动的默认值,可以不加)设置允许使用 WCHAR 数据类型,保证上面插入的数据在 SQLite 中显示正确
    3. 最终的连接字如下
      "DRIVER={SQLite3 ODBC Driver};Database=<数据库路径>;OEMCP=1;NoWCHAR=0;"
      
    4. 注意上面的连接字对应的数据库路径中不能包含中文字符,否则会报错connect failed(连接失败)
  2. ADODB 的 parameter 对象,指定的变量类型应更改为双宽类型,保证 parameter 对象传入驱动的数据字符是正确的

    1. SQLite 中 varcharTEXT类型的变量,应定义为adVarWChar而不是adVarChar
    2. SQLite 中 char 类型的变量,应定义为adWChar而不是adChar
    3. 示例代码的修改如下
      .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 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 & ";OEMCP=1;NoWCHAR=0;"' 建立指令对象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.CommitTrans'执行完成,清理收尾goto CleanuperrorHandler: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 = "导入完成,导入数据行数:" & totalCount
End Function

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/96142.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

执行select * from a where rownum<1;,数据库子进程崩溃,业务中断。

文章目录环境症状触发条件解决方案环境 系统平台&#xff1a;Linux x86-64 Red Hat Enterprise Linux 7 版本&#xff1a;4.5.2 症状 执行select * from a where rownum<1;&#xff0c;数据库子进程崩溃&#xff0c;业务中断。 触发条件 select 和 where条件带有rownum…

python库 Py2app 的详细使用(将 Python 脚本变为 MacOS 独立软件包)

更多内容请见: python3案例和总结-专栏介绍和目录 文章目录 一、Py2app 概述 1.1 Py2app 介绍 1.2 安装 1.3 替代工具推荐 二、基础使用 2.1 最简单的 setup.py 文件 2.2 完整示例 2.3 配置选项详解 2.4 完整项目案例 2.5 打包为单文件应用(可选) 三、高级配置 3.1 处理特定…

NTP配置为客户端广播监听模式

前言 项目需求&#xff1a; 使能ntp为客户端模式&#xff0c;能监服务端广播模式发出的ntp报文&#xff0c;计算出服务端的时间与客户端的时间偏差并上报。 开发状况&#xff1a; 交叉编译ntp源码&#xff0c;将修改后的ntpd进程部署到设备上作为客户端完成项目需求 如何操作&a…

Claude-Flow 使用指南

Claude-Flow 不仅仅是一个工具&#xff0c;更是一个强大的AI驱动开发编排平台。本问初步带您深入了解 Claude-Flow v2.0.0 Alpha 的强大功能&#xff0c;助您在AI开发领域如虎添翼。1. 简介&#xff1a;什么是 Claude-Flow&#xff1f; Claude-Flow v2 Alpha 是一个企业级的AI编…

系统梳理 Test-Time Compute 的主要实现路径

编者按&#xff1a; AI 真的在“思考”吗&#xff1f;当模型面对数学推理、代码生成或复杂决策时&#xff0c;它是如何一步步推演出答案的&#xff1f;如果你曾困惑于大模型在关键任务中表现不稳定、缺乏可解释性&#xff0c;甚至生成结果难以验证&#xff0c;那么你并不孤单。…

vue 经常写的echarts图表模块结构抽取

vue 经常写的echarts图表模块结构抽取将项目中经常写的结构抽取一下, 方便以后用 表头包含标题和右侧操作部分下面为图表 <div class"chartBox"><div class"chartheadbox"><div class"chartheadleft">这是图表标题</div>…

主流的开源协议(MIT,Apache,GPL v2/v3)

文章目录1. MIT 协议 (MIT License)2. Apache 2.0 协议 (Apache License 2.0)3. GPL v2 协议 (GNU General Public License v2)“开源协议选择指南”的流程图 flowchart TDA[开始选择开源协议] --> B{是否要求修改后必须开源?<br>(是否具有 传染性?)};B -- 是&…

CameraService笔记

cameraservicecamera 结构图1. 启动CameraServer1.1 注册media.camera服务1.2 构造CameraService1.3 CameraService::onFirstRef1.4 CameraService::enumerateProviders&#xff1a;前置准备知识1.4 CameraService::enumerateProviders&#xff1a;Provider和Device初始化1.4.1…

MacOS 15.6 编译SDL3 Android平台多架构so库

成功编译输出: 编译: Android平台多架构编译脚本: sdl3_android_build.sh #!/bin/bash# 设置变量 macos 其他系统需要更改路径 SDL_SOURCE_DIR=$(pwd)/SDL BUILD_DIR=${SDL_SOURCE_DIR}/../sdl3_build_android NDK_PATH=$HOME/Library/Android/Sdk/Ndk/25.2.9519653 CMAKE…

Real-IAD D³: A Real-World 2D/Pseudo-3D/3D Dataset for Industrial Anomaly

Real-IAD D: A Real-World 2D/Pseudo-3D/3D Dataset for Industrial Anomaly Detection Paper Github 摘要 随着工业异常检测&#xff08;Industrial Anomaly Detection, IAD&#xff09;复杂程度的不断提升&#xff0c;多模态检测方法已成为机器视觉领域的研究焦点。然而&a…

IT需求提示未读信息查询:深度技术解析与性能优化指南【类似:钉钉已读 功能】

IT需求提示未读信息查询&#xff1a;深度技术解析与性能优化指南【类似&#xff1a;钉钉已读 功能】 DROP TABLE IF EXISTS rs_kpi_it_need_tip; CREATE TABLE IF NOT EXISTS rs_kpi_it_need_tip (id bigint NOT NULL AUTO_INCREMENT COMMENT 主键ID&#xff…

Django中的软删除

软删除&#xff08;Soft Delete&#xff09;是一种数据删除策略&#xff0c;它并不真正从数据库中删除记录&#xff0c;而是通过标记&#xff08;如 is_deleted 字段&#xff09;来表示记录已被删除。 这样做的好处是可以保留数据历史&#xff0c;支持数据恢复和审计。 在 Djan…

JavaEE 进阶第四期:开启前端入门之旅(四)

专栏&#xff1a;JavaEE 进阶跃迁营 个人主页&#xff1a;手握风云 目录 一、常用CSS 1.1. border 1.2. width/height 1.3. padding&#xff1a;内边距 1.4. margin&#xff1a;外边距 二、初始JavaScript 2.1. JavaScript是什么 2.2. 发展历史 2.3. JavaScript 和 HT…

学习日记-SpringMVC-day49-9.4

知识点&#xff1a;1.RequestMapping&#xff08;3&#xff09;知识点核心内容重点RequestMapping注解的parameters属性通过parameters指定请求参数条件&#xff08;如bookID&#xff09;&#xff0c;控制请求匹配规则&#xff08;必须包含/排除特定参数或值&#xff09;参数存…

【Day 50 】Linux-nginx反向代理与负载均衡

概述在现代 Web 架构中&#xff0c;Nginx 作为高并发、高性能的 HTTP 和反向代理服务器&#xff0c;被广泛应用于提升服务性能、增强系统安全性和实现负载均衡。其中&#xff0c;反向代理能够隐藏后端服务器信息并优化请求处理流程&#xff0c;负载均衡则可将请求分发到多个后端…

vue中配置 ts

在 Vue 项目中配置 TypeScript&#xff08;TS&#xff09;可以提升代码的类型安全性和开发体验。以下是在 Vue 项目&#xff08;基于 Vite&#xff09;中配置 TypeScript 的详细步骤和关键配置&#xff1a; 一、创建支持 TypeScript 的 Vue 项目 如果是新建项目&#xff0c;推…

阿里云镜像地址获取,并安装 docker的mysql和nginx等服务,java,python,ffmpeg,go等环境

阿里云那个镜像地址获取 阿里云镜像加速器不是一个通用的 registry.cn-hangzhou.aliyuncs.com&#xff0c;而是你账号专属的&#xff0c;比如这样&#xff1a; https://abcd1234.mirror.aliyuncs.com&#x1f449; 登录阿里云控制台获取&#xff1a; 阿里云镜像加速器 然后替…

conda环境导出

1. 激活你想要打包的环境首先&#xff0c;确保你激活了你要打包的 conda 环境&#xff1a;conda activate qwen2. 导出环境配置使用 conda 命令将当前环境的配置导出为一个 .yml 文件&#xff0c;记录下环境中所有的依赖和版本&#xff1a;conda list --export > techgpt_en…

openEuler2403安装部署Kafka

文章目录 openEuler2403安装部署Kafka with KRaft一、前言1.简介2.架构3.环境 二、正文1.部署服务器2.基础环境1&#xff09;JDK 安装部署2&#xff09;关闭防火墙 3.单机部署1&#xff09;下载软件包2&#xff09;修改配置文件3&#xff09;格式化存储目录4&#xff09;单机启…

发布工业智能体,云从科技打造制造业AI“运营大脑”

近日&#xff0c;在2025世界智能产业博览会重庆市工业智能体首发仪式现场&#xff0c;云从科技重磅发布经营决策-产线运营智能体&#xff0c;为制造业的智能化转型提供了全新的解决方案。该智能体的亮相&#xff0c;不仅代表着人工智能技术在工业领域的深度应用&#xff0c;更标…