作業ログを月次集計表とグラフにまとめる
CSV 内の日付と作業時間を検証し、月ごとの記録件数と合計時間を CSV と棒グラフとして保存します。
4列すべての値が完全一致する行を見つけ、元の行番号とともに新しい Excel ファイルへまとめます。最初に出現した行も含め、重複グループごとに確認します。
この翻訳はAIで作成しました。コード、単位、数値は原文と併せて確認してください。各言語のネイティブ話者による校閲は、まだ完了していません。 English
対象読者Excel データを結合した後に重複入力を確認する事務担当者
この例では、order_id, customer, item, quantity の4つの値がすべて一致した場合にのみ重複とみなします。注文番号だけが一致していても重複にはなりません。文字列内の空白や大文字・小文字は自動変更しません。
何かを削除する前に、最初に出現した行も含め、内容が一致するすべての行を Duplicates シートに集めます。1回しか出現しない行は Unique シートに入れるため、入力された8行すべてを漏れなく確認できます。
orders.xlsx のシート名は Orders でなければならず、1行目には以下の列名が同じ順序で入っている必要があります。列を追加した場合もヘッダーエラーになります。実務ファイルをすぐに使うのではなく、まず必要な4列だけをコピーして練習用ファイルを作成してください。
| 列 | 用途 | 例 |
|---|---|---|
| order_id | 文字列としての注文番号 | O-1001 |
| customer | 文字列としての顧客名 | Alpha |
| item | 文字列としての品目 | Sensor |
| quantity | 正の整数としての数量 | 2 |
完全に空の行はスキップされます。一部の値だけが欠けている場合や、行に数式が含まれている場合はスクリプトが停止します。注文番号、顧客名、品目は空でない文字列でなければなりません。数値の注文番号は自動変換されないため、入力ファイルでは文字列として用意してください。
python --version
python -m pip install -r requirements.txt
python example.pyインストールにはインターネット接続が必要です。コード内の BASE は、現在のターミナルフォルダではなく example.py を基準に入力・出力パスを設定します。
コードは load_workbook を読み取り専用モードで使って元ファイルを開き、Counter で各行が何回出現するか数えます。enumerate と start=2 を使って元の Excel 行番号を追跡します。結果は新しい Workbook に保存されるため、元ファイルは再保存されません。
"""Find repeated business rows. Keep the source workbook unchanged."""
from collections import Counter
from pathlib import Path
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, PatternFill
BASE = Path(__file__).resolve().parent
HEADERS = ("order_id", "customer", "item", "quantity")
def main():
destination = BASE / "outputs"
if destination.exists():
raise ValueError("outputs already exists; rename it before running again.")
source = load_workbook(BASE / "orders.xlsx", read_only=True, data_only=False)
try:
if "Orders" not in source.sheetnames:
raise ValueError("Orders sheet is missing.")
worksheet = source["Orders"]
rows = list(worksheet.iter_rows(values_only=True))
if not rows or tuple(rows[0]) != HEADERS:
raise ValueError(f"Expected headers: {HEADERS}")
records = []
for row_number, row in enumerate(rows[1:], start=2):
if all(value is None for value in row):
continue
if any(value is None for value in row):
raise ValueError(f"Row {row_number}: missing value.")
if any(isinstance(value, str) and value.startswith("=") for value in row):
raise ValueError(f"Row {row_number}: formulas are not supported.")
if not all(isinstance(value, str) and value.strip() for value in row[:3]):
raise ValueError(f"Row {row_number}: first three fields must be text.")
if type(row[3]) is not int or row[3] <= 0:
raise ValueError(f"Row {row_number}: quantity must be a positive integer.")
records.append((row_number, tuple(row)))
if not records:
raise ValueError("No data rows were found.")
finally:
source.close()
counts = Counter(row for _, row in records)
repeated = [(number, row) for number, row in records if counts[row] > 1]
unique = [(number, row) for number, row in records if counts[row] == 1]
book = Workbook()
book.remove(book.active)
for name, selected in (("Duplicates", repeated), ("Unique", unique)):
sheet = book.create_sheet(name)
sheet.append(("source_row", *HEADERS, "occurrences"))
for number, row in selected:
sheet.append((number, *row, counts[row]))
sheet.freeze_panes = "A2"
sheet.auto_filter.ref = sheet.dimensions
sheet.sheet_view.showGridLines = False
for cell in sheet[1]:
cell.font = Font(name="Arial", bold=True, color="FFFFFF")
cell.fill = PatternFill("solid", fgColor="243B53")
for column, width in zip("ABCDEF", (14, 16, 18, 20, 14, 16)):
sheet.column_dimensions[column].width = width
destination.mkdir(exist_ok=False)
book.save(destination / "duplicate_review.xlsx")
book.close()
groups = sum(count > 1 for count in counts.values())
print(f"Input rows: {len(records)}; duplicate groups: {groups}")
print(f"Duplicate rows: {len(repeated)}; unique rows: {len(unique)}")
print("Created outputs/duplicate_review.xlsx (source unchanged).")
if __name__ == "__main__":
try:
main()
except (OSError, ValueError) as error:
raise SystemExit(f"Stopped: {error}") from error
スクリプトは outputs/duplicate_review.xlsx に Duplicates と Unique の2つのシートを作成します。source_row は元ファイルでの Excel 行番号、occurrences は入力全体で同じ内容が出現した回数です。
| 項目 | 付属データでの結果 |
|---|---|
| 入力データ行 | 8 |
| 重複グループ | 2 |
| Duplicates 行 | 4 (元の行 2, 3, 5, 8) |
| Unique 行 | 4 (元の行 4, 6, 7, 9) |
Duplicates に4行あるからといって、4行削除すべきという意味ではありません。各グループで1行だけ残す場合、余分な入力は2件です。どの行を残すかは、元データを確認してから決めてください。
| メッセージまたは症状 | 確認すること |
|---|---|
| Orders sheet is missing | 元のシート名を Orders に設定します。 |
| Expected headers | 列名、順序、余分な列の有無を確認します。 |
| missing value / formulas are not supported | 報告された元の行を確認し、数式ではなく値を入力します。 |
| quantity must be a positive integer | 1 以上の整数を数量として入力します。 |
| outputs already exists | 以前の結果フォルダの名前を変更して保持します。 |
| ModuleNotFoundError | example.py を実行するのと同じ python を使って requirements.txt のパッケージをインストールします。 |
Windows 11 (10.0.26200), CPython 3.12.14 (64-bit). openpyxl 3.1.5, Matplotlib 3.10.8. 各例で使用するライブラリは requirements.txt に固定されています。
コード、入力データ、実行手順が含まれています。展開して、まずREADME.txtを読んでください。
サンプルZIPをダウンロードサンプルコード、ファイル名、入力キーは原文のままです。翻訳本文のコマンドと確認手順も併せて参照してください。
独自に作成した練習用資料 · 元のファイルを別に保管してから実行してください。
説明と例は独自に作成しました。関連する動作や概念は、以下の公式資料で確認できます。