星期三, 6月 05, 2013

[解決] 用 Python來開 Microsoft Access的.mdb資料檔的中文欄位問題

又開始沒事找事做,開始改之前寫好的程式了。

在之前的文章:用 Python來開 Microsoft Access的.mdb資料檔曾經提到
"pyodbc 是个很不错的库,api 也很好用,不过对中文支持的并不好"
我的經驗也是如此。原始資料庫的開發者沒事把欄位名稱用上中文,結果就是我花了好久時間,還是不能用sql語法的where來限制欄位的比對結果。

後來有熱心網友提供了他的心得:用微軟提供的元件 ADODB 來存取 Access。所以我也很快樂的在新版程式中 import這些功能。一個不錯的使用方法及副程式,可以在AlarmChang所維護的Python NoteBook中找到程式碼,基本上直接copy就很好用了。

但是,還是一樣,一但整份.py文件儲存時是使用utf-8,那就完了,一直出現error。
重點是,我突然發現,在
SQL = "Select * from TableABC"
rs = Connect_To_Access(SQL)

這一段,其實是丟一個字串(SQL)給Microsoft ADODB COM去解譯,那我丟的字串符合它要的編碼規定(在我之前的文章有提,就是用ansi儲存的編碼),就可以了吧。
所以,只要把上面的SQL字串重新編/解碼過即可。
因此,程式碼變成:
### 我更改過的部份程式碼:
SQL = ("Select * from SOAP where 識別碼='12345'").decode('utf8')
   ### 因為全部文字都是用utf-8做編碼的,後面直接decode掉就好了。
   ### 下面再做呼叫即可
res = Connect_To_Access(SQL)


整個實做就像這樣:(下以code是從文章:用 Python來開 Microsoft Access的.mdb資料檔稍做修改得到)
# -*- coding: utf-8 -*-
import os
import sys
import win32ui
import win32com.client
import win32com.client.dynamic
import string
import time
import datetime
 
 
 
def Connect_To_Access(SQL_Command):
    #Input : SQL command 可以撈出指定部門的address 檔案裡面的咚咚
    #Output : recordset
    #將cnnection new 出來連接到資料庫(access)
    cm = win32com.client.Dispatch(r"ADODB.Command")
    Conn = win32com.client.Dispatch(r"ADODB.Connection")
    strMDB = 'Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False;Data Source=.\\Your_Access_Database.mdb' #<----就是這一行和SQL server不一樣
    Conn.Open(strMDB)
    cm.ActiveConnection = Conn
    cm.CommandType = 1
    cm.CommandText = SQL_Command
    cm.Parameters.Refresh()
    cm.Prepared = True
    (rs1, result) = cm.Execute()
    return rs1
 
 
def main():
    SQL = "Select * from TableABC where 中文欄位='123456'"
    SQL = SQL.decode('utf8')#<----直接把要送出去的字串decode掉即可
    rs = Connect_To_Access(SQL)
    while not rs.eof:
        print rs.Fields.Item(1).Value
        rs.MoveNext()
這個方法應該也適用於pyodbc才是。 UPDATE 是適用沒錯,請看:
### pyodbc打開.mdb檔的方式

conn = pyodbc.connect('DRIVER={Microsoft Access Driver (*.mdb)};DBQ=c:\\dir\\file.mdb')
cursor = conn.cursor()
cursor.execute('select * from ProgressNote;')

cursor.execute(('SELECT * FROM ProgressNote WHERE "病歷號"=?').decode('utf8'),'12345678')
###

沒有留言:

//for syntaxhighlighter 3 //看一下載入的JS模組有哪些,不要的就刪掉 //end syntaxhighlighter 3