もうすぐ年賀状の季節です(2021年09月執筆)。企業ではだいたい12月頭くらいから、年賀状作成の作業に入るのではないでしょうか。多くの企業では外部のサービスを使ったり、年賀状作成ソフトウェアを使ったりしていますが、今年はDocurainを使って年賀状作成に挑戦してみるのはいかがでしょうか。
今回はハガキ向けに作成できる特殊なテンプレートをベースに、年賀状作成に挑戦してみます。
データ作成について
年賀状を作るにあたって、多くの企業では送付先の住所や宛名を表計算ソフトウェア(Excelなど)で管理しているかと思います。今回は次のような項目で準備したと想定します。
項目 | 内容 |
---|---|
zipcode | 郵便番号。7桁の数字 |
address1 | 住所1。都道府県 + 市区 |
address2 | 住所2。番地まで |
address3 | 住所3。ビルなど |
company | 会社名 + 部署名 |
name | 宛先のお名前 |
この項目に沿って、データを作成していきます。この内容を address.csv
として、保存します。なお、この画像に記載されている住所、会社名、名前はすべてダミーデータで生成したものです。
自社情報について
自社情報はJSONで記述します。 entity.json
というファイル名で、次のような内容になります。
{ "company": "会社名", "name": "名前", "zipcode": "郵便番号(7桁の数字)", "address": "住所" }
テンプレートについて
今回はハガキにぴったり印刷できる、特殊なテンプレートを使っています。 (このような用途にご興味があるDocurainユーザの方はご連絡ください)
このテンプレートでは、各列、行の幅が1mmになるように設計されており、位置合わせが容易になっています。
そして、こちらのテンプレートに合わせて、各項目を埋めていきます。年賀状なので、基本的に各項目は縦書きに設定しています。
配置について
年賀状では送付先の郵便番号、住所、宛名に加えて、自社の郵便番号、住所、宛名の位置が重要になります。今回は既存の年賀状の寸法に合わせて、次のように設計しています。
項目 | 開始位置(左上の位置) | 幅 | 高さ |
---|---|---|---|
郵便番号 | 上12mm 左45mm | 48mm | 9mm |
住所1 | 上23mm 左85mm | 8mm | 100mm |
住所2 | 上23mm 左77mm | 8mm | 100mm |
住所3 | 上23mm 左69mm | 8mm | 100mm |
会社名 | 上23mm 左55mm | 10mm | 100mm |
担当者名 | 上23mm 左45mm | 10mm | 100mm |
自社情報の配置は次の通りです。
項目 | 開始位置(左上の位置) | 幅 | 高さ |
---|---|---|---|
住所1 | 上67mm 左18mm | 10mm | 55mm |
会社名 | 上67mm 左13mm | 5mm | 55mm |
担当者名 | 上67mm 左8mm | 5mm | 55mm |
郵便番号 | 上123mm 左6mm | 29mm | 7mm |
各項目は必要に応じて均等割り付け(郵便番号)や下配置(名前)としています。郵便番号を各桁ごとに分けて設計することできますが、1mm以下での調整が必要になるので、今回は均等割り付けとしています。
そして同じ大きさのページを1つ作成し、ハガキの文面として作成します。今回はEB0182022寅ベーシック年賀状・018 | 年賀状2022(令和4年・寅年・とら) 素材 | 年賀状・無料ダウンロード | 年賀状ならブラザーの画像を使わせてもらいました。
テンプレートの繰り返し処理
ハガキは奇数ページが宛名面、偶数ページが文面という形になります。そこで、奇数ページがはじまる行の上の行、A列に次のように記述します。
A |
---|
#set($e=$ROOT) |
#foreach ($c in $e.clients) |
このように書くことで $!{e.company}
とすれば自社の会社名が取得できたり、 $!{c.address1}
とすれば送付先の住所1が取得できます(下記データ構造について、も参照してください)。また、偶数ページの最終行の下、A列には次のように記述します。
A |
---|
#end |
これは上記の #foreach
に対応する記述になります。このように書くことで、送付先ごとに宛名面および文面が生成されます。
テンプレートでの文字出力
テンプレートでは $!{〜}
のように記述しています。!を入れることで、もし変換するキーワードがなかったとしても、$!{〜}
のようなプログラマブルな文字列が消える仕組みです。
様を付ける
送付先の名前には「様」を末尾に付けています。これは $!{c.name} 様
のようにセルに記述するだけで対応できます。
データ構造について
今回は送付先の住所が複数存在します。そして、送付元(自社情報)が1つという形です。そこで、次のようなJSONを作成して、DocurainのAPIに送信します。
{ // 自社情報 "company": "会社名", "name": "名前", "zipcode": "郵便番号", "address": "住所", "clients": [ // 送付先情報(配列) { "company": "会社名", "name": "名前", "zipcode": "郵便番号", "address1": "住所1", "address2": "住所2", "address3": "住所3", }, { "company": "会社名", "name": "名前", "zipcode": "郵便番号", "address1": "住所1", "address2": "住所2", "address3": "住所3", }, // 繰り返し ] }
プログラミングコードについて
今回はRubyを使ってAPIを呼び出します。
利用するライブラリのインストール
HTTP用のライブラリを含め、次のライブラリを使っています。
- faraday
- faraday_middleware
- ruby-filemagic
適当なディレクトリでGemfileを作成します。
$ bundle init Writing new Gemfile to /path/to/dir/Gemfile
このファイルを編集します。今回は次のように変更しています。
# frozen_string_literal: true source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } # gem "rails" gem "faraday" gem "faraday_middleware" gem "ruby-filemagic"
そしてライブラリをインストールします。
$ bundle install
スクリプトの作成
適当なファイル(今回はupload.rbとしています)を作成し、ライブラリを読み込みます。CSV、JSONを扱うライブラリもインストールします。
require 'faraday' require 'faraday_middleware' require 'ruby-filemagic' require 'json' require 'csv'
DocurainのAPIを実行する処理
まず、Docurainの実行部分を作成します。ここからは api_call 関数の内容です。
# 帳票レンダリング(インスタント)APIコール def api_call # この中に書きます end
まず必要な変数を準備します。
token = 'YOUR_API_TOKEN' # Docurain API トークン out_type = 'pdf' # 出力形式 template_path = './template.xlsx' # テンプレートファイルパス entity_json = JSON.parse(open('./entity.json').read) # テンプレート置き換え文字列のJSON path = "/api/instant/#{out_type}" # APIのパス
住所を記述した address.csv を読み込みます。
# 住所用のCSVを読み込む body = File.open('./address.csv').read csv = CSV.new(body, headers: true, header_converters: :symbol, force_quotes: true)
Excel内にて縦書きを行う際の注意点と解決策して、以下が挙げられます。
-
(ハイフン)が縦にならない
-
を|
に変換します- 数字は均等割り付けしても広がらない
数字の間に(半角スペース)を入れます
この2つの処理を住所、郵便番号に対して行います。ちょっと冗長的なので、関数にまとめても良いでしょう。今回はわかりやすさのために、そのまま記述しています。
rows = csv.to_a.map do |row| # 郵便番号(数字7桁)を分解して、間にスペースを挿入 row[:zipcode] = row[:zipcode].split(//).join(' ') # 住所に含まれる - を | に変換 row[:address1] = row[:address1].gsub(/-/, '|') row[:address2] = row[:address2].to_s.gsub(/-/, '|') row[:address3] = row[:address3].to_s.gsub(/-/, '|') row.to_hash end # 郵便番号(数字7桁)を分解して、間にスペースを挿入 entity_json['zipcode'] = entity_json['zipcode'].split(//).join(' ') # 住所に含まれる - を | に変換 entity_json['address'] = entity_json['address'].gsub(/-/, '|') # JSONの clients の中に送付先顧客情報を追加 entity_json['clients'] = rows
次にテンプレートファイルのコンテンツタイプを取得します。
# テンプレートファイルのContent-Typeを取得 template_content_type = FileMagic.new(FileMagic::MAGIC_MIME).file(template_path, true)
これらの情報を使ってリクエストボディを作ります。
# リクエストボディの作成 params = { template: Faraday::FilePart.new(template_path, template_content_type), entity: Faraday::ParamPart.new(entity_json, 'application/json') }
後はFaraday(HTTPクライアント)を使って、APIを実行します。
# APIを実行する conn = Faraday.new(:url => 'https://api.docurain.jp') do |builder| builder.request :multipart builder.adapter :net_http end # 認証ヘッダーの設定 conn.headers['Authorization'] = "token #{token}" # 実行結果(レスポンス)を返す conn.post(path, params)
これでAPI呼び出し処理の完成です。関数全体の内容は次のようになります。
require 'faraday' require 'faraday_middleware' require 'ruby-filemagic' require 'csv' require 'json' # 帳票レンダリング(インスタント)APIコール def api_call token = 'YOUR_API_TOKEN' # Docurain API トークン out_type = 'pdf' # 出力形式 template_path = './template.xlsx' # テンプレートファイルパス entity_json = JSON.parse(open('./entity.json').read) # テンプレート置き換え文字列のJSON path = "/api/instant/#{out_type}" # APIのパス # 住所用のCSVを読み込む body = File.open('./address.csv').read csv = CSV.new(body, headers: true, header_converters: :symbol, force_quotes: true) rows = csv.to_a.map do |row| # 郵便番号(数字7桁)を分解して、間にスペースを挿入 row[:zipcode] = row[:zipcode].split(//).join(' ') # 住所に含まれる - を | に変換 row[:address1] = row[:address1].gsub(/-/, '|') row[:address2] = row[:address2].to_s.gsub(/-/, '|') row[:address3] = row[:address3].to_s.gsub(/-/, '|') row.to_hash end # 郵便番号(数字7桁)を分解して、間にスペースを挿入 entity_json['zipcode'] = entity_json['zipcode'].split(//).join(' ') # 住所に含まれる - を | に変換 entity_json['address'] = entity_json['address'].gsub(/-/, '|') # JSONの clients の中に送付先顧客情報を追加 entity_json['clients'] = rows # テンプレートファイルのContent-Typeを取得 template_content_type = FileMagic.new(FileMagic::MAGIC_MIME).file(template_path, true) # リクエストボディの作成 params = { template: Faraday::FilePart.new(template_path, template_content_type), entity: Faraday::ParamPart.new(entity_json, 'application/json') } # APIを実行する conn = Faraday.new(:url => 'https://api.docurain.jp') do |builder| builder.request :multipart builder.adapter :net_http end # 認証ヘッダーの設定 conn.headers['Authorization'] = "token #{token}" # 実行結果(レスポンス)を返す conn.post(path, params) end
レスポンスを判定する
次にレスポンスの内容を判定して、レポートをファイル出力します。ここからは res_handle 関数の内容です。
# レスポンスハンドリング(適宜必要なハンドリングを行ってください) def res_handle(res) # この中に書きます end
まずHTTPステータスが200(正常終了)以外の場合はエラーメッセージを出して終了します。
if res.status != 200 # エラー判定 puts res.body # エラーメッセージを返して終了 return end
次にレスポンスのContent-Typeから、出力するファイルの拡張子を指定します。
# 正常時、カレントディレクトリにファイル保存 # content-typeから拡張子に変換 extensions = { 'application/pdf' => 'pdf', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx', 'application/vnd.ms-excel' => 'xls', 'image/svg+xml' => 'svg', 'image/png' => 'png', 'image/jpeg' => 'jpg', 'image/gif' => 'gif', } content_type = res.headers['content-type'] ext = extensions[content_type]
後はファイル名(今回は test に固定)を決めて、ファイル書き出しします。
# ファイル名を決めて書き出し file_name = "test.#{ext}" filePath = "#{Dir.pwd}/#{file_name}"; File.binwrite(filePath, res.body) # メッセージを出力 puts "saved : #{filePath}"
この関数の全体像は次のようになります。
# レスポンスハンドリング(適宜必要なハンドリングを行ってください) def res_handle(res) if res.status != 200 # エラー判定 puts res.body # エラーメッセージを返して終了 return end # 正常時、カレントディレクトリにファイル保存 # content-typeから拡張子に変換 extensions = { 'application/pdf' => 'pdf', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx', 'application/vnd.ms-excel' => 'xls', 'image/svg+xml' => 'svg', 'image/png' => 'png', 'image/jpeg' => 'jpg', 'image/gif' => 'gif', } content_type = res.headers['content-type'] ext = extensions[content_type] # ファイル名を決めて書き出し file_name = "test.#{ext}" filePath = "#{Dir.pwd}/#{file_name}"; File.binwrite(filePath, res.body) # メッセージを出力 puts "saved : #{filePath}" end
実行する
ではこの2つの関数をつないで実行します。
res = api_call # APIコール res_handle(res) # レスポンスハンドリング
実行すると、次のように結果が出力されます。
$ ruby upload.rb saved : /path/to/test.pdf
できあがったPDFの内容です。奇数ページが宛名、偶数ページが文面になります。
印刷する
後は両面印刷対応のプリンターや複合機で印刷します。まだ年賀状が販売される時期ではないので、Word 2019 for Mac:はがきの宛名印刷テンプレートを作成するにはの年賀状テンプレートを利用して、年賀状風に印刷してみました。
宛名側です。
文面側です。
まとめ
Docurainを使うことで、年賀状のような印刷物もExcelでデザインして作成できます。特殊なテンプレートが必要にはなりますが、1mm単位での正確な配置も指定できます。往復ハガキのような特殊な形式でも利用できます。
DocurainはWeb APIを介して利用するので、対象の宛先があっても素早く作成して、印刷が可能です。ぜひご利用ください!