先頭の0が消える問題は列の型、文字化けは文字コードから調べます。 どちらも「CSVを開いたら変になった」と見えますが、同じ設定変更で直るとは限りません。原本を残し、どの段階で値が変わったかを比べるのが出発点です。

この記事は、Pythonで事務データを扱い始めた人と、作ったCSVをExcel利用者へ渡す人向けです。機械学習を始める前のデータ取り扱いにも使えます。架空の備品コードを使い、読み込み前、Pythonの中、保存後、相手が開いた後という四段階で確認します。

一次資料確認日:2026年10月2日。本稿の品番、名称、数量は架空の練習データです。実際の顧客情報や社内ファイルを外部サービスへ渡さずに学べるよう、最初のコードはメモリー内だけで動きます。集計の欠損や重複を調べたい場合は、CSV集計が合わないときの検証で別に扱っています。

先頭ゼロと文字化けを、原因の違いから切り分ける

数字に見えるコードを、計算用の数値にしない

備品コード「00042」と数量「42」は、見た目が似ていても役割が違います。数量なら足したり平均を計算したりします。備品コードは、特定の品物を指すための名前です。先頭ゼロを取り除いた「42」が、元のコードと同じものを指すとは限りません。

列の名前だけで判断しにくい場合は、その値で何をするかを考えます。四則計算をする列なのか、検索、照合、別の台帳との結合に使う列なのかです。郵便番号、電話番号、部署コード、長い管理番号などは、計算に使わない識別情報であることが多いため、元の表記を残す設計から検討します。

例えばコード00042と42が両方存在する台帳なら、数値へ変換すると区別がなくなります。後で文字列に戻しても、二つが同じ値になった段階の情報は戻りません。コードの桁数が固定されているかも、データを見ただけで決めず、出力元の仕様や管理担当者に確認してください。

Pythonの標準のCSV読み込みと、pandasの読み込みを混同しないことも大切です。Pythonのcsv公式資料は、通常のreaderが各値を文字列として返すことを説明しています。一方、pandas.read_csvの公式資料には列型を指定するdtypeがあります。利用している処理を確認してから対処します。

つまり「Pythonで読んだらゼロが消える」とひとまとめにはできません。読み込み時の型推定、途中で行った整数への変換、保存後に表計算ソフトで開いたときの変換など、値を数値にする場所を探します。最初に列の役割を書いておくと、その変換が必要だったかを判断できます。

文字コードは、文字をバイトから読み戻す約束

CSVの中身は文字として見えますが、ファイルにはバイトが保存されています。同じバイト列をどの文字コードで読むかによって、日本語の読み戻し方が変わります。ここを取り違えると、読めない文字が出たり、UnicodeDecodeErrorなどで読み込みが止まったりします。

文字コードを調べるときは、出力したソフトの設定、データの提供元の仕様、同梱の説明を優先します。日本語のCSVだからといって一律にcp932と決めず、UTF-8などの可能性も確認してください。逆に、最近のデータだからUTF-8だと決めることもしません。作られた方法が判断材料です。

BOMはファイルの先頭に付く目印です。UTF-8のBOMを扱う際には、Pythonでutf-8-sigという指定を使う選択肢があります。ただし、この指定は「00042を数値に変えない」という列型の指示ではありません。日本語が読めるようになった後も、コードの値は別に確かめます。Pythonの符号化方式の説明も参照してください。

読めない文字を無視する設定で、エラーだけを消さないようにします。データの確認が目的なら、文字が欠けたまま読み終わるほうが気づきにくくなる場合があります。本稿の実行例では、不正な文字列を黙って捨てる処理を入れません。読めなかった場合は、どの指定で失敗したかを残して止めます。

文字化けを起こした画面を上書き保存すると、表示だけの問題だったものが保存内容の問題になることがあります。最初に原本のコピーを確保する理由はここにあります。なお、文字コードを変えればどんな破損も復元できるわけではありません。元の文字が別の文字に置き換わって保存された場合は、原本や提供元へ戻る必要があります。

原本、読み込み直後、保存後、受け取り側を比べる

確認する四段階をメモにします。Aは受け取った元CSV、BはPythonで読み込んだ値、CはPythonから出力して再読込した値、Dは受け渡し先で開いた値です。AからBで変わるなら読み込み、BからCなら出力処理、CからDなら受け渡し先の取り込み方を調べます。

原本を確認する際は、表計算ソフトの自動変換を経由しないテキスト表示を使うと、切り分けやすくなります。社内で認められたエディターでコピーを開き、先頭ゼロが文字として存在するかを見ます。文字コードが不明なまま上書きはせず、閲覧した段階で判断を止めてください。

