【コピペOK】PythonでExcel転記を自動化する方法|シート間・ファイル間・条件付きの3パターン

毎月末に同じ作業をしていませんか。

各部署から届く勤怠シートを開いて、集計ファイルに1行ずつ貼り付けていく。日報ファイルを10個開いて、月次まとめシートにコピペしていく。在庫台帳の更新データを本社ファイルに手動で転記していく……。

私が製造業の管理部門にいたころ、月末の2〜3時間はこういう転記作業に消えていました。ヒューマンエラーで合計が合わなくなって、1時間かけてどこを間違えたか探した経験も正直3回以上あります。

「Pythonで自動化できるらしい」という話を聞いて、いくつかの記事のコードを試してみたことがあるのですが、動かせないまま諦めた…という経験がある方もいるのではないでしょうか。エラーが出たときの対処が書かれていなかったり、自分のExcelのシート名と合わなかったりして、結局どうしていいかわからなくなるんですよね。

この記事では、転記の状況別に3つのパターンを用意しました。シート間・ファイル間・条件付きの3パターンで、それぞれのコードの「どこを変えればいいか」をセットで説明します。

読み終えたら、今日コードを動かせる状態になります。

この記事を読むとできること
– 同じファイル内のシート間でデータを転記する
– フォルダ内の複数Excelファイルを1ファイルに統合する
– 条件付き転記(「未処理」の行だけ別シートへ移す、など)
– 実務でよく出るエラー3パターンの対処法を知る

Python環境がまだない方へ
まず「総務担当者がPythonを始める方法」で環境を整えてから戻ってきてください。この記事はPythonが動く状態を前提にしています。


まず知っておく:openpyxlとpandas、どちらを使うか

PythonでExcelを操作できるライブラリはいくつかありますが、転記に限れば実質2択です。どちらを使うか迷ったまま進むと後で詰まるので、先に決めておきます。

転記件数が少ない・書式を維持したいなら → openpyxl

  • セルの色・フォント・罫線をそのまま保持できる
  • 少量〜中量のデータ(数百〜数千行)なら処理速度も十分
  • コードが直感的でカスタマイズしやすい

この記事では基本的にopenpyxlを使います。

大量データや集計も必要なら → pandas

  • 数万行でも高速に処理できる
  • ただし書式は保持されない(値だけ転記される)
  • 「転記したうえで集計も行いたい」場合に強い

転記後に集計処理まで自動化したい場合は、pandasを使った実装を「製造日報をPythonで自動集計する方法」で解説しています。

まずopenpyxlのインストールを確認してください。

pip install openpyxl

一度だけ実行すればOKです。すでにインストール済みの場合は何も変わらないので、念のため実行しておくとよいです。


VBAで転記を自動化したい方(Python不要で済ませたい方)はこちら:【コピペOK】Excel自動化7選|総務・生産管理歴10年が実際に使っているVBA・関数まとめ


【パターン1】同じファイル内のシート間転記

こんな場面で使います

  • 「4月_部署A」シートのデータを「集計」シートに追記していく
  • 日別シートから月次まとめシートへデータを集約する
  • 申請シートから「処理済み」シートへ特定の行を移す

ファイルは1つで、シートだけが違う場合がこれです。

コードの基本形

import openpyxl

# ファイルとシートを指定
wb = openpyxl.load_workbook('kintai.xlsx')
ws_src = wb['4月_部署A']   # コピー元のシート名
ws_dst = wb['集計']         # コピー先のシート名

# 2行目以降(ヘッダー行を除く)を転記
for row in ws_src.iter_rows(min_row=2, values_only=True):
    if any(cell is not None for cell in row):  # 空行はスキップ
        ws_dst.append(row)

wb.save('kintai.xlsx')
print('転記完了')

どこを変えればいいか

シート名を変える
wb['4月_部署A']'4月_部署A' を自分のシート名に変えます。シート名はExcelの下部タブに表示されている文字列と一字一句同じにする必要があります。半角スペース1つの違いでもエラーになります。

ヘッダー行数を変える
min_row=2 は「2行目からデータが始まる(1行目はヘッダー)」という意味です。ヘッダーが2行ある場合は min_row=3 にしてください。

特定の列だけ転記したい場合

全列でなく、A列・C列・E列だけ転記したい場合はこうなります。

for row in ws_src.iter_rows(min_row=2, values_only=True):
    # 列番号はゼロ始まり(A=0, B=1, C=2, D=3, E=4)
    selected = (row[0], row[2], row[4])
    ws_dst.append(selected)

【パターン2】別ファイルへの転記(複数ファイル→1ファイル統合)

こんな場面で使います

  • 各部署が提出した月報Excelをフォルダに集めて、1つの集計ファイルに統合する
  • 倉庫ごとの在庫ファイルを本社の集約ファイルにまとめる
  • 取引先ごとに届く発注書を一覧シートに集約する

この作業を手動でやっていると、1ファイルのコピペミスが混入するだけで全体の合計が狂います。ファイルが10個あれば10回ミスの機会があるわけで、「合計が合わない…どこが違うんだ」というデバッグに時間を使った経験がある方も多いのではないでしょうか。

コードの基本形

import openpyxl
from pathlib import Path

# 統合先ファイルを開く
output_wb = openpyxl.load_workbook('月次集計.xlsx')
output_ws = output_wb['まとめ']

# 「各部署」フォルダ内の全Excelファイルを順番に処理
folder = Path('各部署')
for file in folder.glob('*.xlsx'):
    wb = openpyxl.load_workbook(file)
    ws = wb.active  # そのファイルの最初のシートを対象にする

    for row in ws.iter_rows(min_row=2, values_only=True):
        if any(cell is not None for cell in row):
            output_ws.append(row)

