やりたいこと
- TableauOnline上にワークブックがある(都道府県別の売上ダッシュボード)
- ワークブックには複数のビュー(タブ・ダッシュボード)がある
- その複数ビューをPDF1ファイルで出力したい
- ワークブックにはフィルターがあり、値を変えながらPDF出力したい(都道府県のフィルターがあり、47都道府県分のPDFレポートを作りたい)
1,2,3までならば、TableauOnlineに標準で用意されているPDF出力機能をボタン操作すればよい。4の要件が追加されたとたん、GUI操作を47回もする羽目になるので自動化したい。
TableauServerClient(TSC)とは
TableauServerにあるデータをPythonで操作するライブラリ。
TableauServer RESTAPIで実装されていることは大体できる。
▼公式ドキュメントはこちら
https://tableau.github.io/server-client-python/docs/
やってみた
1都道府県分を出力
TSCの初期設定
import tableauserverclient as TSC
# サイトIDはTableau OnlineのURL中の/site/に続く文字列
tableau_auth = TSC.TableauAuth('user_id', 'user_password', site_id='サイトID')
# xxxxの部分はポッドIDを入力。ポッドIDは利用中のTableau OnlineのURLに含まれているので確認すること
server = TSC.Server('https://xxxx.online.tableau.com/')
# APIバージョンは以下のURL内の対応表から取得し、指定する
# https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_concepts_versions.htm
server.version = '3.15'
ワークブックIDの検索
今回は特定のワークブックをPDF出力したい。
ワークブックのIDはTableauOnline上では確認できなかったので、上の初期設定に続いてTSCの検索機能で調べる。
with server.auth.sign_in(tableau_auth):
all_workbooks_items = server.workbooks.filter(name='ワークブックの名前')
for workbook in all_workbooks_items:
print(workbook.id)
print(workbook.name)
'ワークブックの名前'
の部分に調べたいワークブックの名称(TableauOnline上で命名している名前)を打って、ワークブックのIDを探す。
対象ワークブックをPDF出力
PDF出力に必要な情報を入力
#ワークブックのIDを指定
workbook_id = 'ワークブックのID'
#PDF出力時の用紙サイズ等の設定(下記ドキュメントにその他の指定方法が載ってます)
#https://tableau.github.io/server-client-python/docs/api-ref#pdfrequestoptions-class
pdf_req_option = TSC.PDFRequestOptions(page_type=TSC.PDFRequestOptions.PageType.A4,orientation=TSC.PDFRequestOptions.Orientation.Landscape,maxage=100)
#オプション設定(フィルターの値の変更)
pdf_req_option.vf("Select_area","東京都")
pdf_req_option.vf("Select_area","東京都")
がミソ。これでダッシュボード内にある「Select_area」というフィルターの値を「東京都」に指定した状態。後述のPDF出力操作時にこのpdf_req_option
のパラメータを渡すと、「東京都」のPDFが出力される(これを47都道府県分for文回せばよい。
import PyPDF2
import os
#PDF出力
with server.auth.sign_in(tableau_auth):
#ワークブックを取得
workbook_item = server.workbooks.get_by_id(workbook_id)
#ワークブック内にある各ビューのビューIDを取得
server.workbooks.populate_views(workbook_item)
#---以下、ビューにPDFを出力して、それを最後にマージして1つのPDFデータにする---
#temp_pdf用の通し番号
page_num = 1
#pdfをマージするためのリスト
pdf_list = PyPDF2.PdfFileMerger()
#temp pdfを削除するとき用のリスト
tmp_list = []
for view_item in workbook_item.views:
#各ビューのpdfのオブジェクトを作成
server.views.populate_pdf(view_item,pdf_req_option)
#各ビューのpdf(temp_pdf)を出力
with open('C:\\Users\\…\\tmp'+ str(page_num) + '.pdf', 'wb') as f:
f.write(view_item.pdf)
#各ビューのpdf(temp_pdf)をリスト化
pdf_list.append(temp_pdf)
tmp_list.append(temp_pdf)
page_num = page_num + 1
#各ビューのPDFをマージ
pdf_list.write('C:\\Users\\…\\Downloads\\' + filter_values + '.pdf')
pdf_list.close()
#不要となった各ビューのPDF(temp_pdf)を削除
for tmp_pdf in tmp_list:
os.remove(temp_pdf)
まとめ
今まで書いたプログラムをまとめる。今回やりたいことは次のプログラムで実現できる。
import tableauserverclient as TSC
import PyPDF2
import os
#PDF出力先フォルダを指定
output_dir = 'C:\\Users\\…\\Downloads\\'
# サイトIDはTableau OnlineのURL中の/site/に続く文字列
tableau_auth = TSC.TableauAuth('user_id', 'user_password', site_id='サイトID')
# xxxxの部分はポッドIDを入力。ポッドIDは利用中のTableau OnlineのURLに含まれているので確認すること
server = TSC.Server('https://xxxx.online.tableau.com/')
# APIバージョンは以下のURL内の対応表から取得し、指定する
# https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_concepts_versions.htm
server.version = '3.15'
#出力条件の指定
workbook_id = 'ワークブックのID'
filter_values = ['東京都','京都府',…]
#PDF出力時の用紙サイズ等の設定
pdf_req_option = TSC.PDFRequestOptions(page_type=TSC.PDFRequestOptions.PageType.A4,orientation=TSC.PDFRequestOptions.Orientation.Landscape,maxage=100)
#サーバ接続&PDF出力・加工
with server.auth.sign_in(tableau_auth):
#ワークブックIDを指定
workbook_item = server.workbooks.get_by_id(workbook_luid)
#ワークブック内のビューを取得
server.workbooks.populate_views(workbook_item)
#フィルターごと(都道府県ごと)にループ
for filter_value in filter_values:
#フィルター値の変更
pdf_req_option.vf("Select_area",filter_values)
#temp_pdf用の通し番号
page_num = 1
#pdfをマージするためのリスト
pdf_list = PyPDF2.PdfFileMerger()
#temp pdfを削除するとき用のリスト
tmp_list = []
#ビューごとにループ(各ページのtempPDFを出力)
for view_item in workbook_item.views:
#各ビューのpdfのオブジェクトを作成
server.views.populate_pdf(view_item,pdf_req_option)
#各ビューのpdf(temp_pdf)を出力
with open(output_dir + 'tmp'+ str(page_num) + '.pdf', 'wb') as f:
f.write(view_item.pdf)
#各ビューのpdf(temp_pdf)をリスト化
pdf_list.append(temp_pdf)
tmp_list.append(temp_pdf)
page_num = page_num + 1
#各ビューをマージ(1つのPDFに統合)
pdf_list.write(output_dir + filter_values + '.pdf')
pdf_list.close()
#不要となった各ビューのPDF(temp_pdf)を削除
for tmp_pdf in tmp_list:
os.remove(temp_pdf)
参考