UTF-8対応Webアプリケーションの構築: 第3回(VB6.0)
UTF-8対応Webアプリケーションの構築の記事の第3回は、Visual Basic 6.0(以下、VB6)を取り上げたいと思います。
本題に入る前に、前回までのおさらいをしてみましょう。
アプリケーションの全体像は次のようになります。
+-----------+ +--------------+ +---------------+
|Webブラウザ|←ⅰ→|Webサーバ(IIS)|←ⅱ→|ASP プログラム|
+-----------+ +--------------+ +---------------+
↑
ⅲ
↓
+-----------+
|ActiveX DLL|
+-----------+
↑
ⅳ
↓
+-----+ +--------+
|ADODB|←ⅴ→|MSDE2000|
+-----+ +--------+
一見ややこしい感じを受けますが、Webブラウザから送出されたUTF-8文字列が無事にMSDEに格納され、反対にMSDEに格納されているUCS-2文字列がWebブラウザに対してUTF-8で返されることが要求されます。上記の図において、第1回はASPの話、第2回はMSDEの話を通じて
・ⅰ、ⅱがUTF-8での通信(ⅱですでにUCS-2になっているかもしれないけど)
・ⅲは、UCS-2の文字列
・MSDEに格納できるのは、クエリ前提ならばUCS-2
であることを説明しました。
今回の記事では、残る通信経路であるⅳとⅴを見ていきましょう。ⅲがUCS-2である以上、ⅳとⅴはUCS-2での通信にならなければ困ります。ではどうすればいいのでしょうか。
あまり意識されることがないかと思いますが、VB6の世界において、内部の文字コードはUnicodeです。ここでいうUnicodeはWindowsのUnicodeですのでUCS-2です。シフトJISのようなMBCSでないということです。
この仕様が今回のようなUnicode対応アプリケーションを構築する上で大変便利です。つまり、経路ⅲとⅳにおいて、文字列はUCS-2のUnicodeだということです。Unicodeであるので、事実上、OSの言語には依存せず、VB6の英語版でも日本語版でも文字列操作は内部的にはUCS-2で実行されます。私の経験においては、VB6の英語版でActiveX DLLを作る必要があったので、MBCSとUnicodeの変換から解放されるのはとても喜ばしいことでした。
さて、残るは、経路ⅴです。ここまでくると、ADODBとMSDEの間は、やはりUCS-2でなければ困ります。ここからは、ADODBの使いこなしひとつで勝負が決まります。ADODBでSQL文を実行するには、いくつかの方法があります。対Unicodeをきちんと意識するために、ADODB.Commandを利用することを前提に話を進めましょう。
ADODB.Commandオブジェクトを使って、SQL文を呼び出す場合、Parametersコレクションを使って、SQL文に渡すパラメータについて細かく指定することができます。Parameters.Appendメソッドを利用することで、各パラメータを定義できます。ここで重要になるのは、Unicodeに対応したデータ型を指定するということです。もっと厳密に言えば、DataTypeEnum値を指定するということです。
DataTypeEnum値において、Unicodeを指定する場合は、次のような定数があります。
・adWChar : MSDE(SQL Server)のncharに対応
・adVarWChar : MSDE(SQL Server)のnvarcharに対応
・adLongVarWChar : MSDE(SQL Server)のntextに対応
この関係が理解できてしまえば、後は、ADODBを素直に呼び出せばいいのです。
では、第2回で作成したストアドプロシージャを呼び出すクラスを作ってみましょう。
ここからは長くなりますが、VB6のコードを追いかけてください。
' clsUtext.cls
' author: Akira Onishi / copyright(c) 2004, Akira Onishi
Option Explicit
'--------------------------------------------------------------------
' キーワードで検索し、一致したレコードセットを返す
' connString: ADODBの接続文字列
' Keyword: 検索用キーワード
'--------------------------------------------------------------------
Public Function UtextInfo(ByVal connString, ByVal Keyword)
On Error GoTo ErrorHandler:
Dim oConn As New ADODB.Connection
Dim CmdP As New ADODB.Command
Dim rsP As New ADODB.Recordset
oConn.Open connString
rsP.CursorLocation = adUseClient
With CmdP
.ActiveConnection = oConn
.CommandText = "spUtextInfo"
.CommandType = adCmdStoredProc
.Parameters.Append .CreateParameter("@Keyword", adVarWChar, _
adParamInput, 30, Keyword)
End With
rsP.Open CmdP
Set rsP.ActiveConnection = Nothing ' オフラインのRecordset作成
Set UtextInfo = rsP
oConn.Close
Set rsP = Nothing
Set CmdP = Nothing
Set oConn = Nothing
Exit Function
ErrorHandler:
Set rsP = Nothing
Set CmdP = Nothing
Set oConn = Nothing
Set UtextInfo = Nothing
Err.Raise Err.Number, Err.Source, Err.Description
End Function
'--------------------------------------------------------------------
' すべての行をレコードセットとして返す
' connString: ADODBの接続文字列
'--------------------------------------------------------------------
Public Function UtextAll(ByVal connString)
On Error GoTo ErrorHandler:
Dim oConn As New ADODB.Connection
Dim CmdP As New ADODB.Command
Dim rsP As New ADODB.Recordset
oConn.Open connString
rsP.CursorLocation = adUseClient
With CmdP
.ActiveConnection = oConn
.CommandText = "spUtextAll"
.CommandType = adCmdStoredProc
End With
rsP.Open CmdP
Set rsP.ActiveConnection = Nothing ' オフラインのRecordset作成
Set UtextAll = rsP
oConn.Close
Set rsP = Nothing
Set CmdP = Nothing
Set oConn = Nothing
Exit Function
ErrorHandler:
Set rsP = Nothing
Set CmdP = Nothing
Set oConn = Nothing
Set UtextAll = Nothing
Err.Raise Err.Number, Err.Source, Err.Description
End Function
'--------------------------------------------------------------------
' 行を作成する
' connString: ADODBの接続文字列
' Keyword:キーワードの文字列
' note: メモ用の長い文字列
' ErrMessage: エラーメッセージ格納用文字列
'--------------------------------------------------------------------
Public Function UtextInsert(ByVal connString, ByVal Keyword, _
ByVal note, ByRef ErrMessage)
On Error GoTo ErrorHandler:
Dim oConn As New ADODB.Connection
Dim cmdUtext As New ADODB.Command
Dim lTrans As Long
oConn.Open connString
lTrans = oConn.BeginTrans
With cmdUtext
.ActiveConnection = oConn
.CommandText = "spUtextInsert"
.CommandType = adCmdStoredProc
.Parameters.Append .CreateParameter("@Keyword", adVarWChar, _
adParamInput, 30, Keyword)
.Parameters.Append .CreateParameter("@note", adLongVarWChar,_
adParamInput, 4000, note)
.Execute
End With
If Err.Number <> 0 Then GoTo ErrorHandler:
' トランザクションのコミットと後処理
oConn.CommitTrans
oConn.Close
Set cmdUtext = Nothing
Set oConn = Nothing
ErrMessage = "OK"
Exit Function
ErrorHandler:
' ロールバックとエラーの通知
If lTrans <> 0 Then oConn.RollbackTrans
Set cmdUtext = Nothing
Set oConn = Nothing
ErrMessage = Err.Description
Err.Raise Err.Number, Err.Source, Err.Description
End Function
'--------------------------------------------------------------------
' 行を更新する
' connString: ADODBの接続文字列
' Keyword:キーワードの文字列
' note: メモ用の長い文字列
' ErrMessage: エラーメッセージ格納用文字列
'--------------------------------------------------------------------
Public Function UtextUpdate(ByVal connString, ByVal Keyword, ByVal note, _
ByRef ErrMessage)
On Error GoTo ErrorHandler:
Dim oConn As New ADODB.Connection
Dim cmdUtext As New ADODB.Command
Dim lTrans As Long
Dim ChangePassword As Boolean
Dim rsinfo As New ADODB.Recordset
oConn.Open connString
lTrans = oConn.BeginTrans
With cmdUtext
.ActiveConnection = oConn
.CommandText = "spUtextUpdate"
.CommandType = adCmdStoredProc
.Parameters.Append .CreateParameter("@Keyword", adVarWChar, _
adParamInput, 30, Keyword)
.Parameters.Append .CreateParameter("@note", adLongVarWChar, _
adParamInput, 4000, note)
.Execute
End With
If Err.Number <> 0 Then GoTo ErrorHandler:
' トランザクションのコミットと後処理
oConn.CommitTrans
oConn.Close
Set cmdUtext = Nothing
Set oConn = Nothing
ErrMessage = "OK"
Exit Function
ErrorHandler:
' ロールバックとエラーの通知
If lTrans <> 0 Then oConn.RollbackTrans
Set cmdUtext = Nothing
Set oConn = Nothing
ErrMessage = Err.Description
Err.Raise Err.Number, Err.Source, Err.Description
End Function
'--------------------------------------------------------------------
' 行を削除する
' connString: ADODBの接続文字列
' Keyword:キーワードの文字列
' note: メモ用の長い文字列
' ErrMessage: エラーメッセージ格納用文字列
'--------------------------------------------------------------------
Public Function UtextDelete(ByVal connString, ByVal Keyword, _
ByRef ErrMessage)
On Error GoTo ErrorHandler:
Dim oConn As New ADODB.Connection
Dim strSQL As String
Dim lTrans As Long
' ※文字列リテラルでUnicodeを指定する際は、Nプレフィックスが必要!!
strSQL = "spUtextDelete " & "N'" & Trim(Keyword) & "'"
oConn.Open connString
lTrans = oConn.BeginTrans
oConn.Execute strSQL
If Err.Number <> 0 Then GoTo ErrorHandler:
' トランザクションのコミットと後処理
oConn.CommitTrans
oConn.Close
Set oConn = Nothing
ErrMessage = "OK"
Exit Function
ErrorHandler:
' ロールバックとエラーの通知
If lTrans <> 0 Then oConn.RollbackTrans
Set oConn = Nothing
ErrMessage = Err.Description
Err.Raise Err.Number, Err.Source, Err.Description
End Function
これで、アプリケーションの構成要素間のUnicode問題は解決しました。最後にこれらをまとめれば完成です。長くなりましたので、続きは次回に。