企業のデータ統合やシステム間連携において、Excelファイルは最も広く利用されているデータ媒体の一つです。しかし、Excel内の業務データをWebアプリケーション、モバイルアプリ、マイクロサービスAPIにインポートする場合、Excelのバイナリ形式はそのままの転送や解析には適していません。JSONは軽量なデータ交換フォーマットとして、API通信やデータ保存のデファクトスタンダードとなっています。Excelのデータを一つずつ手作業でJSONに入力する方法は非効率であるだけでなく、特に大量データや複数ファイルを一括処理する際にはミスも発生しやすくなります。
プログラミングによってExcelをJSONに変換することで、バッチ処理による自動化されたデータ抽出と構造化出力が実現でき、表の行データを標準的なキーバリュー構造にマッピングし、RESTful APIでの転送、データベースへの保存、フロントエンドでの直接利用が容易になります。
本記事では、Javaを使用してExcelファイルからデータを読み取り、構造化されたJSON形式に変換して出力する方法を紹介します。全体のプロセスは高度に自動化されており、データ移行、帳票エクスポート、システム間連携などの場面に適用できます。
本記事では Free Spire.XLS for Java を使用します。Maven経由でインストールできます:
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.xls.free</artifactId>
<version>16.3.1</version>
</dependency>
1. サンプルExcelファイルの作成
全体の流れを完全に演示するため、まず従業員情報を含むExcelファイルを作成し、企業の人事データ表を模擬します:
import com.spire.xls.*;
public class CreateSampleExcel {
public static void main(String[] args) {
// 1 ワークブックを作成し、最初のワークシートを取得
Workbook workbook = new Workbook();
Worksheet sheet = workbook.getWorksheets().get(0);
sheet.setName("従業員情報");
// 2 ヘッダーを書き込む
sheet.get(1, 1).setText("社員番号");
sheet.get(1, 2).setText("氏名");
sheet.get(1, 3).setText("部署");
sheet.get(1, 4).setText("役職");
sheet.get(1, 5).setText("入社日");
sheet.get(1, 6).setText("月額給与(円)");
// ヘッダーを太字に設定
for (int col = 1; col <= 6; col++) {
sheet.get(1, col).getStyle().getFont().isBold(true);
}
// 3 従業員データを書き込む
sheet.get(2, 1).setText("EMP001");
sheet.get(2, 2).setText("田中太郎");
sheet.get(2, 3).setText("技術部");
sheet.get(2, 4).setText("シニアエンジニア");
sheet.get(2, 5).setText("2019-03-15");
sheet.get(2, 6).setNumberValue(550000);
sheet.get(3, 1).setText("EMP002");
sheet.get(3, 2).setText("佐藤美咲");
sheet.get(3, 3).setText("営業部");
sheet.get(3, 4).setText("営業マネージャー");
sheet.get(3, 5).setText("2020-07-01");
sheet.get(3, 6).setNumberValue(480000);
sheet.get(4, 1).setText("EMP003");
sheet.get(4, 2).setText("鈴木健一");
sheet.get(4, 3).setText("経理部");
sheet.get(4, 4).setText("経理主任");
sheet.get(4, 5).setText("2018-11-20");
sheet.get(4, 6).setNumberValue(520000);
sheet.get(5, 1).setText("EMP004");
sheet.get(5, 2).setText("高橋麻衣");
sheet.get(5, 3).setText("人事部");
sheet.get(5, 4).setText("人事担当");
sheet.get(5, 5).setText("2021-05-10");
sheet.get(5, 6).setNumberValue(380000);
sheet.get(6, 1).setText("EMP005");
sheet.get(6, 2).setText("渡辺大輔");
sheet.get(6, 3).setText("技術部");
sheet.get(6, 4).setText("フロントエンド開発");
sheet.get(6, 5).setText("2022-01-08");
sheet.get(6, 6).setNumberValue(450000);
// 4 列幅を自動調整
sheet.getAllocatedRange().autoFitColumns();
// 5 ファイルを保存
String outputFile = "EmployeeData.xlsx";
workbook.saveToFile(outputFile, ExcelVersion.Version2013);
workbook.dispose();
System.out.println("Excelファイルを作成しました:" + outputFile);
}
}
説明:
-
Workbookは新しいExcelワークブックオブジェクトを作成します。デフォルトで3つのワークシートが含まれます -
getWorksheets().get(0)で最初のワークシートを取得します -
get(row, col)で行列インデックスを使って指定セルにアクセスします -
setText()でテキストデータ、setNumberValue()で数値データを設定します -
getStyle().getFont().isBold(true)でセルのフォントを太字に設定します -
getAllocatedRange().autoFitColumns()で全ての列幅を内容に合わせて自動調整します
この手順で5名の従業員情報を含むExcelファイルを作成し、後続のJSON変換用のソースデータとします。
2. ワークシート全体をJSON配列に変換する
次に、先ほど作成したExcelファイルを読み込み、ワークシートの各行データをJSONオブジェクトにマッピングします。最初の行をフィールド名(キー名)として使用し、最終的にJSON配列として出力します:
import com.spire.xls.*;
import com.spire.data.table.DataTable;
public class ExcelToJsonArray {
public static void main(String[] args) {
String inputFile = "EmployeeData.xlsx";
String outputFile = "EmployeeData.json";
// 1 Excelファイルを読み込む
Workbook workbook = new Workbook();
workbook.loadFromFile(inputFile);
// 2 最初のワークシートを取得
Worksheet sheet = workbook.getWorksheets().get(0);
// 3 ワークシートのデータをDataTableとしてエクスポート
DataTable dataTable = sheet.exportDataTable();
int rowCount = dataTable.getRows().size();
int colCount = dataTable.getColumns().size();
// 4 JSON配列を構築
StringBuilder jsonBuilder = new StringBuilder();
jsonBuilder.append("[\n");
for (int i = 0; i < rowCount; i++) {
jsonBuilder.append(" {\n");
for (int j = 0; j < colCount; j++) {
String columnName = dataTable.getColumns().get(j).getCaption();
String cellValue = dataTable.getRows().get(i).getString(j);
// 値が数値かどうかを判定し、引用符の有無を決定
jsonBuilder.append(" \"").append(escapeJson(columnName)).append("\": ");
if (isNumeric(cellValue)) {
jsonBuilder.append(cellValue);
} else {
jsonBuilder.append("\"").append(escapeJson(cellValue)).append("\"");
}
if (j < colCount - 1) {
jsonBuilder.append(",");
}
jsonBuilder.append("\n");
}
jsonBuilder.append(" }");
if (i < rowCount - 1) {
jsonBuilder.append(",");
}
jsonBuilder.append("\n");
}
jsonBuilder.append("]");
// 5 JSONファイルに書き込む
try (java.io.FileWriter writer = new java.io.FileWriter(outputFile)) {
writer.write(jsonBuilder.toString());
} catch (Exception e) {
e.printStackTrace();
}
workbook.dispose();
System.out.println("JSONファイルを生成しました:" + outputFile);
}
// 文字列が数値かどうかを判定
private static boolean isNumeric(String str) {
if (str == null || str.isEmpty()) return false;
try {
Double.parseDouble(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
// JSONの特殊文字をエスケープ
private static String escapeJson(String value) {
if (value == null) return "";
return value.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
}
説明:
-
loadFromFile()でディスクからExcelファイルを読み込みます -
exportDataTable()でワークシート全体のデータをDataTableオブジェクトとしてエクスポートします。最初の行は自動的に列名として使用されます -
getColumns().get(j).getCaption()で列名を取得し、JSONのキー名として使用します -
getRows().get(i).getString(j)で指定した行列のセル値を取得します -
isNumeric()ヘルパーメソッドで値が数値かどうかを判定し、数値型はJSON内で引用符を付けません -
escapeJson()でJSONの特殊文字をエスケープ処理し、出力フォーマットの正確性を確保します
変換結果:
[
{
"社員番号": "EMP001",
"氏名": "田中太郎",
"部署": "技術部",
"役職": "シニアエンジニア",
"入社日": "2019-03-15",
"月額給与(円)": 550000.0
},
{
"社員番号": "EMP002",
"氏名": "佐藤美咲",
"部署": "営業部",
"役職": "営業マネージャー",
"入社日": "2020-07-01",
"月額給与(円)": 480000.0
}
]
上記は最初の2件のみを表示しています。完全な出力には全5名の従業員データが含まれます。各レコードはヘッダーの日本語をJSONキー名として使用し、数値型のフィールドには引用符を付けません。
3. 指定範囲のデータをJSONオブジェクトに変換する
ワークシートにタイトル行や集計行が含まれている場合など、特定範囲のデータのみを抽出したいことがあります。以下の例では、ヘッダー行をスキップしてデータを選択的に抽出し、ドキュメントレベルのメタ情報を追加して、ネストされたJSON構造を生成する方法を示します:
import com.spire.xls.*;
import com.spire.data.table.DataTable;
import com.spire.xls.ExportTableOptions;
public class ExcelToNestedJson {
public static void main(String[] args) {
String inputFile = "EmployeeData.xlsx";
String outputFile = "EmployeeReport.json";
// 1 Excelファイルを読み込む
Workbook workbook = new Workbook();
workbook.loadFromFile(inputFile);
// 2 最初のワークシートを取得
Worksheet sheet = workbook.getWorksheets().get(0);
// 3 ExportTableOptionsでエクスポートオプションを設定
ExportTableOptions options = new ExportTableOptions();
options.setKeepDataFormat(true);
// 2行目からエクスポート開始(ヘッダーをスキップ)、最終データ行・列まで
int startRow = 2;
int startCol = 1;
int endRow = sheet.getLastDataRow();
int endCol = sheet.getLastDataColumn();
DataTable dataTable = sheet.exportDataTable(startRow, startCol, endRow, endCol, options);
int rowCount = dataTable.getRows().size();
int colCount = dataTable.getColumns().size();
// 4 フィールドマッピングを手動で定義(列名 → JSONキー名)
String[] fieldNames = {"employeeId", "name", "department", "position", "hireDate", "salary"};
// 5 ネストされたJSON構造を構築
StringBuilder json = new StringBuilder();
json.append("{\n");
json.append(" \"report_name\": \"従業員情報レポート\",\n");
json.append(" \"sheet_name\": \"").append(sheet.getName()).append("\",\n");
json.append(" \"total_records\": ").append(rowCount).append(",\n");
json.append(" \"employees\": [\n");
for (int i = 0; i < rowCount; i++) {
json.append(" {\n");
for (int j = 0; j < colCount; j++) {
String key = (j < fieldNames.length) ? fieldNames[j] : "field_" + j;
String value = dataTable.getRows().get(i).getString(j);
json.append(" \"").append(key).append("\": ");
if (isNumeric(value)) {
json.append(value);
} else {
json.append("\"").append(escapeJson(value)).append("\"");
}
if (j < colCount - 1) {
json.append(",");
}
json.append("\n");
}
json.append(" }");
if (i < rowCount - 1) {
json.append(",");
}
json.append("\n");
}
json.append(" ]\n");
json.append("}");
// 6 JSONファイルに書き込む
try (java.io.FileWriter writer = new java.io.FileWriter(outputFile)) {
writer.write(json.toString());
} catch (Exception e) {
e.printStackTrace();
}
workbook.dispose();
System.out.println("ネストJSONを生成しました:" + outputFile);
}
private static boolean isNumeric(String str) {
if (str == null || str.isEmpty()) return false;
try {
Double.parseDouble(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
private static String escapeJson(String value) {
if (value == null) return "";
return value.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
}
説明:
-
ExportTableOptionsでエクスポートオプションを設定します。setKeepDataFormat(true)で元のデータ書式を保持します -
getLastDataRow()とgetLastDataColumn()でデータの最終行・列の位置を自動取得し、範囲の手動計算を不要にします -
exportDataTable(startRow, startCol, endRow, endCol, options)で指定した矩形範囲のデータをエクスポートします -
fieldNames配列でExcelの列を英語のJSONキー名にマッピングし、APIインターフェース仕様に適合させます - 出力構造には
report_name、sheet_name、total_recordsなどのメタ情報フィールドが含まれ、ネスト構造を形成します
変換結果:
{
"report_name": "従業員情報レポート",
"sheet_name": "従業員情報",
"total_records": 5,
"employees": [
{
"employeeId": "EMP001",
"name": "田中太郎",
"department": "技術部",
"position": "シニアエンジニア",
"hireDate": "2019-03-15",
"salary": 550000.0
},
{
"employeeId": "EMP002",
"name": "佐藤美咲",
"department": "営業部",
"position": "営業マネージャー",
"hireDate": "2020-07-01",
"salary": 480000.0
}
]
}
上記は最初の2件の従業員レコードのみを表示しています。出力構造にはドキュメントレベルのメタ情報フィールドが含まれ、フィールド名はキャメルケースの英語命名を採用しているため、APIレスポンスとして直接使用するのに適しています。
4. 複数ワークシートを一括でJSONに変換する
Excelファイルに複数のワークシートが含まれている場合、すべてのワークシートを走査し、各ワークシートのデータを個別に変換して一つのJSONファイルに統合できます:
import com.spire.xls.*;
import com.spire.data.table.DataTable;
public class MultiSheetToJson {
public static void main(String[] args) {
String inputFile = "MultiSheetData.xlsx";
String outputFile = "AllSheetsData.json";
// 1 複数ワークシートを含むExcelファイルを作成
Workbook sourceWorkbook = new Workbook();
// 最初のワークシート - 売上データ
Worksheet sheet1 = sourceWorkbook.getWorksheets().get(0);
sheet1.setName("売上データ");
sheet1.get(1, 1).setText("商品名");
sheet1.get(1, 2).setText("販売数量");
sheet1.get(1, 3).setText("売上金額");
sheet1.get(2, 1).setText("ノートPC");
sheet1.get(2, 2).setNumberValue(1250);
sheet1.get(2, 3).setNumberValue(187500000);
sheet1.get(3, 1).setText("タブレット");
sheet1.get(3, 2).setNumberValue(890);
sheet1.get(3, 3).setNumberValue(80100000);
// 2番目のワークシート - 在庫データ
Worksheet sheet2 = sourceWorkbook.getWorksheets().add("在庫データ");
sheet2.get(1, 1).setText("商品名");
sheet2.get(1, 2).setText("在庫数");
sheet2.get(1, 3).setText("倉庫場所");
sheet2.get(2, 1).setText("ノートPC");
sheet2.get(2, 2).setNumberValue(350);
sheet2.get(2, 3).setText("Aエリア-01");
sheet2.get(3, 1).setText("タブレット");
sheet2.get(3, 2).setNumberValue(280);
sheet2.get(3, 3).setText("Bエリア-03");
sourceWorkbook.saveToFile(inputFile, ExcelVersion.Version2013);
sourceWorkbook.dispose();
// 2 読み込んで全ワークシートを走査
Workbook workbook = new Workbook();
workbook.loadFromFile(inputFile);
StringBuilder json = new StringBuilder();
json.append("{\n");
int sheetCount = workbook.getWorksheets().getCount();
for (int s = 0; s < sheetCount; s++) {
Worksheet sheet = workbook.getWorksheets().get(s);
String sheetName = sheet.getName();
DataTable dataTable = sheet.exportDataTable();
int rowCount = dataTable.getRows().size();
int colCount = dataTable.getColumns().size();
json.append(" \"").append(escapeJson(sheetName)).append("\": [\n");
for (int i = 0; i < rowCount; i++) {
json.append(" {\n");
for (int j = 0; j < colCount; j++) {
String key = dataTable.getColumns().get(j).getCaption();
String value = dataTable.getRows().get(i).getString(j);
json.append(" \"").append(escapeJson(key)).append("\": ");
if (isNumeric(value)) {
json.append(value);
} else {
json.append("\"").append(escapeJson(value)).append("\"");
}
if (j < colCount - 1) json.append(",");
json.append("\n");
}
json.append(" }");
if (i < rowCount - 1) json.append(",");
json.append("\n");
}
json.append(" ]");
if (s < sheetCount - 1) json.append(",");
json.append("\n");
}
json.append("}");
// 3 JSONファイルに書き込む
try (java.io.FileWriter writer = new java.io.FileWriter(outputFile)) {
writer.write(json.toString());
} catch (Exception e) {
e.printStackTrace();
}
workbook.dispose();
System.out.println("複数シートのJSONを生成しました:" + outputFile);
}
private static boolean isNumeric(String str) {
if (str == null || str.isEmpty()) return false;
try {
Double.parseDouble(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
private static String escapeJson(String value) {
if (value == null) return "";
return value.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
}
説明:
-
getWorksheets().getCount()でワークブック内のワークシート総数を取得します -
getWorksheets().add("名称")で新しいワークシートを追加します - 各ワークシートのデータはワークシート名をキーとして、JSONオブジェクトのプロパティに整理されます
- この方法は多次元データの集計に適しており、例えば売上・在庫・経理など異なるワークシートを同時に含む場合に有効です
出力結果例:
{
"売上データ": [
{
"商品名": "ノートPC",
"販売数量": 1250.0,
"売上金額": 187500000.0
},
{
"商品名": "タブレット",
"販売数量": 890.0,
"売上金額": 80100000.0
}
],
"在庫データ": [
{
"商品名": "ノートPC",
"在庫数": 350.0,
"倉庫場所": "Aエリア-01"
},
{
"商品名": "タブレット",
"在庫数": 280.0,
"倉庫場所": "Bエリア-03"
}
]
}
各ワークシートのデータはワークシート名をキーとして、独立したJSON配列に整理されており、ビジネスディメンションごとに個別に利用しやすくなっています。
適用シーン:
- 企業の月次総合レポートで、異なるディメンションのデータをJSONとして統一出力
- プロジェクト管理システムにおける複数ワークシートデータの統一APIレスポンス
- 部門横断的なデータ集約で、各部門の独立ワークシートを統一データ形式に統合
5. 主要クラスとメソッドの解説
コアクラスの説明
Workbook クラス
Workbook はExcel操作のエントリーポイントであり、一つのExcelファイル全体を表します。
主要メソッド:
| メソッド | 説明 |
|---|---|
new Workbook() |
新しいワークブックインスタンスを作成 |
loadFromFile(path) |
指定パスからExcelファイルを読み込む |
saveToFile(path, version) |
ワークブックをExcelファイルとして保存 |
getWorksheets() |
ワークブック内の全ワークシートコレクションを取得 |
dispose() |
ワークブックが占有するリソースを解放 |
Worksheet クラス
Worksheet はExcelの個々のワークシートを表し、データ操作の主要なオブジェクトです。
主要メソッドとプロパティ:
| メソッド / プロパティ | 説明 |
|---|---|
get(row, col) |
行列インデックスで指定セルを取得 |
getRange() |
ワークシートのセル範囲オブジェクトを取得 |
getCellRange(row1, col1, row2, col2) |
指定した矩形領域のセル範囲を取得 |
getName() / setName(name)
|
ワークシート名の取得・設定 |
exportDataTable() |
ワークシート全体をDataTableとしてエクスポート |
exportDataTable(startRow, startCol, endRow, endCol, options) |
指定範囲をDataTableとしてエクスポート |
getLastDataRow() |
最終データ行の行番号を取得 |
getLastDataColumn() |
最終データ列の列番号を取得 |
getAllocatedRange().autoFitColumns() |
全ての列幅を自動調整 |
DataTable クラス
DataTable はワークシートからエクスポートされたテーブルデータを格納します。
主要メソッドとプロパティ:
| メソッド / プロパティ | 説明 |
|---|---|
getRows() |
データ行コレクションを取得 |
getRows().size() |
データ行数を取得 |
getRows().get(i).getString(j) |
第i行第j列の値(文字列)を取得 |
getColumns() |
データ列コレクションを取得 |
getColumns().size() |
データ列数を取得 |
getColumns().get(j).getCaption() |
第j列の列名を取得 |
ExportTableOptions クラス
ExportTableOptions はデータエクスポートのオプションを設定します。
主要プロパティ:
| プロパティ | 説明 |
|---|---|
setKeepDataFormat(boolean) |
元のデータ書式を保持するかどうか |
setRenameStrategy(strategy) |
列名が重複した場合のリネーム戦略を設定 |
使用上のアドバイス:
- 元のExcelに日付、パーセンテージなどの特殊書式が含まれる場合は、
setKeepDataFormat(true)を有効にすることを推奨します - 単純なテキストや数値データの場合は、引数なしの
exportDataTable()メソッドを直接使用できます
まとめ
本記事のサンプルを通じて、Javaを使用してExcelファイルをJSON形式に変換する方法を理解いただけたと思います。サンプルデータの作成、ワークシート全体の変換、指定範囲のネスト構造出力、そして複数ワークシートの一括処理まで、全体のプロセスは高度に自動化されており、データ移行、API連携、帳票エクスポートなどの場面に特に適しています。
手作業でのコピー&ペーストやオンライン変換ツールに依存する方法と比較して、Javaコードベースのアプローチには以下の利点があります:
- 柔軟性が高い:JSON構造、フィールドマッピング、出力フォーマットを自由にカスタマイズできる
- バッチ処理が効率的:複数ワークシートや複数ファイルの自動変換をサポート
- データを完全に制御:指定範囲のデータを選択的に抽出し、不要な内容をフィルタリングできる
- 統合が容易:Spring BootなどのJavaフレームワークに組み込んで、データインターフェースの一部として活用可能
これを基盤として、GsonやJacksonライブラリを組み合わせてより仕様に準拠したJSONを生成する、データフィルタリングやクレンジングのロジックを追加する、RESTful APIに統合してリアルタイムデータクエリを実現するなど、さらなる拡張が可能です。
Excelデータの構造化抽出やシステム連携のニーズに対応する場合、このJavaベースのソリューションは業務効率を大きく向上させます。より詳細な機能については、Free Spire.XLS for Java 公式ドキュメントをご参照ください。