VS2010 MFC ダイアログベースアプリです。
コンマ区切りCSVファイルを出力するプログラムを作っています。
UNICODE文字を扱えるようにしたいので、プロジェクトは「UNICODE 文字セットを使用す
る」としています。
サンプルとして、次のコードを書きました。
void CCSVDlg::OnBnClickedButton1()
{
CString sData[] = {_T(いつやるか。), _T(今でしょ!), _T(あとで), _T
(やります。)};
CString sSave;
sSave = sData[0] + _T(,) + sData[1] + _T(\n);
sSave += sData[2] + _T(,) + sData[3] + _T(\n);
CFile f;
f.Open(_T(test1.csv), CFile::modeCreate | CFile::modeWrite);
f.Write(sSave, sSave.GetLength() * sizeof(TCHAR));
f.Close();
}
これで test1.csv というファイルが出来ます。
MIFESというテキストエディタで調べると、UTF-16のファイルとなっているようです。
しかし、このファイルをエクセルで開くと文字化けします。
エクセルで編集できるUNICODEファイルを出力したいのです。
調べたら、エクセルで開けるUNICODEのCSVファイルは、
①コンマ区切りではなく、タブ区切りであること。
②UTF-16 LE の BOM付きであること。
と解りました。
①は、前記の _T(,) を _T(\t) に置き換えました。
②は、ファイルの先頭に、0xFF 0xFE の2バイトを付ければいいらしいのですが、どの
ようにプログラムコードを書けばいいかが解りません。
どうぞご教授ください。よろしくお願いいたします。
> ①コンマ区切りではなく、タブ区切りであること。
この時点でCSVじゃなくなりますけど、かまわんのですか?
> ②は、ファイルの先頭に、0xFF 0xFE の2バイトを付ければいいらしいのですが
CString sSave = L\xFFFE;
sSave += sData[0] + _T(,) + sData[1] + _T(\n);
これじゃダメ?
επιστημη様、有り難うございます。
> この時点でCSVじゃなくなりますけど、かまわんのですか?
はい、かまいません。
CString sSave = L\xFFFE;
sSave += sData[0] + _T(\t) + sData[1] + _T(\n);
これでやってみましたが、文字化けします。
エクセルのバージョンにもよるとは思いますが、
CSVとして完全に自動的に認識できるUnicodeは
1.UTF-16LE タブ区切り
のようですね。ただし、
エクセルを開いてから読み込む場合で、ウィザードDLGが出ても良いのなら、
2.UTF-8(BOM付き) (区切りはウィザードで設定する)
もOKのようですよ。
特にUnicodeにこだわらなければShift-JISが最も安全ですけどね。
エンディアン的に逆ですかね
>CString sSave = L\xFFFE;
CString sSave = L\xFEFF;
文字列に無理やりしないでバイトとして書き出したほうが簡明かも。
> f.Open(_T(test1.csv), CFile::modeCreate | CFile::modeWrite);
BYTE bom = {0xff, 0xfe};
f.Write(bom, sizeof(bom));
> f.Write(sSave, sSave.GetLength() * sizeof(TCHAR));
> f.Close();
構文的に配列ですかね
>BYTE bom = {0xff, 0xfe};
BYTE bom[] = {0xff, 0xfe};
>akeyさん
普通に間違えてましたorz
ご指摘感謝します。
出来ました。
CString sData[] = {_T(いつやるか。), _T(今でしょ!), _T(あとで), _T
(やります。)};
CString sSave;
sSave = sData[0] + _T(\t) + sData[1] + _T(\n);
sSave += sData[2] + _T(\t) + sData[3] + _T(\n);
BYTE bom[] = {0xff, 0xfe};
CFile f;
f.Open(_T(test1.csv), CFile::modeCreate | CFile::modeWrite);
f.Write(bom, sizeof(bom));
f.Write(sSave, sSave.GetLength() * sizeof(TCHAR));
f.Close();
これで、タブ区切りのCSV?ファイルが出来て、ダブルクリックでエクセルが開き、文字
化けなく正常に表示されました。
本当はコンマ区切りにしたいので、コンマ区切りで作成した場合もやってみました。
① 作成したファイルをダブルクリックすると、エクセルが開いて、文字化けはありませ
んが、コンマも文字として認識した文字列「いつやるか。,今でしょ!」が表示されま
す。
② エクセルを起動してからファイルを開き、ウィザードDLGで”カンマ区切り”を選択
して進むと、正常に表示されました。
③ 次に、エクセル上で編集を行い、上書き保存のアイコンで保存すると、タブ区切りの
ファイルに変化しました。
④ 名前を付けて保存で「CSV(カンマ区切り)」で保存すると、正常に保存されまし
た。
⑤ そのファイルは次回ダブルクリックでも正常に開きました。
②の方法で開き④の方法で保存・・・これを励行すればコンマ区切りでも使えそうで
す。
それにしても、エクセルの Unicode 対応は中途半端と思います。
⑤の理由が解りません。BOM以外の何かをエクセルが書き込んだのでしょうか?
蒼の洞窟様はじめ、皆様ありがとうございました。
>⑤の理由が解りません。BOM以外の何かをエクセルが書き込んだのでしょうか?
④で書き出したファイルがShift-JISだった…とかではないですか?
これは、これは、親分! 大笑い (^o^)
④で書き出したファイルは Shift-JIS でした。
やはりタブ区切りでないとエクセルではまともに扱えませんね。
タブ区切りだと、何かと扱いにくい。
Unicode が大前提なので、エクセルに阿て(おもねて)タブ区切りにするか、エクセル
を無視してコンマ区切りで押し通すか・・・うーむ
ありがとうございました。