はじめに
業務でラベルシール用宛名ラベルの作成にラベル屋さんというソフトを利用しています。しかし公式サイトの使い方を見る限り、連名の有り無しなどの条件分岐に対応したラベル作りに対応できなさそうです。そこでLaTeXのtikzとtcolorbox, datatool, intcalcパッケージなどを利用して宛名ラベルの差し込み印刷に挑戦してみました。
TeXエンジンは、フォントの変更がしやすいという噂のLuaTeX-jaを利用することにしました。
datatoolはデータセットからdata plotや表作成などが行えるLaTeXパッケージです。日本語では
で使い方を見ることができます。csvなどの外部データを利用することもできて、今回は作成したcsvファイルを読み込み、定型フォーマットに文字列を流し込むのに利用しました。
準備
まずは宛名ラベルの差し込み印刷に利用するcsvファイルを用意します。今回は
を利用して、次の画像ようなcsvファイル(personal_information.csv)を作成しました。
csvファイルのヘッダ部分は取り除いています。ヘッダ部分がある場合もdatatoolの記述を変えれば利用できるようです。各列の意味は次の通りです。括弧内はdatatoolで扱う際のkeyを表しています。
- 名前(Name)
- 郵便番号(PostalCode)
- 住所1(Address)
- 住所2(address)
- ご家族様表記の有無(ToFamily)
- 連名1(Family)
- 連名2(family)
出力結果
上のcsvファイルを元に作成した宛名ラベルのpdfファイルの画像を載せておきます。あくまでも画像の住所・氏名はダミーで実在しません。
1枚目の画像は印刷後に余ったラベルシールの再利用を想定して、ラベル開始位置を指定できるようにし、開始位置をずらしたものです。画像では4番目のラベル位置から宛名を配置しています。その他に連名を入れたいもの、ご家族様表記を入れたいものなどを判別してラベルが作成されるようにしています。画像では枠があるように見えますが、印刷には出てきません。
コードの紹介
上記画像の宛名ラベルを作成するためのLaTeXファイルの内容を紹介します。
ここではラベルを印刷するシールは
A-Oneの75312番を想定しています。シート1枚に対して12面のラベルがあり、その寸法に合わせてnewlengthを定義しています。タイプセットは2回必要です。
\documentclass[lualatex,a4paper,ja=standard]{bxjsbook}
\usepackage[haranoaji]{luatexja-preset}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{etoolbox}
\usepackage[math=pgfmath,utf8=true]{datatool}
\usepackage[utf8]{inputenc}
\usepackage{intcalc}
\usepackage{xparse}
\usepackage{tikz}
\usetikzlibrary{calc,math}
\usepackage{tcolorbox}
\newlength{\myleftmargin}
\newlength{\myrightmargin}
\newlength{\mytopmargin}
\newlength{\mylabelwidth}
\newlength{\mylabelheight}
\newlength{\mymidspace}
\setlength{\myleftmargin}{19.3mm}
\setlength{\myrightmargin}{19.3mm}
\setlength{\mytopmargin}{21.5mm}
\setlength{\mylabelwidth}{83.8mm}
\setlength{\mylabelheight}{42.3mm}
\setlength{\mymidspace}{3.8mm}
\pagestyle{empty}
\tikzset{every picture/.style={
remember picture, overlay,
execute at begin picture=
{
\coordinate (P) at (current page.north west);
\tikzmath{
int \i,\j;
coordinate \p;
\p0 = (P)+(\myleftmargin, -\mytopmargin);
\p1 = (\p0)+(\mylabelwidth + \mymidspace, 0);
for \i in {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}{
\j =\i+2;
\p\j = (\p\i) + (0, -\mylabelheight);
};
}}}
}
\newtcolorbox[blend into=tables]{addresslabel}{
colback=white,
width =\mylabelwidth,
height=\mylabelheight,
lower separated=false,
middle = 0pt,
space to lower,
boxrule=0mm,
valign lower=center,
valign upper=top,
halign lower=center,
halign upper=flush left,
fontlower=\sffamily\bfseries,
}
\NewDocumentCommand\AddressLabel{m m m m m m o o}{
\begin{tikzpicture}[every picture]
\node[inner sep=0pt,anchor=north west] at (\p{#1}){
\begin{addresslabel}
\fontsize{10pt}{12pt}\selectfont
〒{#4}
\par
\hspace{1\zw}{#5}
\par
\hspace{1\zw}{#6}
\tcblower
\fontsize{15pt}{1.58\zh}\selectfont
\begin{tabular}{r}
{#3}~様
\IfNoValueTF{#7}{}{\\ {#7}~様}
\IfNoValueTF{#8}{}{\\ {#8}~様}
\ifnumequal{#2}{1}{\\ {ご家族}~様}{}
\end{tabular}
\end{addresslabel}
};
\end{tikzpicture}
}
\newcounter{posnum}
\newcounter{initposnum}
\newcounter{linenum}
\setcounter{initposnum}{3}
\begin{document}
\DTLloaddb[noheader,keys={Name,PostalCode,Address,address,ToFamily,Family,family}]{data}{personal_information.csv}
\begin{DTLenvforeach}{data}{\Name=Name, \PostalCode=PostalCode, \Address=Address, \address=address, \ToFamily=ToFamily, \Family=Family, \family=family}
\setcounter{linenum}{\intcalcAdd{\DTLcurrentindex}{\theinitposnum -1}}
\setcounter{posnum}{\intcalcMod{\thelinenum}{12}}
\ifnum\thelinenum>11\ifnum\theposnum = 0 \newpage\fi\fi
\DTLifstringeq{\Family}{}{
\AddressLabel{\theposnum}{\ToFamily}{\Name}{\PostalCode}{\Address}{\address}
}{
\DTLifstringeq{\family}{}{
\AddressLabel{\theposnum}{\ToFamily}{\Name}{\PostalCode}{\Address}{\address}[\Family]
}{
\AddressLabel{\theposnum}{\ToFamily}{\Name}{\PostalCode}{\Address}{\address}[\Family][\family]
}}
\end{DTLenvforeach}
\end{document}
ループ処理があるため実行速度は遅めです。tcolorboxの設定でcolframe=whiteとすれば、上の画像にあったboxの枠も消えます。
intcalcパッケージは、剰余計算で利用しています.\intcalcAdd, \intcalcModはこのパッケージで定義されています。
xparseパッケージとtcolorboxパッケージを利用してAddressLabelというコマンドを作りそれをdatatoolパッケージで定義されるDTLenvforeach環境内でループ処理させています。最初は、AddressLabelコマンドのオプションの引数のところを必須引数にして、引数が空文字であれば空文字を入れるようにetoolboxのifstremptyコマンドで記述しようとしたのですが、Familyやfamilyキーが空文字でもDTLenvforeach環境内での\Familyなどのコマンドは空文字と判断されなかったため、これらをオプション引数にして条件分岐で対応しました。トークンの展開順序などが関係しているのでしょうか。
最後に
今回作成したラベルはシンプルなものですが、tikzを使って色々装飾できそうです。
しかし作ってはみたものの、事務の方にLaTeXを使わせるわけにもいかないので実際には使わないかな。