TL;DR —
Print #とWrite #は、ファイルへ正反対のスタイルで書きます。Print #は テキストを見たとおりに書きます — 引用符もカンマもなく、区切り文字はあなたが挿入します。Write #は マシン形式を書きます — すべての文字列を引用符で囲み、値の間にカンマを入れ、日付を#...#で 囲む —Input #に読み戻させるために作られています。人が読む CSV にWrite #を使うことが、 あなたのファイルが引用符だらけになる理由です。Print #を使い、行は自分で組み立てましょう。
' Write # — マシン形式、すべての文字列を引用符で囲む:
Write #n, "Ann", "Rome", 42 ' ファイルの中身: "Ann","Rome",42
' Print # — レイアウトはあなたが制御する、引用符なし:
Print #n, "Ann" & "," & "Rome" & "," & 42 ' ファイルの中身: Ann,Rome,42
マクロがチャネルを開けるようになったら、次に決めるのは、ディスク上で
バイトがどう見えるべきかです — そして VBA は、その問いに正反対の答えを返す 2 つのステートメントを
与えます。Print # は目に見えるものを書き、Write # はプログラムが解析し戻せるものを書きます。
間違ったほうを選ぶと、ファイルは技術的には正しくても、次に開く人には使いものになりません。引用符に
溺れる CSV か、あるいは列がすべて 1 つのセルに入る「CSV」かのどちらかです。どちらのステートメントが
どのバイトを生むのかを知ることが、この技のすべてです。
この記事で学べること
- 考え方の軸 —
Print #はあなたが見るものを書き、Write #はプログラムが読み戻すものを書く Write #がすべての文字列を引用符で囲む理由(そして、それがまさに正しいのはいつか)Print #リストの中のカンマが CSV のカンマではなくプリントゾーンを挿入する理由Print #と自分の区切り文字で、きれいな CSV 行を組み立てる方法For Outputが切り詰める一方でFor Appendが追加する理由- 小数点カンマのロケールの罠、そして組み込みの書き込みが UTF-8 ではなく ANSI である理由
考え方の軸:表示形式とマシン形式
「なぜ私のファイルはこう見えるのか」という問いのほとんどを片づける洞察はこれです。Print # と
Write # は、2 種類の異なる読み手に仕えます。
Print #は表示形式を書きます。 テキストを、セルやMsgBoxに現れるのとちょうど同じ形で ディスクに置きます — 引用符も、自動の区切りも、型のマーカーもありません。レイアウトを決めるのは あなたです。Write #はマシン形式を書きます。 すべての文字列を引用符で囲み、値をカンマで区切り、日付を#2026-01-31#、Trueを#TRUE#、Emptyを#NULL#として書きます。これはシリアライズ形式で、Input #がまったく同じ値を読み戻せるように設計されています。
だから選択は好みの問題ではありません — 次に誰がファイルを読むかの問題です。Input # で解析し
戻すプログラムは Write # をほしがります。人、Excel、その他どんなツールも Print # をほしがります。
Write # があなたの CSV を引用符で埋める理由
これはいちばん多い不満で、しかもバグではありません — Write # が仕事をしているだけです。
Write #n, "Ann", "Rome", 42
' ファイル: "Ann","Rome",42
それらの引用符は意図的です。カンマを含む文字列("Rome, Italy")を、2 つの別々のフィールドと
区別できるようにするためです。VBA 同士の往復には完璧ですが、人が開くレポートには間違いです。
「エクスポートした CSV がなぜ引用符だらけなのか」と誰かが尋ねるとき、答えはいつも同じです —
Print # がほしかった場面で、コードが Write # を使ったのです。
Write # が正しい道具であるのは、ちょうど 1 つの場面だけです。ファイルを Write # で書き、それを
Input # で、すべて VBA の中で読み戻すときです。人や Excel が開くものには、Print # に手を伸ばし
ましょう。
Print # の中のカンマが CSV のカンマではない理由
当たり前に思える対処 — 「カンマ付きで Print # を使えばいい」 — には、それ自身の罠があります。
Print # リストの中では、カンマが別の意味を持つからです。
Print #n, "Ann", "Rome", 42 ' Ann,Rome,42 にはならない
Print # リストで項目の間に置いたカンマは、プリントゾーン — およそ 14 文字ごとのタブストップで、
コンソール印刷の名残 — を挿入します。だから上の行は、カンマではなく広い隙間を空けて出力され、あなたの
「CSV」は 1 つの崩れた列として開きます。直し方は、Print # に区切り文字を挿入させるのをやめ、行全体を
自分で組み立てることです。
Print #n, "Ann" & "," & "Rome" & "," & 42 ' Ann,Rome,42 — あなたが制御する 1 つの文字列
ほしいリテラルの区切り文字でフィールドを連結し、Print # に単一の文字列を渡せば、まさにその
バイトが得られます。末尾のセミコロン(Print #n, s;)は、行を少しずつ組み立てる必要があるときに
改行を抑えます。
Print # で本物の CSV 行を組み立てる
まとめると、信頼できる「CSV を書く」パターンは、各行を 1 つの文字列に結合し、Print # にそれを
そのまま出力させます。
Sub ExportRange(ByVal rng As Range, ByVal path As String)
Dim n As Integer, r As Range, cell As Range, line As String
n = FreeFile
Open path For Output As #n ' 切り詰める。追加するには Append を使う
For Each r In rng.Rows
line = ""
For Each cell In r.Cells
line = line & cell.Value & "," ' あなたの区切り文字、あなたのルール
Next cell
If Len(line) > 0 Then line = Left(line, Len(line) - 1) ' 末尾のカンマを落とす
Print #n, line ' 組み立てたとおりの 1 行まるごと
Next r
Close #n
End Sub
これは、ほぼすべての実運用の CSV エクスポートが取る形です。引用符付けと区切り文字を正確に制御できる
唯一の方法だからです。フィールド自体がカンマを含みうるなら、そのフィールドを自分で引用符で囲み
ましょう — それは Print # があなたに委ねる決定であり、そこが要点です。
Output は切り詰め、Append は追加 — そしてロケールとエンコーディングの罠
あと 2 つの細部が、ファイルが正しいかどうかを決めます。
- モード —
For Outputは毎回ファイルを空から書き直し、For Appendは 末尾に追加します。C:\Logs\run.logのような増え続けるログはFor Appendで開かなければならず、 さもないと各実行が前回を消してしまいます。 - 小数点カンマ — ドイツ・フランス・スペインのシステムでは、
CStr(3.5)が3,5を生むことがあり、 そのカンマは CSV の区切り文字と衝突して、1 つの数値を 2 つの列に分割します。Format(x, "0.00")かStr(x)(つねに.を使う)で小数点を強制するか、数値フィールドを引用符で囲みましょう。 - エンコーディング — 組み込みの
Print #は UTF-8 ではなく ANSI を書きます。アクセント付きや 非ラテンのテキスト(é、ü、日本語)はシステムのコードページで書かれ、ファイルを UTF-8 として 開くと文字化けします。Unicode 出力には、ADODB.StreamかFileSystemObjectのCreateTextFile(path, True, True)を使いましょう。
正直な結論:誰がファイルを読むかで選ぶ
Print # と Write # は交換可能ではなく、決定のすべては 1 つの問いに帰着します。
- Write # は VBA 同士の往復にのみ → その引用符、カンマ、
#...#マーカーは、Input #がまったく同じ値を再構築できるように存在します。人が 目にするべきではありません。 - Print # はそれ以外のみんなに → 各行を、ほしい区切り文字で自分で組み立てる。
Print #リストの 中のカンマは、区切り文字ではなくプリントゾーンです。 - 貯めるなら Append、書き直すなら Output → モードが、履歴が残るかどうかを決めます。
- 本物の CSV には
.を強制し UTF-8 にする → ファイルがマシンを離れる前に、小数点カンマの ロケールの罠と ANSI エンコーディングの罠をガードする。
間違ったステートメントに手を伸ばした、いちばんはっきりした合図は、頼んでもいない引用符です。それが
現れたら、あなたは Write # で書いています。Print # に切り替えて、レイアウトを自分のものに
しましょう。
ExcelMaster の活用
きれいなデータをエクスポートするとは、Write # が Input # のためにすべてを引用符で囲むこと、
Print # の中のカンマが区切り文字ではなくプリントゾーンであること、For Output はファイルを消す
一方で For Append は増やすこと、そして小数点カンマや ANSI エンコーディングが CSV を静かに壊し
うることを知っておくことです — 「ファイルを書く」にしては、たくさんの判断です。
ExcelMaster は、きれいに
開けるエクスポートを書きます。ジョブを説明すれば — 「この範囲を CSV として保存して」、あるいは
「各実行でログに 1 行追記して」 — 正しい区切り文字を備えた Print # の行ビルダー、正しいモード、
そしてロケール安全な数値書式を、ThisWorkbook.Path に固定して生成します。
あなたは人やプログラムが読む必要のあるファイルを説明するだけ。まさにそのバイトを生むコードを書くのは、
それがやります。
よくある質問
VBA で Print # と Write # の違いは何ですか?
Print # はテキストを見たとおりに書きます — 引用符も区切り文字もなく、レイアウトはあなたが制御
します。Write # はマシンが読める形式を書きます — すべての文字列を引用符で囲み、値の間にカンマを
入れ、日付を #...# で囲む — Input # に読み戻させるために設計されています。人や Excel が開くものには
Print # を、Input # で VBA に読み戻すファイルにのみ Write # を使いましょう。
VBA の CSV が引用符だらけになるのはなぜですか?
コードが Write # を使ったからです。Write # は、Input # が解析し戻せるように、わざとすべての
文字列を引用符で囲みます。それは VBA 同士の往復には正しいのですが、レポートには間違いです。Print #
に切り替え、各行を自分で組み立てましょう — Print #n, a & "," & b — そうすれば余計な引用符のない
きれいな CSV が得られます。
Print # が値をカンマで区切らないのはなぜですか?
Print # リストで項目の間に置いたカンマは、CSV のカンマではなくプリントゾーン(およそ 14 文字
ごとのタブストップ)を挿入するので、フィールドは 1 つの列の中に広い隙間を空けて出力されます。代わりに
Print # へ連結した単一の文字列を渡しましょう — Print #n, a & "," & b & "," & c — そうすれば区切り
文字は、あなたが書いたとおりのものになります。
VBA で上書きせずにテキストファイルを書くには?
For Output ではなく For Append で開きます。For Output は書き込む前にファイルを空に切り詰めるので、
各実行が以前の内容を消します。For Append は、ファイルがなければ作り、そうでなければ末尾に追加します。
チャネル番号は FreeFile から取り、終わったら Close #n で閉じましょう。
VBA で UTF-8 やアクセント付き文字をファイルに書くには?
組み込みの Print # と Write # はシステムのコードページで ANSI を書くので、アクセント付きや
非ラテンのテキストは、ファイルを UTF-8 として読むと文字化けします。Unicode 出力には ADODB.Stream を、
あるいは FileSystemObject の CreateTextFile(path, True, True) を使い、
最後の引数で Unicode を要求します。また、Format(x, "0.00") で小数点を強制して、ロケールの小数点
カンマが区切り文字を壊さないようにしましょう。
検証環境
検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-25。
関連ガイド: VBA FreeFile & Open · VBA Read Text File · VBA FileSystemObject · VBA Save Workbook · VBA CurDir
