結局 Excel の 内部UTF に悩ませる

ちょいと新たに分かったことがあったので色々修正。

繰り返し作業させるために機械向けにプログラムを作りたかったが、途中で寝るほど退屈な作業の繰り返し。

そのため、プログラムでささっと変更するプログラムを作ろうと思った。

コンピューターは人間を楽にするためにあるのだから。

最初Python で作ろうと思ったが、Excelで編集しながら出力したくなってきたので、 Excel VBA で作り始めてしまった。

単純にファイルハンドルもひとつずつ、手順的に処理させるのには VBA は確かに最適。

ただし問題があった。Excel VBA は内部的には 一文字ずつUTF で動いているらしく、ぼんやりと快適に動く。

ところが、機械側は今風の BOM付きUTF-16LE によるテキストファイルだった。

FFFE 45 00 55 00 0D 00 0a 00 みたいな。

まず現状の機械のプログラムを読ませると頭に FFFE がついてくる。こいつは実力で取り除いた。

     Dim buf As String
            Open 読み込むフルパス For Input As #1
                 Do Until EOF(1)
                    Line Input #1, buf

  If StrToHex(Mid(buf, 1, 2)) = "FFFE" Then
        buf = Mid(buf, 3)
        
        
     End If

その後読まれた buf を Debug.Console してみると、「VERSION」のように中身が一文字ずつ入っている。String 型と思って文字単位に変換してくれたらしい。

            'ファイルをカレント+日付で書き出し
    Dim strNow As String
    strNow = Format(Now, "yyyy-mm-dd hh.nn.ss")
    Open 読み込むフォルダ名 & Application.PathSeparator _
    & strNow & ".PRD" For Output As #1
    '開いたファイルに書き込む
    Print #1, OutputPRD
    '開いたファイルを閉じる
    Close #1
 

次に Open write で bufを一気に print で書き出してみると、45550d0a みたいなsjis ファイルになった。このことから Excel VBA は内部的にsjis かと思ったが、内部的にはUTFで書き込むときに sjis CP932か?になっているらしい。

まあ読んでくれるだろうと、機械に読ませてみると、読まない。ちゃんと UTF-16LE でないと読まないのだった。

仕方なし、実力でFFFE を頭に付け加え、StrConv( xxx, vbUnicode) で変換したものを Print 。

            OutputPRD = StrConv(OutputPRD, vbUnicode)

スコンブが vbUnicode に変換しているが、メモリ上では UTFのUTF変換となり、すさまじい文字か刻まれている。ほんとはデータ型を Byte に変換しないとヤバい。これで結果としてUTF-16LEで書き込まれた。

なんとか機械様に読んでもらった。最後の CRLFが 0d 0a になってしまったが。(0d 00 0a 00)

Print #1, OutputPRD;

最後に JS の様にセミコロンをつけると改行コードの出ない Print となるらしい。なにその独特ルール。

めんど。Mac のExcelとか文字コード何で動いてるんだろう。

Excel VBA とかこの辺が嫌なんだよな。内部は sjis でもいいけど、UTF の読み書きぐらいさっとできてほしいものだ。参照設定で、「Microsoft ActiveX Data Objects 2.8 Library」を import して Set adoSt = CreateObject(ADODB.Stream) とか Java っぽい事が正義。

python 2.7でunicode

python 2.7でunicodeの達人になる。

さくらのレンサバが実はpython 2.7 早く3化してほしいが、世の中なぜかレンサバにpython3を無理やりインストールしている。

% python
Python 2.7.16 (default, Sep 19 2019, 05:07:24)
[GCC 4.2.1 Compatible FreeBSD Clang 6.0.0 (tags/RELEASE_600/final 326565)] on freebsd11
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
   #default は ascii それでは utf-8 を指定する。
>>> sys.setdefaultencoding('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'setdefaultencoding'
# エラーになる。最初から入っているsysはutfを知らない。
# 但し、リロードすると使えるようになる。
>>> reload(sys)
<module 'sys' (built-in)>
>>> sys.setdefaultencoding('utf-8')
>>> sys.getdefaultencoding()
'utf-8'
>>>
 #あっさり。

I love UTF

http://blog.livedoor.jp/kaz0215/archives/51124286.html