Pythonの中では、値だけでなく型と長さも確認できます。画面に42と出ていても文字列の「42」なのか整数の42なのかで意味が変わります。reprを使うと、前後の空白なども見分けやすくなります。実務ログに個人情報を出すのではなく、本稿のような架空データで観察方法を覚えましょう。

保存後はファイル名だけで完了を判断せず、出力をもう一度読みます。先頭ゼロを保持するプログラムを書いても、別の列順で保存した、改行や区切りで項目がずれた、といった問題が残る可能性があります。期待する列名、行数、値を一緒に比べると、部分的な成功を全体の成功としにくくなります。

最後に、相手がどう開くかを確認します。ダブルクリックで開くのか、取り込み画面で列型を指定するのか、別システムへ読み込むのかで受け渡し条件が変わります。CSVの正しさと、相手のアプリが期待どおりに解釈することは、別の確認項目です。

症状に合った対策を選ぶ比較表

対策を選ぶ前に、症状を短い言葉で記録してください。「日本語が読めない」「ゼロがない」「長い番号の末尾が変わった」「1行目の列名だけ一致しない」は、調べる場所が同じとは限りません。以下は編集部の確認表で、どのソフトにもそのまま当てはまる設定一覧ではありません。

CSVの症状と、最初に確かめる設定
症状最初の確認先それだけでは解決しないこと
日本語が読めない出力元と読込側の文字コード先頭ゼロの型変換
00042が42になる列型の推定・数値化した処理すでに失われた桁の特定
長い管理番号が変わる数値として扱った段階と元文字列表示幅を広げるだけの対処
列名だけ合わないBOM・空白・列名の綴り内容を確かめない一括置換
保存前はよく相手側で変わる受け渡し先の取込方法Python側だけの再実行

先頭ゼロだけが問題なら、文字コードを何種類も変えて読み直す前に型を見ます。日本語が壊れているなら、列を文字列にするだけで済ませず符号化を見ます。この順番を決めておくと、偶然動いた設定の組み合わせをそのまま使うことが減ります。

自動判定のツールを使う場合も、判定結果だけで原本を書き換えないでください。候補の文字コードで読み、列名と日本語の具体的な値が妥当かを確認します。推定と確認は分けて記録すると、次回別の提供元から届いたファイルにも対応しやすくなります。

ゼロ埋めや引用符を、万能な復元策にしない

文字列を指定桁数まで0で埋める処理は、元の仕様が分かっているときに使います。例えば備品コードは5桁固定、という業務ルールが確認済みなら、そのルールに沿った整形を検討できます。しかし42という値を見ただけでは、元が042、0042、00042のどれだったかは分かりません。

CSVで「00042」を引用符で囲めば、どのアプリでも文字列になる、とは考えないでください。CSVの引用符には、区切り文字や改行を値の中に含めるといった役割があります。受け取るアプリの列型の判断まで一律に固定できるわけではないため、実際の取り込み条件を確認します。

Excelの表示形式で0を付けて見せることと、保存されている値がコードとして保たれていることも区別します。見た目が00042でも、中身が数値42のままなら、別のシステムへ渡した際に同じ表記にならない可能性があります。受け渡しでは、表示だけでなく再読込した文字列を確認してください。

長い管理番号についても、失われた末尾を見た目の調整で戻したことにはできません。Microsoftの先頭ゼロと大きな数値の説明では、文字列としての取り込みや数値精度の注意点が案内されています。元の番号と照合することを優先しましょう。

数式の形にして文字列を表示させる小技を、汎用のCSV受け渡し方法にはしません。相手の処理が数式を値として扱うか、文字列として読むかなど、新たな条件が増えるからです。用途に合う形式と列型の指定を選び、データに余計な意味を持たせない方針から始めると説明しやすくなります。

架空データを往復させて、壊れない受け渡しを練習する

4行のデータから、残したい値を先に決める

練習のデータは備品コード、備品名、数量の三列です。コードは「00042」「00420」「12003」「09000」の四つを用意します。備品名には、通常の日本語に加え、カンマを含む「ラベル,小」を一つ入れます。単純な文字列分割でCSVを処理すると、この値を二つに分けてしまう問題に気づけます。

期待する結果は、四行のコードが順番も含めて同じこと、備品名が欠けないこと、数量の文字が保存前後で変わらないことです。この段階では数量を計算しません。「読み書きしたら元の値が保たれる」という一つの課題へ絞っています。集計や欠損処理を同時に入れると、不一致の原因が増えてしまいます。

表を目で見て分かったつもりにならず、期待値をリストとして書きます。コード00042が42になれば、見た目は似ていてもテストで違いが分かります。数量の列に空白や単位が混ざる別のテストは、この往復確認が通ってから追加できます。

