VB6で、DBデータ(UTF-8)を扱う方法


VB6の文字コードは難しいです  2005-10-26 06:43:02  No: 126897

VB6について、あまり詳しくない者で御座います。
どなたか、以下についてご教授頂けますでしょうか?

仕様は
VB6を使って、DBから値を取得し、EXCELに貼り付けるという
ごくごく簡単な処理です。

DB(DB2)の文字コード体系はUTF-8で、
DBとの接続はODBCを使っています。

通常の日本語、英語等はEXCELにて表示できるのですが、UTF-8で表現できる
スペイン語文字のアクセント文字等が化けてしまいます。

どなたか、スペイン語文字のアクセント文字等が正常に表示
できる方法を教えていただけませんでしょうか?

環境
OS:WINDOWS  NT4.0  SP6
EXCEL:EXCEL97  
VB:VB6.0  SP3
DB:DB27.2

色々試しましたが上手くいきませんでした。
例えば、OSの言語オプションで、スペイン語環境に設定し
VBを動かすと、スペイン語のアクセント文字は正常に標記出来たのですが
日本語が化けてしまいました。。。。。

VB6の設定等で、実現できないでしょうか?

以上
宜しくお願いいたします


魔界の仮面弁士  2005-10-26 08:34:27  No: 126898

具体的に、どのようなコードになっているのでしょう?
また、文字化けはどの時点で発生しているのでしょうか?

> 通常の日本語、英語等はEXCELにて表示できるのですが、UTF-8で表現できる
> スペイン語文字のアクセント文字等が化けてしまいます。
Excel 97自体は、Unicode文字列の表示に対応しているはずですが…。

Excel 97 VBA で下記を実行してみましたが、正しく「ごめんなさい」と表示されましたよ。
Sheet1.Range("A1").value = "Perd" & ChrW(&HF3) & "n" 

> VBを動かすと、スペイン語のアクセント文字は正常に標記出来たのですが
> 日本語が化けてしまいました。。。。。
VB6 の標準コントロールは、Unicode 文字列の表示に対応していません。
ChrW(&HF3) 等を表示可能なのは、一部の ActiveX コントロール (DataGrid など) に限られます。


VB6の文字コードは難しいです  2005-10-26 11:04:56  No: 126899

魔界の仮面弁士さん
ご返信ありがとうございます。

>具体的に、どのようなコードになっているのでしょう?
文字コードが、S-JISになって表示されてしまっています。

>また、文字化けはどの時点で発生しているのでしょうか?
これを確認したいと思っているのですが、・・よく分かっていません。
ソースコードは、以下の通りです。
***************
Dim oRec As rdoResultset   ''検索条件から取得するDBデータのレコードセット
Dim sBuf As String         ''データ格納文字列
Dim oExcelWorkbook      As Excel.Workbook
Dim oExcelCopySheet     As Excel.Worksheet 


・SQL文を発行し、DBデータを取得

buf = CStr(oRec(1).Value)

・EXCELファイルのOPEN

Set oExcelCopySheet = oExcelWorkbook.Sheets("AA")
oExcelCopySheet.Range("A1").Value = buf

・EXCELファイルの保存

***************
デバック実行時にbufを参照しても、oRec(1).Valueの値のスペイン語アクセント文字は表示されないもので・・・

ご返信内容にChrW()関数を使ってらっしゃいますね。
この関数について、少し調べたいと思います。
また、上記ソース内容で、何か問題がある場合、ご教授いただけると
助かります。

よろしくお願い致します。


魔界の仮面弁士  2005-10-26 11:37:28  No: 126900

>> 具体的に、どのようなコードになっているのでしょう?
> 文字コードが、S-JISになって表示されてしまっています。
この場合は、文字コードではなく、プログラムコードの意味でした。m(_ _)m

> デバック実行時にbufを参照しても、
本来 buf に格納されるべきデータは、具体的にはどのようなデータで、
実際の buf の内容は、どのようなデータになっているのでしょうか?

