A5コインチェックリストPDFジェネレーター
使用するタイミング
- ユーザーが印刷可能なコイン収集チェックリストを求めている
- ユーザーがA5、フィロファックス、バインダー、プランナーページをコイン用に言及している
- ユーザーがNumistaエクスポートをシリーズマスターリストとクロスリファレンスしたい
- ユーザーが以前生成したコインチェックリストPDFを修正している
ページ設定
from reportlab.lib.pagesizes import A5
PAGE_W, PAGE_H = A5 # 148mm x 210mm (419.53 x 595.28 pt)
LEFT_M = 18*mm # 広め — フィロファックス6穴パンチを避けるため
RIGHT_M = 6*mm
TOP_M = 9*mm
BOT_M = 8*mm
USABLE_W = PAGE_W - LEFT_M - RIGHT_M # ~124mm
6穴パンチガイド
すべてのページに描画します。フィロファックスA5標準穴位置(上端から):
HOLE_POSITIONS_MM = [19, 51, 70, 140, 159, 191]
for h in HOLE_POSITIONS_MM:
y = PAGE_H - h*mm
c.setStrokeColor(HexColor("#CCCCCC"))
c.setLineWidth(0.25)
c.circle(4.5*mm, y, 2.2*mm, stroke=1, fill=0)
フォント
Carlitoを使用します(Calibriとメトリック互換、SIL Open Font Licenseのもとで無料)。Linuxでは通常以下の場所にあります:
/usr/share/fonts/truetype/crosextra/Carlito-Regular.ttf
/usr/share/fonts/truetype/crosextra/Carlito-Bold.ttf
/usr/share/fonts/truetype/crosextra/Carlito-Italic.ttf
WindowsまたはmacOSでは、Google FontsからCarlitoをダウンロードし、代わりにそれらのファイルを指定します。
3つのバリエーションすべてを登録します。決してHelveticaにフォールバックしないでください。以下のレイアウトはCalibriスタイルのメトリックに合わせて調整されています。
タイポグラフィルール(ハード制約)
| 要素 | フォント | サイズ | 備考 |
|---|---|---|---|
| カバータイトル | Carlito-Bold | 20pt | 黒いバナーに中央揃え |
| カバーサブタイトル | Carlito-Bold | 16pt | タイトルの下 |
| セクションヘッダー | Carlito-Bold | 8.5-9pt | 黒いバーに白文字 |
| カラムヘッダー | Carlito-Bold | 7.5pt | 灰色、区切り線の上 |
| ボディテキスト — 全カラム | Carlito / Carlito-Bold | 11pt | Name、Period、Nowで統一 |
| 収集済み詳細行 | Carlito-Italic | 8.5pt | 灰色、収集行の下 |
| フッター | Carlito | 6pt | ページ番号+チェックリスト名 |
| 額面カラム | Carlito | 9pt | 右揃え、略記(5Y、10Y、1J) |
重要: Name、Period、Nowカラムは同じフォントサイズ(11pt)に保ちます。 サイズが混在すると印刷ページでプロフェッショナルに見えません。
行レイアウト
ROW_H = 16-18 # pt — 行間の余裕
SEC_H = 17 # セクションヘッダーバーの高さ
COL_H = 13 # カラムヘッダーの高さ
COLLECTED_EXTRA = 11 # 収集行の詳細行のための追加の高さ
- 各行の下部に薄い区切り線(0.2pt、#DDDDDD)を描画します
- 行の背景を交互に: 偶数行は#EBEBEBで塗りつぶします
- 収集行: 太字+チェックボックスにチェックマーク
カラム位置(LEFT_Mから)
COL_CK = 0 # チェックボックス
COL_YR = 11 # 年
COL_NM = 36 # コイン名(主要カラム)
# 右側カラム — 期間テキストとの重なりを避けるため右に寄せます
COL_ERA = 84*mm # 時代マーカー(B/P/N)または額面
COL_NOW = 89*mm # 現在の状態 / 補足情報
重要な教訓: 「300 BCE-1279」のような期間/日付文字列は、11ptで約28mmの幅があります。時代マーカーとNOWカラムは84mm以降から開始しなければ重なります。 これは複数回の修正を経て解決しました。
グレースケールデザイン(必須)
グレースケールレーザープリンター向けに設計されています。意味を伝えるために色に依存しないでください。
| 視覚要素 | グレースケールのアプローチ |
|---|---|
| 収集行の強調 | 斜線ハッチング(色塗りではない) |
| セクションヘッダー | 黒いバーに白文字 |
| 交互の行 | #EBEBEBと白 |
| 時代インジケーター | テキスト文字(B/P/N)、色付きドットではない |
| 収集ミントマーク | 太字と通常のウェイト(色ではない) |
| チェックボックス | 線で描かれたチェックマーク、Unicodeではない |
ハッチングの実装:
def hatch(c, x, y, w, h):
c.saveState()
p = c.beginPath(); p.rect(x, y, w, h)
c.clipPath(p, stroke=0)
c.setStrokeColor(HexColor("#CCCCCC"))
c.setLineWidth(0.35)
for i in range(-int(h), int(w+h), 5):
c.line(x+i, y, x+i+h, y+h)
c.restoreState()
チェックマーク(Xではない、Unicodeではない):
c.setStrokeColor(BLK); c.setLineWidth(1.2)
cx = LEFT_M + COL_CK + 1; cy = ty - 1
c.line(cx+2, cy+4, cx+4, cy+1.5)
c.line(cx+4, cy+1.5, cx+8, cy+7.5)
ページフロー(連続)
各セクションに独立したページを与えないでください。 セクションは連続して流れます。小さいセクション(3-5項目)は、前のセクションの末尾と同じページに詰め込む必要があります。
# 孤立を防ぐ: セクションヘッダーにはh + COL_H + 2 + ROW_H + 4が必要
if item_type == 'section_header':
needed = h + COL_H + 2 + ROW_H + 4
if y - needed < BOT_M:
y = new_page(c)
カバーページの構造
- タイトル(20pt)とサブタイトル(16pt)の黒いバナー
- バナーの下のサブタイトライン(12pt、灰色)
- 水平線
- 統計ボックス(#EBEBEB塗り): 「合計: X 所持: Y 不足: Z」(14pt太字)
- カバレッジ率(11pt、灰色)
- コレクター名(14pt太字)+Numistaハンドル(11pt)
- 凡例セクション(該当する場合)
- シリーズ概要と右揃えのカウント
含めないもの
- 個別の白紙メモページ(紙の無駄)
- 色に依存する要素
- Unicodeのチェックマークや特殊文字(フォントのカバレッジ問題)
- どの要素でも7pt未満のフォントサイズ
- ドキュメント内のどこにも1ページ以上の空白
出力
ユーザーが開ける場所にPDFを保存します(claude.aiでは: /mnt/user-data/outputs/ に保存し present_files を呼び出す、Claude Codeでは: 作業フォルダー)。配信前にビジュアルQAのために pdf2image でページをレンダリングします。