Python エクセルのデータを置換対応表の文字列で一斉書き換えできるツールを作成しました。

汎用Excel置換ツール 使い方ガイド

1. 概要

このツールは、Excelファイル内のデータを、別のExcelファイルに記載された置換表に従って自動で置換するための汎用ツールです。

  • 置換対象ファイル: 置換したいデータを含むExcelファイル(例:商品説明や文章データ)

  • 置換表ファイル: 置換前と置換後の文字列ペアをまとめたExcelファイル

置換表に従って対象ファイルのデータが置換され、更新後のデータと置換表の使用状況がそれぞれ保存されます。


2. ファイル準備

2-1. 置換表ファイル(replace_rules.xlsx)

  • ファイル形式: .xlsx または .csv

  • 記載内容:

    • A列:置換前文字列(検索文字列)

    • B列:置換後文字列(置換後の文字列)

  • 2行目以降にデータを記載

  • A列またはB列が空欄の行はスキップされます

2-2. 置換対象ファイル(target_data.xlsx)

  • Excel形式のファイル

  • A列の2行目以降が置換対象データ

  • 出力結果は B列 に置換後データ、C列 に更新フラグが追加されます


3. ツールの実行手順

  1. スクリプトと同じフォルダに対象ファイルと置換表ファイルを配置

  2. スクリプトを実行

     
    python script.py
  3. 実行後に以下のファイルが作成されます:

    • target_data_updated.xlsx → 置換後の対象ファイル

    • replace_rules_usage.xlsx → 置換表の使用状況(何回置換されたか、未使用の文字列はどれか)


4. 出力内容の説明

4-1. 対象ファイル

  • B列: 置換後の文字列

  • C列: 更新フラグ

    • 「更新あり」 → 置換が行われた行

    • 空白 → 置換なし

4-2. 置換表使用状況

  • 各置換前文字列に対して、何回置換が行われたかを記録

  • 使用されなかった文字列は「未使用」と表示


5. 注意点

  • Excelが開かれている場合、スクリプト実行時に独立したExcelプロセスを使用するため、他のExcelファイルには影響しません

  • 置換表の列や行の順序を変更すると正しく読み込めません

  • 空白セルや空白行は無視されます


6. 推奨作業フロー

  1. 置換表を作成

  2. 対象ファイルをコピーしてバックアップ

  3. スクリプト実行

  4. 出力結果を確認し、必要に応じて元データに反映


7. ファイル名例(参考)

役割 ファイル名例
置換表 replace_rules.xlsx
置換対象 target_data.xlsx
置換後出力 target_data_updated.xlsx
使用状況出力 replace_rules_usage.xlsx

 

import os
import win32com.client

# ===== Excel操作用ヘルパー関数 =====
def open_excel_file(file_path):
    """独立したExcelインスタンスでファイルを開く"""
    excel = win32com.client.DispatchEx("Excel.Application")
    excel.DisplayAlerts = False
    excel.Visible = True
    workbook = excel.Workbooks.Open(file_path)
    return excel, workbook

def read_excel_data(sheet, cell_range=None, coord_range=None):
    """Excelシートのセル範囲を2次元リストとして取得"""
    if cell_range:
        data = sheet.Range(cell_range).Value
    elif coord_range:
        sr, sc, er, ec = coord_range
        data = sheet.Range(sheet.Cells(sr, sc), sheet.Cells(er, ec)).Value
    else:
        raise ValueError("cell_range または coord_range を指定してください")
    return [list(row) for row in data] if data else []

def write_excel_data(sheet, data, start_row, start_col):
    """Excelシートに2次元リストを書き込む"""
    if not data:
        return
    rows = len(data)
    cols = len(data[0])
    end_cell = sheet.Cells(start_row + rows - 1, start_col + cols - 1)
    sheet.Range(sheet.Cells(start_row, start_col), end_cell).Value = data

def find_last_row(sheet, column):
    """指定列の最終行を取得"""
    return sheet.Cells(sheet.Rows.Count, column).End(-4162).Row  # xlUp

def release_excel(excel, workbook):
    """Excelインスタンスを終了"""
    if workbook:
        workbook.Close(SaveChanges=False)
        del workbook
    if excel:
        excel.Quit()
        del excel


# ===== 汎用置換処理 =====
def replace_excel_data(mapping_file_path, target_file_path):
    """
    Excelのデータを置換表に従って書き換える汎用ツール
    :param mapping_file_path: 置換表ファイルのパス(A列:検索文字列、B列:置換文字列)
    :param target_file_path: 置換対象ファイルのパス(A列2行目以降のデータが対象)
    """
    # --- 1. 置換表を読み込み ---
    excel_map, wb_map = open_excel_file(mapping_file_path)
    sheet_map = wb_map.Sheets(1)
    last_row_map = find_last_row(sheet_map, 1)
    mapping_pairs = read_excel_data(sheet_map, coord_range=(2, 1, last_row_map, 2))

    replace_dict = {str(a).strip(): str(b).strip() for a, b in mapping_pairs if a and b}
    print(f"置換ペア数: {len(replace_dict)}")

    replace_usage = {key: 0 for key in replace_dict.keys()}

    # --- 2. 置換対象ファイルを開く ---
    excel_target, wb_target = open_excel_file(target_file_path)
    sheet_target = wb_target.Sheets(1)
    last_row_target = find_last_row(sheet_target, 1)

    data_target = read_excel_data(sheet_target, coord_range=(2, 1, last_row_target, 1))
    updated_data = []
    update_flags = []

    # --- 3. 置換処理 ---
    for row in data_target:
        original_text = str(row[0]) if row[0] is not None else ""
        updated_text = original_text
        updated_flag = False

        for old, new in replace_dict.items():
            if old in updated_text:
                updated_text = updated_text.replace(old, new)
                replace_usage[old] += 1
                updated_flag = True

        updated_data.append([updated_text])
        update_flags.append(["更新あり" if updated_flag else ""])

    # --- 4. 結果を書き込み ---
    # B列:更新後データ、C列:更新フラグ
    write_excel_data(sheet_target, updated_data, start_row=2, start_col=2)
    write_excel_data(sheet_target, update_flags, start_row=2, start_col=3)

    # --- 5. 置換表に使用状況を追記 ---
    usage_results = [[f"{replace_usage[k]} 回" if replace_usage[k] > 0 else "未使用"] for k in replace_dict]
    sheet_map.Cells(1, 3).Value = "使用状況"
    write_excel_data(sheet_map, usage_results, start_row=2, start_col=3)

    # --- 6. 保存 ---
    output_target = os.path.splitext(target_file_path)[0] + "_updated.xlsx"
    wb_target.SaveAs(output_target)
    wb_map.SaveAs(os.path.splitext(mapping_file_path)[0] + "_usage.xlsx")
    print(f"対象ファイルを保存: {output_target}")
    print(f"置換表の使用状況を保存: {os.path.splitext(mapping_file_path)[0] + '_usage.xlsx'}")

    # --- 7. クリーンアップ ---
    release_excel(excel_map, wb_map)
    release_excel(excel_target, wb_target)
    print("処理完了")


if __name__ == "__main__":
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))
    replace_excel_data(
        os.path.join(BASE_DIR, "replace_rules.xlsx"),
        os.path.join(BASE_DIR, "target_data.xlsx")
    )