この練習は、ファイルを新規作成しなくても始められます。StringIOで文字列をファイルのように扱い、csv.DictReaderとDictWriterで読み書きします。自分のパソコンのフォルダー構成に依存しにくく、既存ファイルを誤って上書きする心配を避けてコードの動作に集中できます。

標準ライブラリで読込・保存・再読込を確かめる

次のコードを、Python 3の実行環境で試します。追加ライブラリは使いません。原本の代わりになる文字列を読み、CSVとして書き出した文字列をもう一度読み、同じデータが得られるかを比較します。ここにある名称やコードは教材用なので、実務データのコピーは不要です。

import csv
import io

source = (
    'code,name,quantity\n'
    '00042,封筒,2\n'
    '00420,"ラベル,小",3\n'
    '12003,ファイル,1\n'
    '09000,仕切り,4\n'
)
expected_codes = ['00042', '00420', '12003', '09000']
rows = list(csv.DictReader(io.StringIO(source, newline='')))
assert [row['code'] for row in rows] == expected_codes
assert rows[1]['name'] == 'ラベル,小'

buffer = io.StringIO(newline='')
writer = csv.DictWriter(buffer, fieldnames=['code', 'name', 'quantity'])
writer.writeheader()
writer.writerows(rows)
saved_text = buffer.getvalue()

roundtrip = list(csv.DictReader(io.StringIO(saved_text, newline='')))
assert roundtrip == rows
assert [row['code'] for row in roundtrip] == expected_codes
assert len(roundtrip) == 4
print('往復確認OK:', [row['code'] for row in roundtrip])

for encoding in ['utf-8', 'utf-8-sig', 'cp932']:
    saved_bytes = saved_text.encode(encoding)
    restored = saved_bytes.decode(encoding)
    checked = list(csv.DictReader(io.StringIO(restored, newline='')))
    assert checked == rows
    print(encoding, '文字とコードの一致を確認')

前半のassertは、条件が違っていれば実行を止めるための学習用確認です。後半では、この架空データについて、選んだ文字コードでバイトへ変換し、同じ指定で読み戻して比較しています。実際の受け渡し先のExcelを操作したテストではなく、Python内の往復テストです。

この区別は大切です。三つの符号化で往復できても、すべての文字がcp932で表現できるとは言えません。また、同じ指定で読み戻せたことは、相手のアプリが自動で同じ指定を選ぶ証明ではありません。テストが確認した範囲を、そのまま結果の説明に使います。

実ファイルへ応用する場合は、元ファイルと別の出力先を使い、文字コードと改行の扱いを明示します。標準CSV資料に沿って、ファイルを開く際のnewline指定も確認してください。ここでは既存のファイルを保存し直すコードを省き、読み書きの原理と検算を先に練習します。

一か所だけ変えて、失敗に気づけるかを試す

正常な例を一度動かしたら、どんな間違いを検出できるかを調べます。コードを全部書き換える必要はありません。例えばwriterへ渡す前に、一行目のコードを整数にしてから文字列へ戻す処理を入れます。00042が42になり、期待したコードと一致しないことを確認できます。

ただし、比較する期待値まで一緒に変更してはいけません。元のrowsを書き換えたあと、そのrowsとの一致だけを調べると、誤った値を正解として受け入れてしまいます。最初に決めたexpected_codesとの比較を、出力の再読込後にも置くことが、こうした失敗を見つける助けになります。

文字コードのテストでは、utf-8-sigで作ったバイト列をutf-8として読み、最初の列名を調べてみます。どこに目印が残るかを観察すると、「列名は同じに見えるのに一致しない」という状態を理解しやすくなります。本番データに対して、無条件に先頭文字を削る処理へつなげないでください。

もう一つは、cp932に含まれない文字を備品名へ追加する練習です。例えば絵文字を使った場合、符号化が失敗することを確認できます。その際、エラーを無視して通すのではなく、受け渡し先が扱える文字や形式を確認する、という判断まで練習します。表示できるかどうかを実際の要件へ戻します。

自分の確認コードが気づいてほしい変更の例
一つだけ変える条件期待する観察次の判断
コードを数値へ変換00042と42の違いが出る識別列の型変換を見直す
BOM付き文字列を別指定で読込列名の先頭に差が出る場合を観察BOMに合った読込を使う
cp932にない文字を追加変換時にエラーで止まる対応文字と受渡し形式を相談
備品名へカンマを含める一つの値として保持されるsplitではなくCSV処理を使う

テストの目的は、失敗をなくしたように見せることではありません。値が変わったときに気づき、どこを戻せばよいかを判断することです。コードの説明を人に求める際も、「この値を保ちたい」「ここで検出したい」と渡すと、単なるエラー解消より具体的な相談になります。

pandasとExcelへ渡すときの条件をそろえる

