PhpSpreadsheetで先頭ゼロを保持する方法:文字列型とゼロ埋め表示の違い
作成日:2026.10.26
PhpSpreadsheetで商品コードなどの先頭ゼロを保持する方法を解説します。文字列型での保存と、数値の表示形式によるゼロ埋めを比較し、XLSXの再読み込みで値・型・表示の違いを確認します。長い番号や「=」で始まる文字列を出力する際の注意点も紹介します。
目次
PhpSpreadsheetで商品コードなどをExcelへ出力するとき、00123のような先頭ゼロを残したいことがあります。ここで分けて考えたいのが、「文字列として00123を保存すること」と「数値の123を00123と表示すること」です。
商品コードそのものを保持したいならデータ型としての文字列、数値を決まった桁数で表示したいならデータ型は数値のままで表示形式を設定して使います。今回はこの違いを、XLSXへの保存と再読み込みで比べてみます。
文字列と表示形式は役割が違う
セルには値とデータ型があり、それとは別に表示形式があります。例えば次の2つは、どちらも見た目を00123にできますが、保存する値が違います。
| 方法 | 保存する値 | セルの型 | 表示形式 |
|---|---|---|---|
| 文字列として保存 | 00123 | 文字列 | 標準(General) |
| 数値をゼロ埋め表示 | 123 | 数値 | 00000 |
別のシステムへ渡したり、商品コードとして照合したりするなら、先頭ゼロも値の一部として残したいですね。一方、計算に使う数値の見た目を5桁にそろえるなら、表示形式の出番です。
表示形式は元の桁数を記録するものではありません。数値に変換された123だけを見ても、元が123、00123、000123のどれだったかは分かりません。
XLSXへ保存する
以下はPHP 8.3.36・PhpSpreadsheet 5.10.0で確認したCLI用のサンプルです。PhpSpreadsheetはComposerで導入済みとし、vendorディレクトリと同じ場所へPHPファイルを置きます。導入の流れはComposerでPhpSpreadsheetをインストールする記事を参照してください。過去記事のPHPバージョン設定は流用せず、必要なPHPや拡張はPhpSpreadsheet公式の動作要件で確認してください。
create.phpとして保存します。書き込み可能な作業ディレクトリで実行すると、同じ場所へcodes.xlsxを出力します。同名ファイルがある場合は上書きするので、サンプル専用の場所で試してください。
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// A1:商品コードを文字列型で保存する。
$sheet->setCellValueExplicit('A1', '00123', DataType::TYPE_STRING);
// B1:数値の123を、5桁で表示する。
$sheet->setCellValue('B1', 123);
$sheet->getStyle('B1')->getNumberFormat()->setFormatCode('00000');
// C1:型を指定せず、既定の値バインダーで書く比較用。
$sheet->setCellValue('C1', '00123');
// 長い番号や、等号で始まる文字列も型を明示して保存する。
$sheet->setCellValueExplicit('A2', '00012345678901234567', DataType::TYPE_STRING);
$sheet->setCellValueExplicit('A3', '12345678901234567', DataType::TYPE_STRING);
$sheet->setCellValueExplicit('A4', '=1+1', DataType::TYPE_STRING);
foreach (['A', 'B', 'C'] as $column) {
$sheet->getColumnDimension($column)->setWidth(28);
}
$writer = new Xlsx($spreadsheet);
$writer->save(__DIR__ . '/codes.xlsx');
$spreadsheet->disconnectWorksheets();
php create.php
文字列型を明示するのがsetCellValueExplicit()とDataType::TYPE_STRINGの組み合わせです。表示形式を文字列へ変更するだけではなく、セルへ書き込む時点で型を指定しています。
B1の00000は、少なくとも5桁になるよう先頭にゼロを表示する指定です。保存値は123のままですし、6桁以上の数値を5桁へ切り詰める指定でもありません。
setCellValue()なら必ずゼロが消えるわけではない
C1は、通常のsetCellValue()で文字列の'00123'を渡す例です。既定の値バインダーでは、このような先頭ゼロのある整数形式の文字列は文字列型として扱われます。通常のメソッドを使うと必ず先頭ゼロが消える、というわけではありません。
ただし、'123'のような数値に見える文字列は数値型になるなど、入力に応じた型の判定が入ります。商品コードの列として一貫して文字列を保存したい場合は、型を明示する方が意図を伝えやすいかと思います。値バインダーを変更している環境では挙動も確認してください。詳細は公式ドキュメントのセル値とデータ型の説明を参照。
再読み込みして値と型を比べる
次はinspect.phpとして保存し、作成したファイルを読み直します。表示形式も調べたいので、setReadDataOnly(true)は指定せず、通常の読み込みを使います。
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\IOFactory;
$spreadsheet = IOFactory::load(__DIR__ . '/codes.xlsx');
$sheet = $spreadsheet->getActiveSheet();
foreach (['A1', 'B1', 'C1', 'A2', 'A3', 'A4'] as $address) {
$cell = $sheet->getCell($address);
$result = [
'cell' => $address,
'value' => $cell->getValue(),
'type' => $cell->getDataType(),
'format' => $cell->getStyle()->getNumberFormat()->getFormatCode(),
'formatted' => $cell->getFormattedValue(),
];
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR), PHP_EOL;
}
$spreadsheet->disconnectWorksheets();
php inspect.php
getValue()はセルの値、getDataType()はセルの型を返します。ここでのsは文字列、nは数値です。getFormattedValue()は、PhpSpreadsheetが表示形式を適用した結果を返します。
| セル | 再読み込みした値 | 型 | 表示形式 | 整形後の値 |
|---|---|---|---|---|
| A1 | 00123 | s | General | 00123 |
| B1 | 123 | n | 00000 | 00123 |
| C1 | 00123 | s | General | 00123 |
| A2 | 00012345678901234567 | s | General | 00012345678901234567 |
| A3 | 12345678901234567 | s | General | 12345678901234567 |
| A4 | =1+1 | s | General | =1+1 |
上の表は、2026年10月26日にDocker上のLinux(x86_64)、PHP 8.3.36・PhpSpreadsheet 5.10.0で、保存したXLSXを再読み込みした結果です。A4はXLSX内部のXMLにも数式要素がなく、文字列として保存されていることを確認しました。
A1とB1は整形後の値が同じでも、getValue()と型が違います。読み込み先で商品コードを照合するなら、見た目だけでなく、どちらの値を使っているかも確認したいところです。
長い番号と等号で始まる入力
A2とA3は長い番号の例です。Excelの数値の精度は有効数字15桁なので、16桁以上の番号を識別子として保持するなら、文字列として扱います。詳しくはMicrosoftの先頭ゼロと長い番号の説明を参照してください。
PHP側でも、元データを数値へ変換しないことが大切です。(int)や(float)で変換した後に文字列へ戻しても、消えた先頭ゼロや失われた桁は復元できません。DBやCSVから受け取る段階も含めて、商品コードを文字列のまま渡すようにします。
A4の=1+1は、数式ではなく文字列として出力する例です。通常のsetCellValue()ではこの入力が数式として扱われるため、文字列型を明示しています。これはXLSXでの例であり、そのままCSV出力などの対策にもなるという意味ではありません。
Excelではセルの表示と数式バーも確認する
最後にcodes.xlsxをExcelで開き、A1とB1を選択して比べます。セルの表示はどちらも00123になる想定ですが、数式バーではA1が00123、B1が123となることを確認します。A2・A3は全桁、A4は計算結果の2ではなく=1+1が表示されるかを確認してください。
文字列として保存した番号には、Excelで「数値が文字列として保存されています」という警告が出る場合があります。商品コードとして文字列にしたのであれば、警告を消すために数値へ変換しないようにします。
商品コードは文字列として保持し、数値の見た目をそろえるときは表示形式を使う。この使い分けをしておくと、Excel上では同じに見えるのに、取り込んだ値が違う、といった問題を切り分けやすくなります。既存のテンプレートへ書き込む場合も考え方は同じです。読み込みと保存の基本はExcelテンプレートから新しいファイルを作る記事を参照してください。
奈良市を拠点に、27年以上の経験を持つフリーランスWebエンジニア、阿部辰也です。
これまで、ECサイトのバックエンド開発や業務効率化システム、公共施設の予約システムなど、多彩なプロジェクトを手がけ、企業様や制作会社様のパートナーとして信頼を築いてまいりました。
【制作会社・企業様向けサポート】
Webシステムの開発やサイト改善でお困りの際は、どうぞお気軽にご相談ください。小さな疑問から大規模プロジェクトまで、最適なご提案を心を込めてさせていただきます。
ぜひ、プロフィールやWeb制作会社様向け業務案内、一般企業様向け業務案内もご覧くださいね。
PhpSpreadsheetでExcelシートのタイトルを設定する方法
2023.05.22
PhpSpreadsheetを使ったExcel操作で、シートのタイトルを変更する方法をご紹介します。
PhpSpreadsheetでセルに自動改行を設定する方法
2023.05.21
PhpSpreadsheetを使用して、セル内のテキストを自動で改行させる設定方法を解説します。
PhpSpreadsheetでセルのフォントサイズを変更する方法
2023.05.20
PhpSpreadsheetを使って、特定のセルのフォントサイズを簡単に変更する方法を解説します。
PhpSpreadsheetでExcelの行の高さを設定する方法
2023.05.12
PhpSpreadsheetを使用して、特定の行の高さを簡単に変更する方法を紹介します。Excelファイルのレイアウトを調整する際に役立つ、行の高さ設定の基本的なコード例です。