0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Python を使用して JSON を Excel に変換する

0
Posted at

Web API の応答、各種サービスのエクスポート、設定ファイルやログの保管形式として、JSON は今やデータ交換の標準になっています。人が直接目を通すにはテキストのままよりも、表として Excel に展開したほうが格段に見やすく、フィルターや並べ替えもそのまま使えます。本記事では、Python で JSON を読み込み、Excel ブックとして書き出す一連の流れを整理します。

JSON を扱うだけなら Python 標準ライブラリの json モジュールで事足りますが、そこから Excel ファイルを生成するには専用のライブラリが必要です。Spire.XLS を使えば、ワークブックの作成からセルへの書き込み、.xlsx としての保存までを一貫して行えます。以下では、まず JSON の読み込みと Excel への書き出しの基本を確認します。

必要なライブラリのインストール

本記事では Spire.XLS for Python を使用します。Workbook オブジェクトを中心に、JSON から取り出したデータを行・列のセルへ配置します。以下のコマンドでインストールしてください。

pip install Spire.XLS

インストール後、スクリプト内でモジュールをインポートします。

from spire.xls import *
from spire.xls.common import *

JSON を読み込んで Excel に書き出す基本の流れ

変換の出発点は、JSON ファイルを Python のデータ構造へ読み込むことです。標準ライブラリ json の load() を使えば、ファイルから辞書やリストをそのまま復元できます。その後は、Workbook を作成して Worksheets[0] を取り出し、セルへ値を書き込んで SaveToFile() で保存します。

import json
from spire.xls import *
from spire.xls.common import *

inputFile = "data.json"
outputFile = "data.xlsx"

# JSON ファイルを読み込む(標準ライブラリ json を使用)
with open(inputFile, "r", encoding="utf-8") as f:
    records = json.load(f)

# ワークブックを作成し、最初のシートを取得
workbook = Workbook()
sheet = workbook.Worksheets[0]

# 1 件目のレコードからキーを取り出してヘッダー行に書く
headers = list(records[0].keys())
for col, key in enumerate(headers, start=1):
    sheet.Range[1, col].Text = key

# 各レコードを 1 行ずつ書き込む
for row, record in enumerate(records, start=2):
    for col, key in enumerate(headers, start=1):
        sheet.Range[row, col].Text = str(record.get(key, ""))

# Excel 形式で保存
workbook.SaveToFile(outputFile, ExcelVersion.Version2013)
workbook.Dispose()

セルへのアクセスは sheet.Range[行, 列] の形で行います。引数はいずれも 1 から始まる番号であり、Range[1, 1] が A1 セルに相当します。ヘッダー行を 1 行目に置き、データを 2 行目以降に順に並べるのが、最も一般的な配置です。値は Text プロパティに文字列として代入するため、数値や日付であっても str() で一度文字列化しています。

レコードのリスト(辞書の配列)をそのまま表にする

多くの実務データは、同じキーを持つ辞書のリストという形をしています。API の一覧取得や、データベースの抽出結果を JSON にしたものがこれに当たります。前節の書き方はまさにこの形状を想定しており、キー名をそのまま列名(ヘッダー)として活用できるため、余計なマッピング表を作る必要がありません。

import json
from spire.xls import *
from spire.xls.common import *

inputFile = "users.json"
outputFile = "users.xlsx"

with open(inputFile, "r", encoding="utf-8") as f:
    records = json.load(f)

workbook = Workbook()
sheet = workbook.Worksheets[0]

# 列の順序を固定したい場合は、キーを明示的に並べる
columns = ["id", "name", "email", "department"]
for col, name in enumerate(columns, start=1):
    sheet.Range[1, col].Text = name

for row, record in enumerate(records, start=2):
    for col, name in enumerate(columns, start=1):
        value = record.get(name, "")
        sheet.Range[row, col].Text = "" if value is None else str(value)

workbook.SaveToFile(outputFile, ExcelVersion.Version2013)
workbook.Dispose()

列の順序を制御したい場合は、前節のように records[0].keys() を使う代わりに、出力したい順にキーを並べたリストを自分で用意します。欠落しているキーに対しては record.get(name, "") で空文字を返すようにしており、データの揃っていない JSON でも例外を出さずに処理できます。

ヘッダー行に書式を付ける

生成直後のシートは、ヘッダーとデータの区別が付きません。ヘッダー行だけを太字にし、必要なら文字色を変えると、そのまま共有できる表に近づきます。書式は Style.Font を通じて、ヘッダーの各セルに個別に設定します。

import json
from spire.xls import *
from spire.xls.common import *

# (中略:JSON の読み込みとデータの書き込み)

columns = ["id", "name", "email", "department"]
for col, name in enumerate(columns, start=1):
    sheet.Range[1, col].Text = name
    # ヘッダーセルを太字にし、文字色を付ける
    sheet.Range[1, col].Style.Font.IsBold = True
    sheet.Range[1, col].Style.Font.Color = Color.get_CadetBlue()