> ご返信内容にChrW()関数を使ってらっしゃいますね。
VB6のソースコードは Shift_JIS ベースなので、Unicode文字が使えません。
そのため、ChrW関数を用いた表現を使った次第です。

ChrW関数は、Unicode(UCS-2/UTF-16) のコードを元にして、文字を返します。
Chr関数は、Shift_JIS のコードを元にして、文字を返します。
同様に、0〜255のコードを受け取る ChrB関数もあります。

逆に、文字をコードに変換するための、AscW, Asc, AscB関数もあります。

> oRec(1).Valueの値のスペイン語アクセント文字は表示されないもので・・・
もし、Value から返されるデータ自体が化けているようであれば、
VB 側では対処できません。その場合は、データベース または OS 環境側の
設定の問題という事になるので、この掲示板での範疇を超えてしまうかと。


VB6の文字コードは難しいです  2005-10-26 11:56:49  No: 126901

魔界の仮面弁士さん  たびたびのご回答ありがとうございます。

>本来 buf に格納されるべきデータは、具体的にはどのようなデータで、
>実際の buf の内容は、どのようなデータになっているのでしょうか?

BárbaraEspaña(UTF-8)という値が・ソBテ。rbaraEspaテアa(S-JIS)に
化けてしまっています。

>もし、Value から返されるデータ自体が化けているようであれば、
>VB 側では対処できません。その場合は、データベース または OS 環境側の
>設定の問題という事になるので、この掲示板での範疇を超えてしまうかと。

やはりそういう問題の可能性もあるということでしょうか・・・
たとえば、UTF-8形式のファイルから、データを取得し、EXCELに貼り付ける場合
*************
    '現在年月のログファイルをOPEN
    Open sLogFile1 For Input As #iFileNum
    
    '現在年月のログ内容出力
    Input #iFileNum, sdata
    
    '現在年月のログファイルをCLOSE
    Close #iFileNum

Set oExcelCopySheet = oExcelWorkbook.Sheets("AA")
oExcelCopySheet.Range("A1").Value = sdata

***************

で可能でしょうか?
たびたび、申し訳ありませんが、ご教授のほど、よろしくお願い致します。


魔界の仮面弁士  2005-10-26 14:06:17  No: 126902

まず大前提として、日本語環境下においては、
「VB6 の文字列型は UTF-16 で保持されている」という点と、
「VB6 での文字列入出力は、基本的に Shift_JIS で行われる」
という点を覚えておいてください。(UTF-8 は利用されていません)

----

> BárbaraEspaña(UTF-8)という値が
それは、UTF-8のバイナリでいえば、
  42 C3 A1 72 62 61 72 61 45 73 70 61 C3 B1 61
というデータという事でよろしいですか?

とすれば、VB 的に言えば、
  buf = "B" & ChrW(&HE1) & "rbaraEspa" & ChrW(&HF1) & "a"
という事になりますね。  

> ・ソBテ。rbaraEspaテアa(S-JIS)に
> 化けてしまっています。
いや、化けた結果を貼られても、二重に化けちゃいますので。(^_^;)
そうではなく、
  Dim B() As Byte
  B = buf
などして、それらのバイナリ値を示して下さい。

# ……でも、データの化け方を見た感じでは、元データは、
#   42 C3 A1 72 62 61 72 61 45 73 70 61 C3 B1 61
# ではなく、
#   EF BB BF 42 C3 A1 72 62 61 72 61 45 73 70 61 C3 B1 61
# のようですね。DB側の 元データには、BOM を含めてあるのでしょうか?

ところで、先ほど
> ・ソBテ。rbaraEspaテアa(S-JIS)に
のように「S-JIS」なのだと仰いましたよね。
この場合、どの時点で S-JIS 化されたのかも、非常に重要な点となります。

例えば、UTF-8 の『あ』は、「E3 81 82」というバイナリですよね。
で、「E3 81 82」というバイナリは、UTF-16 として解釈すると
『臣*』であり、Shift_JIS として解釈すると『縺*』となります。
(上記の * は、バイナリデータを意味しています)

