Kon's DX Lab - Case Study

Day 42|xlsxwriterで“結合セルの外枠線”を引く地味に難しい話

Published on 2025-05-13

🔬 Case Study Summary
Problem

(ここに課題を記述)

Result

(ここに具体的な成果を記述)


Tech & Process

(ここに採用技術とプロセスを記述) コードを詳しく見る »

こんにちは、こんです🦊
今日は Commercial Invoice 出力機能のブラッシュアップに取り組みました。特に「merged cells に罫線(外枠)だけを引く」という、ごく一見簡単そうに見える課題が、意外と奥深く、そして罠が多かったので、その記録を残します。


🎯 今日のテーマ:テンプレートに忠実なExcel生成

元々作っていた Streamlitアプリでは、納品Excelをアップするだけで次の3つを自動出力できる構成を目指しています:

  • SagawaOms出荷データ(Excel形式)

  • 納品書(PDF形式)

  • Commercial Invoice(Excel形式)

このうち、Commercial Invoiceの出力には、テンプレートを忠実に再現するための細かいExcelレイアウト制御が必要です。


🧪 試行錯誤ポイント:「merged cells に外枠を引く」

試したこと:

  • xlsxwriter の write_blank() + add_format({"top": 1})

  • set_top(), set_left() などの専用メソッドによる個別罫線設定

  • merge_range() の前後タイミングを変える

  • conditional_format() を使って範囲指定でスタイル適用

問題点:

  • merged_range() で結合されたセルの内部(中継セル)にも write_blank() すると、結合が壊れたり罫線が重複して表示されたりする

  • set_top() などでフォーマットを作っても、それを どのセルにいつ書くか で結果が変わる

  • write_blank() では中身が上書きされないと思いきや、結合セルの一部に書くと全体が壊れる


🔧 最小構成で再検証

一旦すべての高度な処理を止め、**「A2セルの上だけに線を引く」**という最小単位でコード検証を実施:

import xlsxwriter

wb = xlsxwriter.Workbook("border_test.xlsx")
ws = wb.add_worksheet()

fmt = wb.add_format()
fmt.set_top(1)  # 上線のみ
ws.write_blank(1, 0, None, fmt)  # A2 = (row=1, col=0)

wb.close()

このコードで期待通りA2セルの上に線が引かれることを確認し、ようやく罫線ロジックの本質的な動作に確信を持てました。


📦 それでも進んだ成果たち

今日はあくまで「罫線」に時間を使ってしまった日ではありますが、それでも以下の前進がありました:

  • Commercial Invoiceテンプレートの構造が整理され、すべての merge_range 指定と row height が明文化

  • draw_outer_border() の構造が単純化され、検証単位ごとのロールバックが可能になった

  • 複数の方法を検証して、xlsxwriter の制約と自由度を把握できた


💡 今日の学び:簡単なことこそ“仕様”を正確に知る

「セルの周りに線を引く」という当たり前のことが、merged cell × Python × 書式という条件になると急に難しくなる。
でも、こうした一見些細な処理こそが、テンプレートの完成度を大きく左右します。


🧭 明日以降の方針

  • draw_outer_border() を使って 結合セルの周囲だけに罫線を引く実装を確定

  • そのうえで、レイアウト全体に均一な品質で罫線を適用

  • 必要に応じて fpdf でPDF版との構造差異を吸収し、出力一貫性の確保


🧠 ハッシュタグ

#100日チャレンジ
#xlsxwriter
#PythonでExcel自動化
#業務改善
#罫線問題
#Streamlit開発記録
#テンプレート忠実再現
#DXの泥臭いところ