📌

【学習ログ】Pythonを使ってJSONデータをExcelへ自動変換

2025/02/07に公開

今回は、Pythonスクリプトを通じて、JSONからExcelへの変換処理について学習したので、アウトプットとして記事を共有します。

ディレクトリ構成図

─ json_to_excel
    ├ input
    |   ├ sample1.json
    |   ├ sample2.json
    |   └ template.xlsx
    ├ output
    |   └output.xlsx(ない場合は自動的に作成されます)
    └ src
        └main.py

スクリプトの概要

このスクリプトは以下の機能を提供します。

  • 指定ディレクトリ内の全JSONファイルの読み込み
  • 不要な文字の除去
  • 特定のフォーマットでExcelへのデータ書き出し

実際のコード

import json
import os
from openpyxl import load_workbook, Workbook
from typing import List, Dict, Any
import re
from pathlib import Path
from dataclasses import dataclass

@dataclass
class Config:
    """基本設定を保持するデータクラス"""
    start_row: int = 22
    start_column: int = 4
    rows_per_item: int = 5

def clean_text(text: str) -> str:
    if not isinstance(text, str):
        text = str(text)
    return re.sub(r'[\000-\010]|[\013-\014]|[\016-\037]|[\x00-\x1f\x7f-\x9f]|[\uffff]', '', text)

def load_json_files(input_directory: str) -> List[Dict[str, Any]]:
    """ディレクトリ内のすべてのJSONファイルからデータを読み込む"""
    all_data = []
    
    try:
        # ディレクトリ内のすべてのファイルを取得
        json_files = [f for f in os.listdir(input_directory) if f.endswith('.json')]
        
        if not json_files:
            print(f"Error: {input_directory} にJSONファイルが見つかりません")
            return []
        
        # 各JSONファイルを読み込む
        for filename in json_files:
            file_path = os.path.join(input_directory, filename)
            try:
                with open(file_path, encoding='utf-8') as f:
                    file_data = json.load(f)
                    if isinstance(file_data, list):
                        all_data.extend(file_data)
                    else:
                        all_data.append(file_data)
                            
            except json.JSONDecodeError:
                print(f"Error: {filename} は有効なJSONファイルではありません")
            except Exception as e:
                print(f"Error: {filename} の読み込み中にエラーが発生しました - {e}")
        
        return all_data
    
    except Exception as e:
        print(f"Error: JSONファイルの読み込み中に予期せぬエラーが発生しました - {e}")
        return []

def write_to_excel(sheet, data: List[Dict[str, Any]], config: Config) -> None:
    """Excelシートにデータを書き込む"""
    for i, item in enumerate(data):
        base_row = (i * config.rows_per_item) + config.start_row
        
        # 質問と回答の書き込み
        sheet.cell(row=base_row, column=config.start_column, 
                  value=item.get('question', ''))
        sheet.cell(row=base_row, column=config.start_column + 4, 
                  value=item.get('answer', ''))
        
        # context_nameの書き込み
        context_names = item.get('context_name', [])
        if not isinstance(context_names, list):
            context_names = [context_names]
        
        for index, context in enumerate(context_names):
            sheet.cell(row=base_row + index, column=config.start_column + 5, 
                      value=clean_text(context))
        
        # contextの書き込み
        contexts = item.get('context', [])
        if not isinstance(contexts, list):
            contexts = [contexts]
        
        for index, context in enumerate(contexts):
            sheet.cell(row=base_row + index, column=config.start_column + 6, 
                      value=clean_text(context))

def main():
    # 基本設定
    config = Config()
    
    # パス設定
    input_directory = 'input'
    template_path = "input/template.xlsx"
    output_path = "output/output.xlsx"
    sheet_name = 'sheet1'
    
    # データの読み込み
    data = load_json_files(input_directory)
    if not data:
        print("処理するデータがありません。プログラムを終了します。")
        return
    
    # Excelファイルの処理
    try:
        workbook = load_workbook(template_path)
        sheet = workbook[sheet_name]
        
        # データの書き込み
        write_to_excel(sheet, data, config)
        
        # 保存
        Path(output_path).parent.mkdir(parents=True, exist_ok=True)
        workbook.save(output_path)
        print(f"処理完了: {output_path}{len(data)} 件のデータを書き出しました")
        
    except FileNotFoundError:
        print(f"Error: テンプレートファイル {template_path} が見つかりません")

if __name__ == "__main__":
    main()

ライブラリーのインストール手順

ライブラリをインストールするために以下のコマンドを入力します。

pip install openpyxl typing pathlib

インストールが完了したか確認するには

pip list

でインストールされたパッケージの一覧を確認することができます。

コード解説

ライブラリーの概要

import json
import os
from openpyxl import load_workbook
from typing import List, Dict, Any
import re
from pathlib import Path
from dataclasses import dataclass

これらのライブラリーは以下の目的で使用します:

  • json: JSONファイルの処理
  • openpyxl: Excel操作
  • typing: 型ヒントの提供
  • re: 正規表現による文字列処理
  • pathlib: モダンなファイルパス操作
  • dataclasses: データ構造の定義

クラスの定義

@dataclass
class Config:
    """基本設定を保持するデータクラス"""
    start_row: int = 22
    start_column: int = 4
    rows_per_item: int = 5

データクラスを用意して、Excel書き込みに関する基本設定を管理しています。
今回はフォーマットの記入開始位置がD列の22行目だったのでこのように設定しています。rows_per_itemは入力する間隔を設定できます。今回は5行ずつ値を入れていきます。

テキストクリーニング機能

def clean_text(text: str) -> str:
    """不正な文字を削除する"""
    if not isinstance(text, str):
        text = str(text)
    return re.sub(r'[\000-\010]|[\013-\014]|[\016-\037]|[\x00-\x1f\x7f-\x9f]|[\uffff]', '', text)

今回使用したjsonファイルにUnicode文字が含まれており、そのままExcelへ転記しようとするとエラーが発生したのでこのような機能を実装しました。

JSONファイルの読み込み

def write_to_excel(sheet, data: List[Dict[str, Any]], config: Config) -> None:

こちらのコードでは、inputフォルダ内にある、全てのjsonファイルを読み込んでいます。

メイン処理

def main():
    config = Config()
    # ... 省略 ...

メイン処理では:

  1. 設定の初期化
  2. データの読み込み
  3. Excelファイルの処理
  4. 結果の保存

を順番に実行しています。

まとめ

今回は、業務効率化の一環として、JSONからExcelへの変換スクリプトを作成しました。
単純な変換作業であっても、プログラミングによって自動化することで、大量のデータを処理できることを実感しました。
また、プログラムを組むことで作業時間を削減することだけでなく、ヒューマンエラーの防止にも繋がると感じました。今回の経験を活かし、今後も業務効率に繋がるツールを開発していきたいです。
最後まで読んでいただきありがとうございました!

参考文献

https://atmarkit.itmedia.co.jp/ait/articles/2202/08/news031.html
https://pydocument.hatenablog.com/entry/2023/03/26/142658
https://pydocument.hatenablog.com/entry/2023/03/26/135013
https://tech-blog.rakus.co.jp/entry/20210729/openpyxl

ヘッドウォータース

Discussion