UTF-8の文字列をセルに区切ってセットするには?

解決


へな  2005-01-25 01:15:49  No: 87982

UTF-8のファイルをmDatDataに入れてラベルには表示されるのですが
この読み込んだ内容を区切ってエクセルの各列にセットしようとすると
文字化けでどうしたらいいかわかりません。

    Dim mDatData as string
    Set Stm = CreateObject("ADODB.Stream")
    Stm.Open
    Stm.Charset = "UTF-8"
    Stm.LineSeparator = adCRLF
    Stm.LoadFromFile SourceFilePath

    Do Until Stm.EOS    'End Of Streamまでループ
        mDatData = mDatData + Stm.ReadText(adReadLine)
    Loop

’こんな感じでセットしようかと思ったのですが化けてしまいます
    Range("F1").Value = MidB(mDatData, 1, 2)
    Range("F2").Value = MidB(mDatData, 3, 5)
    Range("F3").Value = MidB(mDatData, 10, 28)
    Range("F4").Value = MidB(mDatData, 40, 25)

簡単に変換できるようにしたいのですが、どうしてもわからないので
教えていただけますでしょうか?


魔界の仮面弁士  2005-01-25 02:45:11  No: 87983

>    Do Until Stm.EOS    'End Of Streamまでループ
>        mDatData = mDatData + Stm.ReadText(adReadLine)
>    Loop
これは、改行文字を除去する処理でしょうか?

>    Range("F2").Value = MidB(mDatData, 3, 5)
バイト単位で処理をされているのには、何か理由があるのでしょうか?
特に理由が無ければ、MidB関数ではなく、Mid関数を使ってみて下さい。

MidBを使えないわけではありませんが、その場合は、MidB関数の
第3引数に指定する数値は、(奇数ではなく)偶数である必要があります。
(VB6/VBAの文字列型は、1文字を2バイトで表現しますから)


へな  2005-01-26 00:16:35  No: 87984

魔界の仮面弁士さん。レスどうもです

>これは、改行文字を除去する処理でしょうか?
これはただデータが全部ほしかっただけです。
いまいち使い方がわからなかったのでloopしてますけど(^^;

>バイト単位で処理をされているのには、何か理由があるのでしょうか?
>特に理由が無ければ、MidB関数ではなく、Mid関数を使ってみて下さい。

全角を3バイト、半角カナも3バイトで計算しないといけなかったので
MidBを使ってみました

>MidBを使えないわけではありませんが、その場合は、MidB関数の
>第3引数に指定する数値は、(奇数ではなく)偶数である必要があります。
>(VB6/VBAの文字列型は、1文字を2バイトで表現しますから)

ご指摘とおりMid関数にしました

取りあえず下記で対応できたので乗せときます

'UTF-8で読み込み
    Set Stm = CreateObject("ADODB.Stream")
    Stm.Open
    Stm.Charset = "UTF-8"
    Stm.LineSeparator = adCRLF
    Stm.LoadFromFile UserForm1.TxtFileDat

'Shift_JISでオブジェクト作成
    Set Stm2 = CreateObject("ADODB.Stream")
    Stm2.Open
    Stm2.Charset = "Shift_JIS" '"SJIS" '"Shift_JIS"

'UTF-8→Shift_JISでコピー
    Stm.CopyTo Stm2
'適当な名前で保存
    Stm2.SaveToFile UserForm1.TxtFileDat & "1", 2
Stm2の内容をもう一度よみこんでおく
Stm.Close:Stm2.Close
----省略
'ArryRange(i)=ほしい文字のバイト数が入ってます
’AAA=Stm2の内容です
'flg=切出すスタート位置です

For  〜省略   
  Range("F" & i).Value = MidByte(AAA, flg, ArryRange(i))
  〜省略
loop

MidByteの関数は下記を参考してちょっと内容変更してますが
http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/vb_t04.htm

魔界の仮面弁士さんいろいろありがとうございました。
これからも拝見しますので、そのときはまたよろしくお願い致します


魔界の仮面弁士  2005-01-26 00:54:30  No: 87985

>> これは、改行文字を除去する処理でしょうか?
> これはただデータが全部ほしかっただけです。
.ReadText(adReadLine) の替わりに、.ReadText(adReadAll) を使って
取得すれば、ループ無しで、全データを一度に取得できますよ。

あるいは、「.ReadText(取得したい文字数)」のような事もできます。

なお、元ファイルの文字コードが UTF-8 であれ、EUC-JPであれ、
ReadTextメソッドで取り出される単位は、「文字単位/行単位/全部」です。
あくまで文字の取得であって、バイナリの取得ではありません。

もし、生のバイナリをそのまま取り出すなら、.Read()メソッドを使う事になります。

>> バイト単位で処理をされているのには、何か理由があるのでしょうか?
>> 特に理由が無ければ、MidB関数ではなく、Mid関数を使ってみて下さい。
> 全角を3バイト、半角カナも3バイトで計算しないといけなかったので
> MidBを使ってみました
文字コードの扱いに誤解があるようです。

確かにUTF-8では、英数字=1バイト、ロシア語等=2バイト、漢字等=3バイトで
表現されていますが、それはあくまで「UTF-8」の場合だけです。

しかし、VB6が内部で利用しているUnicodeは、UTF-8ではなく、UCS-2/UTF-16です。
また、ADODB.Streamのテキストモードでは、元のバイナリがどの形式であれ、
.ReadText()される際には、常にVB標準の文字コードに変換されています。

つまり先のコードでは、元ファイルの文字コードや、文字の種類に関係なく、
.ReadText()した時点で、常に「1文字=2バイト」で表現される文字列として
取得される事になります。ですから、それを3バイト単位で切り出して
しまっては、当然データが破損してしまうというわけです。

# そもそも、Mid関数(≠MidB関数)を使えば、文字種に関係なく、「文字単位」で
# 切り出せますから、Streamから読み込んだ文字列を、バイト単位で操作する意味は、
# ほとんど無いはずです。

> 取りあえず下記で対応できたので乗せときます
# 載せる?

ファイルに保存して開きなおしていますが、ファイル化も必要でしょうか。
ファイル化する必要が無いなら、Copy後に、「Stm2.Position = 0」を
実行すれば、Stm2の先頭から、もう一度 ReadText で読み込む事ができますよ。

あるいは、UTF-8のバイナリをShift_JIS形式のバイナリにしたいだけなら、
  Stm1.Charset = "UTF-8"
  Dim B() As Byte
  B = StrConv(Stm1.ReadText(adReadAll), vbFromUnicode)
のようにすればOKです。


へな  2005-01-28 18:09:53  No: 87986

魔界の仮面弁士さんおはようございます。

>あるいは、UTF-8のバイナリをShift_JIS形式のバイナリにしたいだけなら、
>  Stm1.Charset = "UTF-8"
>  Dim B() As Byte
>  B = StrConv(Stm1.ReadText(adReadAll), vbFromUnicode)

上記、その他ADODB.Streamのいろいろな使い方やご指摘ありがとうございます。
大変参考になりました。これからもっと勉強します。
どうもでした


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

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






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