output_wb.save('月次集計.xlsx')
print('統合完了')

フォルダ構成のポイント

このコードを動かすには、以下のように配置するのが一番シンプルです。

作業フォルダ/
├── 統合スクリプト.py    ← Pythonファイル
├── 月次集計.xlsx         ← 統合先ファイル(あらかじめ「まとめ」シートを作っておく)
└── 各部署/
    ├── 営業部_4月.xlsx
    ├── 総務部_4月.xlsx
    └── 製造部_4月.xlsx

前提は「各ファイルの1行目がヘッダー、2行目以降がデータ」です。ファイルによってヘッダー行数が違う場合は、先に手動で揃えておくのが現実的です。

どこを変えればいいか

  • '月次集計.xlsx' → 統合先ファイル名
  • 'まとめ' → 統合先のシート名
  • '各部署' → 集めたファイルが入っているフォルダ名
  • min_row=2 → データ開始行

集計まで自動化したい場合:製造日報をPythonで自動集計する方法【コピペOK】


【パターン3】条件付き転記(特定の行だけ転記する)

こんな場面で使います

  • 発注管理シートで「未処理」フラグの行だけを別シートに抜き出す
  • 在庫台帳で在庫数が一定以下の商品を発注候補リストに転記する
  • 勤怠データで残業時間が45時間を超えた社員だけを抽出する

手作業でフィルタしてコピペするのが定番ですが、毎月やる処理なら確実に自動化できます。

コードの基本形(「未処理」の行だけ転記)

import openpyxl

wb = openpyxl.load_workbook('発注管理.xlsx')
ws_src = wb['全件一覧']
ws_dst = wb['未処理分']

count = 0
for row in ws_src.iter_rows(min_row=2, values_only=True):
    if row[3] == '未処理':  # D列(インデックス3)の値で判定
        ws_dst.append(row)
        count += 1

wb.save('発注管理.xlsx')
print(f'転記件数:{count}件')

条件の書き方を変えるだけで応用できます

row[3] == '未処理' の部分を変えるだけで、ほとんどの条件に対応できます。

やりたいこと コードの書き方
「完了」以外の行を転記 row[3] != '完了'
数値が100以上の行を転記 row[3] is not None and row[3] >= 100
特定の文字列が含まれる行 row[3] is not None and '要確認' in str(row[3])
B列とD列の両方で判定 row[1] == '製造部' and row[3] == '未処理'

列番号はA=0から始まります(B=1, C=2, D=3, E=4…)。自分の管理表の列位置を確認してから変えてください。

在庫管理の発注アラートまで自動化したい場合:在庫管理をPythonで自動化する方法【コピペOK】


よくあるエラーと対処法

コードを動かすと必ず1度はエラーが出ます。対処法を知らないまま止まると諦めやすいので、よくある3パターンを書いておきます。

PermissionError:Excelを開いたまま実行した

PermissionError: [Errno 13] Permission denied: 'kintai.xlsx'

原因: Excelファイルを開いたままPythonを実行しようとしている

対処: Excelを閉じてから実行するだけです。これだけで解決します。スクリプトを実行する前にExcelを閉じる習慣をつけるのが一番シンプルな解決策です。

処理が終わったら自動で再度開くようにしたい場合は、冒頭に import os を追加したうえで、末尾に os.startfile('kintai.xlsx') を追加できます。

KeyError:シート名が見つからない

KeyError: 'Worksheet 集計 does not exist.'

原因: wb['集計'] と書いたシート名が、実際のシート名と一致していない

対処: まずこのコードでシート名の一覧を表示してみてください。

import openpyxl
wb = openpyxl.load_workbook('kintai.xlsx')
print(wb.sheetnames)

「[‘集計 ‘, ‘4月_部署A’]」のように表示されたとき、「集計」の後ろにスペースが入っていることに気づけます。表示されたシート名をそのままコピーしてコードに貼り付けると確実です。

AttributeError:セルの値がNoneのとき

AttributeError: 'NoneType' object has no attribute 'strip'

原因: 空白セル(値が入っていないセル)をそのまま処理しようとしている

対処: Noneのチェックを入れてから処理する。

value = row[2]  # C列の値を取り出す
if value is not None:
    # 値がある場合だけ処理を続ける
    print(value.strip())

この記事で紹介した各パターンのコードには、最初から if any(cell is not None for cell in row): というNoneチェックが入っているので、基本的にはそのまま使えます。条件付き転記(パターン3)で数値比較をする場合は、row[3] is not None and row[3] >= 100 のように None チェックを条件の前に付けてください。


まとめ:自分の転記業務に合うパターンを選ぶ

3つのパターンをまとめます。

状況 使うパターン
同じファイル内でシートをまたいでデータを移したい パターン1(シート間転記)
複数のExcelファイルを1つに統合したい パターン2(ファイル間統合)
特定の条件に合う行だけ抽出・転記したい パターン3(条件付き転記)

どのパターンでも、カスタマイズするのは基本的に「シート名」と「データが始まる行番号」の2点だけです。そこさえ自分のExcel構造に合わせれば、ほとんどの転記業務に対応できます。

転記作業が1本のスクリプトで動くようになると、月末の2〜3時間が別の仕事に使えるようになります。まずパターン1の10数行から試してみてください。

転記以外のPythonの活用事例は「総務でPythonを使うと何ができるか」にまとめています。


業務別の転記テンプレートをNoteで配布しています

この記事では基本の3パターンを解説しましたが、実務ではもう少し複雑なケースが出てきます。勤怠・日報・在庫・請求書など業務ごとの完成テンプレートと、エラーログを自動記録する実装をNoteにまとめています。