見出し画像

【Tableau】APIを活用した柔軟で拡張性の高いデータダウンロード機能の実装方法

こんにちは、らむです。
ナビタイムジャパンの移動データ事業にて、『Tableau』を用いて移動ビッグデータの比較・分析が可能なプロダクト開発を行っています。
2024年7月4日、移動データ事業が『Tableau』を活用して提供している『インバウンドプロファイラー』にダウンロード機能を追加しました。

ダウンロードの様子

ダウンロード機能の追加にあたり、『Tableau』が標準で提供しているダウンロード機能を活用することを検討しました。しかし、表示用のフラグがダウンロードデータに残ってしまったり、無制限にデータがダウンロードできたりするなどプロダクトに追加するにはいくつかの課題が見つかりました。
そこで、Tableau Extension APITableau REST APIを活用し、より柔軟で拡張性の高いダウンロード機能を開発しました。

本記事では『Tableau Cloud』での柔軟で拡張性の高いデータダウンロード機能の実装に焦点を当てており、Tableauを使用したことのある方を想定読者としていますので、『Tableau』の使い方に関する説明については割愛しています。Tableau用語に関する詳細は公式サイトの用語集をご確認ください。
今回の記事は、下記の環境で実行しました。

  • Tableau Desktop 2023.2.4

  • Tableau Cloud 2024.2(24/07/2024)


使用した技術

『Tableau』では、「Tableau Extension API」と「Tableau REST API」が提供されています。
詳細については、各APIの公式ドキュメントを参照してください。


Tableau Extension API

Tableau Extension APIを利用することで、ダッシュボード内のデータやフィルタの取得、イベントの発火の検知ができるウェブアプリケーションの開発が可能です。開発したウェブアプリケーションをサーバーへのホストを行い、ホスト先のURLをtrexファイルに記載することで拡張機能を作成できます。作成したtrexファイルを他のダッシュボードオブジェクトと同様に配置することでワークブックへの拡張機能の追加が可能です。

Tableau Extension APIを使用した拡張機能の構成

Tableau REST API

Tableau REST APIは、『Tableau Server』や『Tableau Cloud』の管理やデータ取得を行うためのAPIです。Tableau REST APIを利用することで外部のアプリケーションから『Tableau』の機能の操作やデータの取得が実現できます。『Tableau Cloud』上でデータダウンロードが可能な権限でなくても、外部のアプリケーションからデータを取得することが可能です。

データダウンロード時のプロセス

以下は、今回作成するデータダウンロードのプロセスです。

  1. 拡張機能内の「ダウンロード」ボタンをクリックします。

  2. Tableau Extension APIを使って、現在のワークブックのフィルタ条件を取得します。

  3. 取得したフィルタ条件を用いて、自作したデータダウンロードAPIにリクエストを送信します。

  4. フィルタ条件を適用してTableau REST APIにリクエストを送り、必要なデータを取得します。

  5. 取得したデータを整形し、Excelファイルとして生成します。

  6. ブラウザ上で自動的にファイルのダウンロードが開始されます。


データダウンロードの手順

データダウンロード機能作成手順

1. データダウンロード用のワークシートを作成

ダッシュボード上で表示されるデータと、実際にダウンロードされるデータが一致するようにするため、ダウンロード専用のワークシートを作成します。このワークシートでは、ダッシュボードで使用しているフィルタは適用しません。

ダッシュボード用のシートとの差分

理由としては、Tableau REST APIがワークブックをアップロードした時点の状態に基づいてデータを取得するためです。もしフィルタが適用された状態でアップロードされていると、ダウンロードされるデータに誤差が生じる可能性があります。

そのため、正確なデータをダウンロードするために、ダウンロード用のワークシートにはフィルタをかけずに作成します。

2. データダウンロードAPIの作成

Tableau REST APIを利用して、下記のコードのようにデータダウンロード用ワークシートからデータを取得し、そのデータをExcelファイルとして整形・出力するAPIを作成します。

import os
import json
import io
from urllib import request, parse

class TableauClient:
    def __init__(self):
        self.__auth_token = None
        self.__base_url = None
        self.authenticate()

    # Tableau REST APIを使用するための認証を行う
    def authenticate(self):
        token_name = os.environ["TOKEN_NAME"]
        token_key = os.environ["TOKEN_KEY"]
        content_url = os.environ["CONTENT_URL"]
        request_url = "https://prod-apnortheast-a.online.tableau.com/api/3.22/auth/signin/"
        data = {
            "credentials": {
                "personalAccessTokenName": token_name,
                "personalAccessTokenSecret": token_key,
                "site": {"contentUrl": content_url},
            }
        }
        body = json.dumps(data).encode("utf-8")
        headers = {"Accept": "application/json", "Content-Type": "application/json"}
        req = request.Request(request_url, data=body, headers=headers, method="POST")

        with request.urlopen(req) as response:
            response_body = response.read().decode("utf-8")
            response_dict = json.loads(response_body)
            site_id = response_dict["credentials"]["site"]["id"]
            self.__base_url = f"https://prod-apnortheast-a.online.tableau.com/api/3.22/sites/{site_id}"
            self.__auth_token = response_dict["credentials"]["token"]

    # Tableau REST APIからデータを取得する
    def fetch_data(self, view_id, query_params={}):
        relative_url = f"/views/{view_id}/data"
        query_string = parse.urlencode(query_params)
        request_url = f"{self.__base_url}{relative_url}?{query_string}"
        headers = {"Accept": "application/json", "X-Tableau-Auth": self.__auth_token}
        req = request.Request(request_url, headers=headers, method="GET")

        with request.urlopen(req) as response:
            response_body = response.read().decode("utf-8")
        
        return response_body
        
# TableauClient クラスのインスタンス化
tableau_client = TableauClient()

# view_idとクエリパラメータを指定してデータを取得
view_id = "your_view_id"  # ダウンロードしたいview_idに置き換えてください
query_params = {"param1": "value1", "param2": "value2"}  # フィルタ条件をパラメータとして設定

# viewのデータを取得
summary_data = tableau_client.fetch_data(view_id, query_params)

作成したAPIをサーバーに配置し、いつでもデータダウンロードプロセスを実行できるように設定します。

3. 拡張機能の開発

下記の要件を満たすウェブアプリケーションを作成します。

  • Tableau Extension APIを使って、現在のワークブック(Tableau内のデータの集まり)のフィルタ条件を取得できる

  • 『Tableau』に追加されたボタンをクリックすると、そのフィルタ条件を使ってサーバー上のデータダウンロードAPIを実行できる

  • データダウンロードAPIから取得したデータをダウンロードできる

このアプリケーションを作るために、『Tableau』公式のTableau Extension APIのサンプルコードを参考にしました。サンプルにはfetchFiltersという関数があり、この関数を使ってフィルタ条件を取得しています。 次に、このウェブアプリケーションをサーバーに配置します。配置先のサーバーのURLをtrexファイルという設定ファイルに記載します。このtrexファイルを『Tableau Desktop』で読み込むことで、拡張機能として簡単にダッシュボードに追加できるようになります。

おわりに

今回は『Tableau』のデータダウンロード機能の実装について紹介しました。Tableau Extension APIやTableau REST APIを用いることで『Tableau』でのプロダクト開発において選択肢が増えていくように感じました。
今後も『Tableau』でのプロダクト開発でTableau Extension APIやTableau REST APIも選択肢に入れた柔軟なプロダクト開発を行っていこうと思います。