pandasを使う段階では、コード列のdtypeを文字列として指定する方法を検討します。読み込んだ後にastypeで文字列へ変えるだけでは、すでに消えたゼロを復元できません。処理の入口で、識別列と計算する列を分ける考え方を持っておくと、ライブラリが変わっても応用できます。

また、文字列として読みたい値にNAなどが含まれる場合は、欠損値としての解釈も確認します。pandasの公式資料にあるkeep_default_naやna_valuesなどの設定は、列の意味に合わせて選ぶ項目です。すべての空欄を同じ扱いに変えてよいとは限らないので、小さなサンプルで結果を比べてください。

Excelで受け取る人には、取り込み時にコード列を文字列として扱う方法を共有します。Microsoftの公式資料では、テキストまたはCSVから取り込んで列型を文字列へ設定する方法が案内されています。自動データ変換の設定は対応する版があるため、相手の利用環境で使える機能を確認します。

相手が毎回ダブルクリックで開く運用なら、CSVのほかに文字列型を保持する形式で渡す選択肢も検討できます。ただし、別システムがCSVしか受け付けない場合は、都合だけで形式を変えません。相手の目的、必要な列、指定の文字コード、読込方法を一枚の受け渡しメモにまとめます。

そのメモには、例えば「code列は文字列」「先頭ゼロを含む5桁の架空コードでテスト済み」「備品名のカンマは一つの値」「文字コードは受け渡し先の指定に合わせる」「実データの処理前に原本を残す」と書けます。コードだけ渡すより、何を変えてはいけないかが伝わります。

学習を続けるための確認表とFAQ

今回の成果物は、動いたコードだけではありません。列の意味を書いたメモ、四段階の比較、期待値、失敗させたときの観察、相手へ渡す条件までが一組です。学習記録として残すと、次のCSVで似た問題が起きたときにも調べる入口ができます。

Pythonを始めたばかりなら、まず標準ライブラリの例を自分の言葉で説明できるところを目標にします。何となくpandasへ置き換えるより、どの列を文字列として守りたいかを言えるほうが、処理の意図が明確です。データの件数が増えたり、集計の要件が出たりした段階で、必要な道具を広げていきましょう。

学習順は社会人のPython・CSV入門、道具の選択は事務自動化のPower Query・Python・AI比較で整理できます。AIにコードの説明を頼むか、自分で処理を書く学習へ進むか迷う場合は、ChatGPT活用とPythonを学ぶ順番も参考になります。

講座や指導を検討するなら、ファイル操作、文字コード、例外処理、検算を自分の課題で相談できるかを確認します。スクールの受講範囲と本稿の練習内容が同じとは限りません。Python Winnerの受講前の確認点や無料相談で使う質問リストを読み、実際の講座内容や総額を確認したうえで比較してください。

Pythonの基礎から学び直し、コードを説明できるようになりたい人には、Python Winnerも比較候補です。公式案内ではPythonの基礎・応用を含むコースとマンツーマン指導を紹介しています(2026年10月2日確認)。このCSVの問題だけを直したい人は、先に原本・列型・文字コードの確認を進められます。本稿のサンプルを使った添削や手元の業務コードの相談が可能かは、契約前に確認してください。受講料の総額、指導回数、受講期限とともに、自分が学びたい範囲を比較しましょう。

【PythonWinner】

よくある質問

Q. CSVをUTF-8にすれば先頭ゼロは残りますか?
A.

文字コードと列の型は別の問題です。UTF-8で日本語が読めても、コード列が数値に変換されれば先頭ゼロは失われます。読み込みから受け渡し先まで列型を確認します。

Q. Pythonのcsvモジュールも数値へ自動変換しますか?
A.

通常のcsv.readerは値を文字列として返します。特別なオプションや、その後に自分で書いた数値変換を確認してください。pandasなど別の読込処理とは区別して調べます。

Q. 消えたゼロをzfillで戻してよいですか?
A.

元のコードが何桁であるかを仕様や原本から確認できる場合に整形を検討します。元の桁数が分からない値へ一律にゼロを足して、復元できたとは判断しません。

Q. 引用符で囲った00042がExcelで42になるのはなぜですか?
A.

CSVの引用符は、受け取るアプリの列型を一律に固定するものではありません。Excelの取り込み方法で文字列として扱い、元の値と照合してください。

Q. 往復テストが通れば、そのCSVを配ってよいですか?
A.

Python内で確認した範囲に加え、受け渡し先のアプリやシステムでもサンプルを取り込んで確認します。列名、行数、コード、日本語、区切りを含む値を比べてから判断します。

先頭ゼロを守るには、最後に0を足すより、どこで文字列が数値へ変わったかを見つけることが先です。原本を残し、小さな期待値で読み書きを確認し、受け渡し先まで同じ値かを比べる。この手順を一度作れば、CSVのトラブルを説明しながら直す練習になります。