最初に
kintoneに限らず業務系のWebサービスでは、帳票印刷が必要になってきます。
(まだまだ紙で印刷したり、メールに添付したり、ダウンロードしたり)
ここでは、kintone の印刷機能について調査と独自実装する場合の方法についての考え方をまとめたいと思います。
主な kintone 帳票印刷ソリューション
(カッコ内は販売会社名)
kintone連携ソリューション公式ページから個人的に使ったり、知っている主な製品をまとめてみました。
(ここでの印刷はPDFで出力することを指しています)
-
プリントクリエイター(トヨクモ)
- コース毎の月額定額のサブスクリプションモデル。専用のサービス上で印刷レイアウトをプレビューで確認しながら作成可能。印刷枚数は無制限。
- 専用サービスにログインして、PDFで作成したテンプレートファイルをアップロード。アップロードしたPDFテンプレート上にkintoneのフィールドをマッピングしていきます。(マウスで矩形を作り、そこにフィールドをマッピングする感じです)
-
RepotoneU PDF(株式会社ソウルウェア)
- PDF印刷専用プラグイン型買い切り制。プラグイン設定画面にて印刷レイアウトを作成。Excel出力版や毎月一定額を支払うサブスクリプションモデルもあります。
- プラグイン画面でPDFで作成したテンプレートファイルをアップロード。アップロードしたPDFテンプレート上にkintoneのフィールドをマッピングしていきます。(マウスで矩形を作り、そこにフィールドをマッピングする感じです)
-
ReportsConnect for kintone(株式会社ケーピーエス)
- 月額定額のサブスクリプション。PCにインストールしたレイアウトツールiReportデザイナーを使ってレイアウトを作成。無料枠有り。
-
gusuku Customine(アールスリーインスティテュート)
- ノーコードでkintoneにJavaScriptのカスタマイズを追加できるサービス。このサービスのできることに「Excel/PDF/CSV」の出力機能があります。Customineでは、Excelでテンプレートを作成し、テンプレートにてkintoneのフィールドコードをマッピングします。そのテンプレートにkintoneのレコードのフィールドの値を流し込むような仕組みです。テンプレートのマッピングはこちらのマニュアルを参照。
- https://support.gusuku.io/ja-JP/support/solutions/articles/36000303634
-
csvラポ kintone連携プラグイン
- kintoneの一覧印刷に特化した帳票サービス。レイアウトを必要としないのが特徴。
Thinreports を使った帳票印刷
サーバーレスが普通になってきた昨今、帳票印刷はサーバーレスで自前で実装することも可能になってきましたね。
概要
Thinreportsは専用のデザイナーアプリ Thinreports EditorとRubyのSDK Thinreports Generatorを使ってPDFを出力するソリューションです。
デザイナーではドラッグ&ドロップでレイアウトを作成出来ます。
データとレイアウトファイルを繋ぐコードをRubyで記述します。
専用サーバーで利用する
Ruby on Rails 等の Ruby製 WebアプリケーションフレームワークにレイアウトファイルとSDKをインストールすることでWebアプリケーションにPDF出力機能を追加することが出来ます。
サーバーレスで利用する
AWS Lambda などを利用することで専用のサーバーを自前で用意することなくPDF出力機能を追加出来ます。
サーバーレスでPDF処理を実装する
システム構成
システム構成イメージです。
AWS Lambda を利用してPDF印刷を実装する手順です。
流れ
- Thinreportsデザイナーで印刷レイアウトを作成
- SDK(Thinreports Generator for Ruby) https://rubygems.org/gems/thinreports を利用して印刷プログラムを作成
- 印刷レイアウトと印刷プログラムを AWS Lambda に登録
- kintone に設置した JavaScript から Lambda を実行
- kintone にPDFファイルがアップロードされる
順に説明していきます。
1. Thinreportsデザイナーで印刷レイアウトを作成

