【エクセル】CSV変換で日付が文字化け!?正しい日付を自動出力する方法とは?

一覧表をCSVファイルに変換したら日付の表示がおかしくなった、という経験はありませんか?
エクセルで「2024/04/01」と表示されている日付をCSVで保存したときに「45383」のような数値に変換されてしまう現象は、多くのエクセルユーザーが頭を抱える問題ですよね。
手作業で1件ずつ日付を入力し直している方もいますが、件数が多くなるほど時間と労力が膨大になります。
こんな手間と時間のかかる作業はVBAで自動化することが可能。
日付の数値変換・備考欄テキストの結合・CSVファイルへの出力まで、一連の編集作業をボタン1クリックで自動化することができます。
この記事では、CSV変換時に発生する日付の文字化け(数値化)の原因から、VBAを使った正しいCSV出力の方法まで、実際のコードを交えて解説しています。
エクセルデータをCSVファイルに変換する作業が多い方は是非参考にしてみてください。
エクセルCSV変換で日付が文字化けする原因とは
エクセルでCSV変換すると日付が「45383」のような数値に変わってしまう原因は
エクセルの内部的な日付管理の仕組み
にあります。
エクセルは日付を「シリアル値」と呼ばれる数値で管理しています。
1900年1月1日を「1」として、そこから何日経過したかを整数で表したものがシリアル値です。
たとえば「2024年4月1日」はシリアル値で「45383」になります。
エクセルのセル上では書式設定によって「2024/04/01」と表示されていますが、実際に保存されているのは「45383」という数値です。
CSVはテキスト形式のファイルであり、エクセルのような書式設定情報を持ちません。
そのため、エクセルのデータをCSVで保存すると、日付の書式が失われてシリアル値の数値がそのまま書き出されてしまいます。
これが、エクセル CSV変換 日付文字化けの正体です。
表示上は正しい日付に見えていても、CSV出力した瞬間に数値に変わってしまうので、戸惑う方が多いのでないでしょうか。
手作業で修正すると毎回30分以上ロスする
この問題に直面したとき、多くの方が「CSVを開いて日付を手入力で修正する」という対処をしています。
10件や20件程度のデータであれば何とかなりますが、100件・200件を超えると話が変わります。
1件の日付入力に10秒かかったとして、200件では33分以上かかる計算です。
さらに毎月・毎週この作業を繰り返すとなると、年間で膨大な時間がムダになります。
入力ミスが発生するリスクを考えると手動での編集は今すぐにやめるべきです。
VBAを使えばこの手間が完全にゼロ。
日付データの変換処理もコードで自動化できるため、人の手は一切不要となります。
備考欄の結合作業もVBAで自動化できる
CSV変換の作業では日付の問題以外にも、エクセルファイルとCSVファイルの様式の違い問題が発生することがあります。
たとえば、システム側の都合でCSVの1つのカラムに「備考1の内容+備考2の内容」をまとめて入力しなければならない、というケースです。
CONCATENATE関数や「&」演算子を使って数式を組む方法もありますが、毎回同じ作業を繰り返すのは効率的ではありません。
VBAならこの結合処理もコードで一括実行できます。
日付変換と合わせて1つのマクロにまとめておけば、複数の編集作業をボタン1回で完了させることが可能です。
エクセルの書式設定だけでは根本的な解決にならない
「セルの書式設定で日付形式を変えればCSVも正しく出力されるのでは?」と考える方も多いです。
残念ながら、この方法では根本的な解決にはなりません。
書式設定はあくまで「表示方法」を変えるだけであり、内部に保存されているシリアル値は変わらないのです。
CSVに書き出されるのは内部のシリアル値なので、書式設定をどう変えてもCSV出力すると数値になってしまいます。
正しく解決するには、VBAを使って日付データをテキスト形式の文字列に変換してからCSVに書き出すという処理が必要です。
VBAで日付を正しくCSV出力する方法|Format関数を活用する
VBAで日付をテキスト文字列に変換するには、Format関数を使います。
Format関数は指定した書式でデータを文字列に変換してくれる便利な関数です。
具体的には、Format(セルの値, “yyyy/mm/dd") とすることで、シリアル値を「2024/04/01」という形式の文字列に変換することが可能。
この変換処理をCSV出力の前に挟み込むことで、日付が数値に化けることなく正しい形式でCSVファイルを作成できます。
日付変換と備考結合をまとめたサンプルコード
エクセルの一覧表から必要なデータを取り出し、日付をテキスト変換・備考欄を結合してCSVに出力するVBAを作成してみます。
一覧表の構成を以下のように想定

A列:管理番号 B列:氏名 C列:登録日(日付) D列:備考1 E列:備考2
サンプルコードがこちら
Sub CSV出力_日付変換と備考結合()
Dim ws As Worksheet
Dim lastRow As Long
Dim i As Long
Dim csvPath As String
Dim fileNo As Integer
Dim line As String
Dim dateStr As String
Dim bikoStr As String
' 対象シートを設定
Set ws = ThisWorkbook.Worksheets("一覧")
' CSVの保存先パスを設定(デスクトップに保存)
csvPath = Environ("USERPROFILE") & "\Desktop\出力データ.csv"
' データの最終行を取得
lastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
' ファイルを開く
fileNo = FreeFile
Open csvPath For Output As #fileNo
' ヘッダー行を書き込む
Print #fileNo, "管理番号,氏名,登録日,備考"
' 2行目からデータを書き込む
For i = 2 To lastRow
' C列の日付をテキスト形式に変換
dateStr = Format(ws.Cells(i, 3).Value, "yyyy/mm/dd")
' D列(備考1)とE列(備考2)を結合
bikoStr = ws.Cells(i, 4).Value & ws.Cells(i, 5).Value
' CSV形式で1行分のデータを作成して書き込む
line = ws.Cells(i, 1).Value & "," & _
ws.Cells(i, 2).Value & "," & _
dateStr & "," & _
bikoStr
Print #fileNo, line
Next i
' ファイルを閉じる
Close #fileNo
MsgBox "CSV出力が完了しました。" & vbCrLf & csvPath, vbInformation
End Sub
上記のコードがどのように動いているかを順番に解説します。
最初の Set ws = ThisWorkbook.Worksheets(“一覧") で、処理対象のシートを「一覧」シートに固定しています。
シート名が異なる場合はここを変更してください。
次の csvPath = Environ(“USERPROFILE") & “\Desktop\出力データ.csv" では、CSVファイルの保存先をデスクトップに指定しています。
Environ(“USERPROFILE")はWindowsのユーザーフォルダのパスを自動で取得してくれる命令です。
lastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row は、A列の最終行を自動で取得するコードです。
データが増えても範囲指定を変更する必要がないため、この書き方を使っておくことをおすすめします。
Print #fileNo, “管理番号,氏名,登録日,備考" でヘッダー行を書き込んでいます。
CSV形式はカンマ区切りなので、各項目をカンマで区切って記述しましょう。
For i = 2 To lastRow のループ処理の中で、1行ずつデータを取り出して加工しています。
重要なのが dateStr = Format(ws.Cells(i, 3).Value, “yyyy/mm/dd") の部分です。
C列の日付セルの値を Format関数でテキスト変換しています。
これにより「45383」のようなシリアル値ではなく「2024/04/01」という文字列としてCSVに書き出すことが可能です。
bikoStr = ws.Cells(i, 4).Value & ws.Cells(i, 5).Value では、D列(備考1)とE列(備考2)の文字列を「&」演算子で結合しています。
スペースや区切り文字を挟みたい場合は & " " & のように間に入れてください。
最後に Close #fileNo でファイルを閉じて、MsgBoxで完了メッセージを表示します。
セル内にカンマが含まれる場合の対処法
CSV形式では、データにカンマが含まれていると区切り文字と混同されてしまい、読み込み時にデータがズレるという問題が発生します。
たとえば備考欄に「商品A、Bを発注済み」のようにカンマが入っているケースです。
この場合、該当のフィールドをダブルクォーテーションで囲むことで解決できます。
コードの中の備考部分を以下のように変更してください。
' カンマが含まれる可能性があるフィールドは " " で囲む
bikoStr = """" & ws.Cells(i, 4).Value & ws.Cells(i, 5).Value & """"
VBAでダブルクォーテーションを文字として扱うには、"" と2つ続けて書く必要があります。
VBAコードをボタンに登録してワンクリックで実行する方法
作成したVBAコードは、エクセルシート上のボタンに登録することでワンクリックで実行できるようになります。
毎回VBAエディタを開く必要がなくなり誰でも簡単にマクロを使えるようになるため必ず作成しましょう。
ボタンを配置してマクロを登録する手順
まず、エクセルのメニューバーにある「開発」タブをクリックします。
「開発」タブが表示されていない場合は、「ファイル」→「オプション」→「リボンのユーザー設定」から「開発」にチェックを入れると表示されるようになります。
「開発」タブの「挿入」→「ボタン(フォームコントロール)」を選択し、シート上でドラッグするとボタンが作成されます。
ボタンを置いた直後に「マクロの登録」ダイアログが表示されるので、先ほど作成した「CSV出力_日付変換と備考結合」を選んで「OK」をクリックします。
ボタンを右クリックして「テキストの編集」を選択すると、ボタンに表示する文字の変更が可能。
「▶ CSV出力」などわかりやすい名前にしておくと、他のメンバーが使う場合も迷わなくなります。
VBAコードの実行前に確認しておくべき3つのポイント
VBAを実行する前に確認しておきたいポイントが3つあります。
1つ目は、シート名の確認です。
コード内の Set ws = ThisWorkbook.Worksheets(“一覧") に記載しているシート名と、実際のシート名が一致しているか確認してください。
シート名が違うとエラーが発生します。
2つ目は、データの列構成の確認です。
サンプルコードはA列:管理番号、B列:氏名、C列:登録日、D列:備考1、E列:備考2という構成を前提にしています。
自分のデータの列構成に合わせてコードを修正してください。
3つ目は、日付列の書式確認です。
C列のデータが文字列として入力されている場合、Format関数が正しく動作しないことがあります。
セルの書式が「日付」または「標準」になっているか事前に確認しておきましょう。
CSV変換VBAをさらに応用する方法
ここまで紹介した基本的なCSV出力VBAをベースに、さらに便利な機能を追加することもできます。
実務でよく使われる応用パターンを2つ紹介します。
出力するシートや列を動的に切り替える方法
毎月異なるシートからCSVを出力したい場合や出力する列の組み合わせを変えたい場合は、変数でシート名や列番号を管理する方法が便利です。
たとえば以下のように設定用のセルをシート上に用意しておき、VBAがそのセルを参照して動作を変える仕組みにすれば、コードを修正せずに設定だけ変えて運用できます。
' A1セルに指定されたシート名を取得して処理対象にする
Dim sheetName As String
sheetName = ThisWorkbook.Worksheets("設定").Cells(1, 2).Value
Set ws = ThisWorkbook.Worksheets(sheetName)
この仕組みを使えば、「設定」シートのB1セルにシート名を入力するだけで、処理対象のシートを変えることができます。
VBAの中身を変更せずに運用できるため、エクセルに詳しくないメンバーでも迷わず操作することが可能。
関連記事「別シートにテキストを自動転記」では、シートを指定するVBA、転記VBAが設定されたエクセルファイルをダウンロードすることができます。
日付が空白のセルをスキップする処理を追加する
一覧表の中に日付が未入力の行がある場合、Format関数にシリアル値ではなく空白が渡されてしまい、意図しない値がCSVに書き込まれることがあります。
これを防ぐには、日付セルが空白かどうかを判定するIf文を追加しましょう。
' 日付が入力されている場合のみ変換する
If ws.Cells(i, 3).Value <> "" Then
dateStr = Format(ws.Cells(i, 3).Value, "yyyy/mm/dd")
Else
dateStr = ""
End If
この処理を加えることで、日付が入力されていない行は空白のままCSVに出力されます。
データに不備があってもストップさせず最後まで処理を継続することが可能。
また、日付が空白の場合にその行自体を出力対象外にしたい場合は「If文の条件を逆にして空白行は For i のループをスキップする」なんて方法もあります。
保存ファイル名に日付を自動入力する方法
CSV出力のたびにファイル名を手動で変更しているケースがよく見られますが、この処理もVBAで自動化できます。
以下のように、ファイル名の一部に今日の日付を組み込んでください。
' 今日の日付をファイル名に組み込む
Dim today As String
today = Format(Now(), "yyyymmdd")
csvPath = Environ("USERPROFILE") & "\Desktop\出力データ_" & today & ".csv"
実行するたびに自動的に日付入りのファイル名で保存され、過去のCSVファイルを上書きしてしまうリスクがなくなります。
さらに「出力データ_20240401.csv」のように実行した日付がファイル名に自動で付いてくるので、ファイル管理の効率をアップさせることが可能です。
まずは月次・週次でCSV出力を繰り返す業務に導入してみましょう。
まとめ ~ CSV変換の日付問題はVBAで完全に解決できる ~
エクセルのCSV変換で日付が文字化け(数値化)してしまう原因は、エクセルが日付をシリアル値で管理しているためです。
この問題は、VBAのFormat関数を使ってシリアル値をテキスト文字列に変換することで完全に解決できます。
日付変換・備考欄の結合・CSV出力までを1つのマクロにまとめれば、毎回の手作業がボタン1クリックで完了。
- Format関数で日付をテキスト変換してCSVに書き出す
- 「&」演算子で複数の備考欄テキストを結合する
- カンマを含むデータをダブルクォーテーションで囲む
- 保存ファイル名に今日の日付を自動入力する
ぜひ今回紹介したコードをベースに、自分の業務の列構成に合わせてカスタマイズしてみてください。
関連記事記事「日付データがCSVで文字化け!?一覧表の日付を数値変換して正しくCSV出力する方法とは」では、CSV出力マクロが設定されたエクセルファイルをダウンロードすることができます。
もし「自分の業務に合わせた複雑なチェック処理を実装したい」「既存のマクロを改良したい」といったご要望がありましたら、マメBlogのエクセルマクロ開発依頼にご相談ください。
業務内容に合わせたオーダーメイドマクロを設定させていただきます。
最後まで読んでいただきありがとうございました。
エクセルVBAを使って面倒なルーティーン作業を自動化しちゃいましょう。