for row, record in enumerate(records, start=2):
    for col, name in enumerate(columns, start=1):
        sheet.Range[row, col].Text = str(record.get(name, ""))

IsBold を True にするとそのセルが太字になり、Color で文字色を指定できます。色は Color.get_CadetBlue() のように定義済みの値から取得します。ヘッダーだけを強調することで、データ行との境目が明確になり、一覧としての読みやすさが大きく向上します。

列幅を自動調整する

JSON から書き出したばかりのシートは、列幅が既定値のままです。内容によっては長い文字列が切り詰められて見えにくくなります。データが入っている範囲を対象に列幅を自動調整すると、配布に耐える見た目になります。

import json
from spire.xls import *
from spire.xls.common import *

# (中略:JSON の読み込みとデータの書き込み)

# データが存在する範囲の列幅を内容に合わせて広げる
sheet.AllocatedRange.AutoFitColumns()

workbook.SaveToFile(outputFile, ExcelVersion.Version2013)
workbook.Dispose()

AllocatedRange は、値が入力されている領域全体を表すプロパティです。行数や列数が変動する JSON でも、範囲を固定値で書かずに済むため便利です。AutoFitColumns() はその範囲に含まれる列の幅を、内容に応じて自動で広げます。

複数の JSON ファイルをまとめて変換する

同じ構造の JSON がフォルダに溜まっている場合、1 ファイルずつ処理するのは現実的ではありません。標準ライブラリの os と組み合わせれば、フォルダ内のファイルを順に Excel へ変換できます。

import json
import os
from spire.xls import *
from spire.xls.common import *

inputFolder = "./json_files"
outputFolder = "./excel_files"

if not os.path.exists(outputFolder):
    os.makedirs(outputFolder)

for name in os.listdir(inputFolder):
    if not name.lower().endswith(".json"):
        continue

    inputPath = os.path.join(inputFolder, name)
    outputPath = os.path.join(outputFolder, os.path.splitext(name)[0] + ".xlsx")

    with open(inputPath, "r", encoding="utf-8") as f:
        records = json.load(f)

    workbook = Workbook()
    sheet = workbook.Worksheets[0]

    columns = list(records[0].keys())
    for col, key in enumerate(columns, start=1):
        sheet.Range[1, col].Text = key
        sheet.Range[1, col].Style.Font.IsBold = True

    for row, record in enumerate(records, start=2):
        for col, key in enumerate(columns, start=1):
            sheet.Range[row, col].Text = str(record.get(key, ""))

    sheet.AllocatedRange.AutoFitColumns()
    workbook.SaveToFile(outputPath, ExcelVersion.Version2013)
    workbook.Dispose()

ポイントは、ループの中で毎回 Workbook を新しく作り、処理が終わるたびに Dispose() を呼ぶことです。多数のファイルを連続して処理する場合、リソースを解放せずに持ち続けるとメモリ使用量が増えていきます。拡張子の判定を lower() で行うことで、.JSON のように大文字で書かれたファイルも取りこぼしません。

実践的なヒント

  • ネストした JSON は事前に平坦化する。値が辞書やリストになっていると、str() で文字列化したときに {"a": 1} のような表記がそのままセルに入ります。階層をたどって必要な項目だけを取り出す処理を、JSON 読み込み直後に済ませると扱いやすくなります。
  • Range[行, 列] は 1 始まり。A1 が [1, 1] であり、Excel の表示と同じ番号でアクセスできます。ループの start を 1 に揃えると、ヘッダーとデータの行ずれを防げます。
  • Text には文字列を入れる。数値や日付をそのまま代入すると型の扱いが不安定になるため、明示的に str() で変換するか、書式を整えてから代入します。
  • ヘッダー強調は Style.Font で個別に。列数が動的に変わる場合でも、ヘッダー書き込みのループ内で IsBold を立てれば、範囲を固定で書かずに済みます。
  • エンコーディングを明示する。open() に encoding="utf-8" を指定すれば、日本語を含む JSON でも文字化けを防げます。

まとめ

本記事では、Python を使って JSON を Excel に変換する手順を整理しました。

  • 標準ライブラリ json の load() で JSON を読み込み、辞書やリストとして扱う
  • Workbook を作成し、Worksheets[0] の Range[行, 列].Text へ値を書き込む(引数は 1 始まり)
  • レコードのリスト(辞書の配列)を想定し、キーをヘッダー、各レコードを 1 行として展開する
  • Style.Font.IsBold でヘッダー行を強調し、AllocatedRange.AutoFitColumns() で列幅を整える
  • os と組み合わせれば、フォルダ内の JSON を一括変換できる

JSON はそのままでは人に見せにくい形式ですが、Excel へ展開すればフィルターや集計もそのまま使えます。まずは 1 ファイルで流れを確認し、必要に応じて列の順序固定やバッチ処理へ広げていくのが進めやすいでしょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?