下記リンクを参照。
2. SDK を利用して印刷プログラムを作成
PDF生成
AWS Lambda にて Thinreports Generator を使って PDFファイルを生成します。
拙稿をご覧ください。
# coding: utf-8
require 'thinreports'
require 'json'
require 'aws-sdk-s3'
require './file_upload.rb'
require './file.rb'
def lambda_handler(event:, context:)
app_id = nil
record_id = nil
field_code = 'file'
begin
print 'JSON.parse event.body => '
pp JSON.parse(event['body'])
event_body = JSON.parse(event['body'])
record = event_body['record']
app_id = event_body['appId']
record_id = event_body['recordId']
print 'record => '
pp record
puts '$id => ', record['$id']['value']
# puts 'text => ', record["text"]["value"]
puts 'title => ', record['title']['value']
rescue => e
puts "#{e.class}: #{e.message}"
puts e.backtrace
end
begin
# region = 'S3バケットのリージョン'
# bucket_name = 'バケット名'
key = 'put-hello-ruby.pdf'
# S3 Backet Object init
s3 = Aws::S3::Resource.new(region: region)
# pp s3
obj = s3.bucket(bucket_name).object(key)
# Thinreports Object init
report = Thinreports::Report.new layout: 'hello_world'
# 1st page
report.start_new_page
report.page.item(:world).value(record["$id"]["value"])
report.page.item(:thinreports).value(record["text"]["value"])
report.page.item(:title).value(record["title"]["value"])
# pp report
obj.put(body: report.generate)
# /tmpファイルに書き込み
filename = '/tmp/put-hello-ruby-' + Time.new.localtime("+09:00").strftime("%Y%m%d%H%M%S") + '.pdf'
puts filename
File.open(filename, 'w+') { |f| f<< report.generate }
puts `ls -la /tmp`
# ファイルアップロード
res = file_upload(filename)
pp res
# pp JSON.parse(res.body)
file_key = res['fileKey']
# 添付ファイルフィールド更新
res_file = file_update(app_id, record_id, field_code, file_key)
pp res_file
rescue => e
puts "#{e.class}: #{e.message}"
puts e.backtrace
end
{ statusCode: 200, body: JSON.generate('Hello Lambda! Thinreports for Ruby') }
end
ファイルアップロード
Lambda から /tmp に作成した PDFファイルを、kintoneにアップロードします。
下記拙稿も参考にして下さい。
kintoneの領域にファイルアップロードが成功した時に、ファイルキーが返却されます。
require 'rubygems'
require 'bundler/setup'
require 'dotenv/load'
require 'net/http'
require 'uri'
require 'json'
require 'pp'
def file_upload(filename)
puts __FILE__
begin
upload_file = File.open filename, "r"
data = [["file", upload_file, {"filename" => filename, "content_type" => "application/pdf"}]]
url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/file.json"
uri = URI.parse(url)
api_token = ENV['API_TOKEN']
req = Net::HTTP::Post.new(uri.path)
req['X-Cybozu-API-Token'] = api_token
req['Content-Type'] = 'multipart/form-data'
req.set_form(data, "multipart/form-data")
pp req # <Net::HTTP::Post POST>
res = ''
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
res = http.request(req)
res.each_header do |name, val|
puts "name = #{name}, val = #{val}"
end
case res.code.to_i
when 200
pp JSON.parse(res.body) # {"fileKey"=>"b28a1ecc-e8dc-4a10-b030-7cf96b35b272"}
else
pp %Q(#{res.code} #{res.message})
pp JSON.parse(res.body)
end
end
upload_file.close
JSON.parse(res.body)
rescue => exception
pp exception
upload_file.close
exception.message
end
end
アップロードしたファイルとレコードの関連付け
下記拙稿を参考にして下さい。
前段で取得したファイルキーを使って、レコードの添付ファイルフィールドを更新します。
require 'rubygems'
require 'bundler/setup'
require 'dotenv/load'
require 'net/http'
require 'uri'
require 'json'
require 'pp'
def file_update(app, id, field_code, file_key)
puts __FILE__
begin
field_code = field_code || 'file'
url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/record.json"
uri = URI.parse(url)
api_token = ENV['API_TOKEN']
req = Net::HTTP::Put.new(uri.path)
req['X-Cybozu-API-Token'] = api_token
req['Content-Type'] = 'application/json'
req.body = JSON.generate({
"app" => app,
"id" => id,
"record" => {field_code => {"value" => [{"fileKey"=>file_key}]}}
})
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
res = http.request(req)
res.each_header do |name, val|
puts "name=#{name}, val=#{val}"
end
case res.code.to_i
when 200
pp JSON.parse(res.body)
JSON.parse(res.body)
else
pp %Q(#{res.code} #{res.message})
pp JSON.parse(res.body)
JSON.parse(res.body)
end
}
rescue => exception
pp exception
exception.message
end
end
3. 印刷レイアウトと印刷プログラムを AWS Lambda に登録
作成した プログラムファイル及びライブラリ、印刷レイアウトファイルをZip圧縮して Lambda にアップロードします。
下記拙稿を参考にして下さい。
4. kintone に設置した JavaScript から Lambda を実行
下記拙稿を参考にして下さい。
アプリに添付ファイルのフィールドを追加しています。


5. kintone にPDFファイルがアップロードされる
成功すると添付ファイルフィールドにPDFファイルがアップロードされます。
詳細画面を再読み込みして下さい。


まとめ
AWS Lambdaを始めとするサーバーレスのサービスが一般的になり、フロントエンドとバックエンドを隔てる壁も随分と低く、曖昧になってきたと感じています。
フロントエンドのプログラマもバックエンドの世界を知る機会があると思いますし、バックエンドの方もフロントエンドを理解した上でバックエンドの処理を考える良い機会があるのではと感じています。
参考リンク
Thinreports関連
AWS関連
- AWS Lambda
- AWS SDK for Ruby Lambda.invoke
- AWS Lambda Ruby & Serverless Framework & FFmpeg によるアップロード動画からのサムネ画像生成
- [AWS] API Gateway + Lambda for Ruby + S3 + Slack通知をSAMで構築
- AWS Cloud9からSAM Localをためしてみる
- AWS SDK SAM CLI
- AWS Serverless Application Model (SAM) コマンドラインインターフェイス。サーバレスアプリケーションをローカルで構築、テスト、デバッグする
- AWS ドキュメント
- AWS Code Sample Catalog