もし、DB(UTF-8)側 に『あ』が格納されており、それをVB6の文字列に
受け取るような場合、正常に文字コード変換が行われていたとすれば、
  UTF-8『あ』E3 81 82    →    UTF-16『あ』42 30
のように変化しますので、VB 側には、
  buf = ChrB(&H42) & ChrB(&H30)  'もしくは buf = ChrW(&H3042)
というデータとして渡される事になります。

その後、(Print 等で)出力する際に、UTF-16 → Shift_JIS 変換が
自動的に行われます。これが正常な状態となります。

しかし、データベース自体(あるいはミドルウェア)の設定に問題があって、
Shift_JIS 変換が先に行われてしまっており、結果として
  buf = "縺*"    'buf = ChrB(&H3A) & chrB(&H7e) & ChrB(??)
な状態で渡されてしまうような状況だとしたら、これはもはや
VB 側では手の施しようがありません。取得した時点で、データの欠損が
発生してしまっている(または、欠損する可能性がある)ためです。

一方、文字コード変換が何も行われていなかったのであれば、まだ救いはあります。
たとえば、『あ』のUTF-8バイナリが、変数 buf に無加工で格納されたなら、
  buf = ChrB(&HE3) & ChrB(&H81) & ChrB(&H82)
のような状態になっているはずです。(VB6 の文字列としては『臣*』の状態ですね)

この場合は、UTF-8 → UTF-16 変換を VB6 側でプログラム的に行ってあげる事で、
『あ』という元データを正しく復元する事ができます。

> たとえば、UTF-8形式のファイルから、データを取得し、EXCELに貼り付ける場合
> (中略)
> で可能でしょうか?
テキストモード(For Input)では駄目です。使うなら、バイナリモード(For Binary)ですね。

Input ステートメント(というか、VB6の文字列処理全般)では、自動的に
Shift_JIS と UTF-16 との間での変換が行われる仕様になっているので、
UTF-8 データを食べさせると、データが破損してしまうからです。

ですが、UTF-8 のテキストファイルを読み込ませたいのであれば、VB 標準の
Open ステートメントを使うのではなく、ADODB.Stream というオブジェクトを
使って読み込ませた方が良いでしょう。

ADODB.Streamについては、過去ログにサンプルがありますので、探してみてください。


VB6の文字コードは難しいです  2005-10-27 04:30:47  No: 126903

魔界の仮面弁士さん、度々のご回答ありがとう御座います。

私のほうで、
>しかし、データベース自体(あるいはミドルウェア)の設定に問題があって、
>Shift_JIS 変換が先に行われてしまっており、結果として・・・

調査を行い、ODBC側の設定に問題があることが分りました。
また、設定をする事で、
>一方、文字コード変換が何も行われていなかったのであれば、まだ救いはあります。
>たとえば、『あ』のUTF-8バイナリが、変数 buf に無加工で格納されたなら、・・

の状態にする事が出来ました。
そこで、ご教授いただきたいのですが
VB6において、
>この場合は、UTF-8 → UTF-16 変換を VB6 側でプログラム的に行ってあげる事で、
>『あ』という元データを正しく復元する事ができます。

上記処理は、どのようにすれば良いのでしょうか?
ご教授いただけますでしょうか?
宜しくお願いいたします


魔界の仮面弁士  2005-10-27 07:57:50  No: 126904

> >この場合は、UTF-8 → UTF-16 変換を VB6 側でプログラム的に行ってあげる事で、
> >『あ』という元データを正しく復元する事ができます。
> 上記処理は、どのようにすれば良いのでしょうか?

先の回答にて述べた『ADODB.Stream』を使うのが簡単でしょう。
たとえば、過去ログのこのあたりが参考になるかと。

http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200401/04010054.txt

上記では、JISバイナリ(バイト配列)→Stringへの変換を行っていますが、
同様の手順を踏めば、UTF-8バイナリを VBのStringに変換する事もできます。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加