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
英文地址,請注明出處:http://en.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 D3: 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;更標…