ノーコードでクラウド上のデータとの連携を実現。
詳細はこちら →PCA会計DXのデータをCData ODBC REST Driver + Tableauで可視化してみる
はじめに
基幹・会計システムのデータ分析・連係の需要はまだまだ尽きることがありませんが、各種アプリケーションが対応しているBIツールやETL/EAIツールは少ないのが実情かと思います。
そこで今回はPCAの会計ソフト、会計DXが公開しているWeb APIを用いて、CData ODBC REST Driver経由でBIツールのTableauとの連係を実現してみました。
PCA会計DXとは
ピー・シー・エー株式会社が提供する一般企業様向け会計ソフトです。
詳しくは以下のURLからどうぞ。
http://pca.jp/area_product/prokai.html
また、今回使用するPCA クラウド Web APIについては、以下のWebサイトで詳しく記載されています。
http://pca.jp/area_top/ltd/160411.html
実現イメージ
各BIツール(Tableau、QlikSence、PowerBI)からはODBCインタフェースでSQL(Select文)を発行するとCData REST ODBC Driverが、PCA会計DXのWebAPIのエンドポイントに対してHTTPリクエストでGetメソッドを発行します。
Jsonフォーマットで返ってきたデータセットをCData REST ODBC DriverがODBCインタフェースのResultsetに変換してBIツールに返します。
これにより、BIツールからアドホックにSQLによるリクエストがあったタイミングで最新のデータをPCA会計DXから取得することが可能です。
前提条件
本記事では以下のサービスや製品を使用しています。
- PCA 会計DX クラウド版 (あらかじめインストールしておいてください)
- CData REST ODBC Driver ※30日間の評価版あり
- Tableau Desktop ※無料トライアル版あり
- Googleアカウント(OAuth用アプリケーション登録をするために必要となります)
手順
PCA Web API 利用準備
PCA Web APIを利用する場合は、あらかじめ利用申請等が必要になるので、以下のWeb Siteから実施しておきます。
http://pca.jp/area_top/ltd/160411.html
申請後PCAクラウドアプリケーション利用用アカウントとして、ServiceユーザーIDとパスワード、招待コードが送られてくるので、控えておきましょう。
その上で、以下Webサイトにアクセスし、OAuthの認証を通すためにアプリケーション登録を行います。
https://pcadev.jp/DevelopersConsole/
Webサイトにアクセスすると、以下のような画面が表示されるので、任意のGoogleアカウントでログインします。
一番最初はアカウント登録をする必要があるので、各種情報を招待コードを入力し、[登録]をクリックします。
登録完了後、アプリケーションの管理画面へ遷移します。
この画面からOAuth認証用のアプリケーション登録を行い、認証に必要なClientID・ClientSecretを取得します。
それでは実際に[新規アプリケーションの作成]をクリックし、アプリケーション登録を行います。
以下の情報をそれぞれ入力し、[登録]をクリックします。
- アプリケーション名 : 任意のアプリケーション名を入力します。
- 会社名 : 任意の会社名を入力します。
- 説明 : 任意の説明文を入力します。
- リダイレクトURL : http://localhost:33333 (33333ポートを別なアプリケーションで使用している場合は違うポートを指定してください)
- アプリケーションURL : http://localhost:33333
- プログラムID : cdata等任意のプログラムIDを入力します。
- 使用するPCAのAPI : 「PCA会計DX」を選択します。
登録完了後、クライアントIDとクライアントシークレットが表示されるので、控えておきます。
以上でアプリケーション登録は完了です。
REST データ RSDファイル
続いて、PCAのWeb APIをCData ODBC REST DeiverがSQLとして解釈できるように設定ファイルを作成します。
サンプルとしてPCA会計DXの仕訳伝票 (InputSlip)のデータを取得するための設定ファイルを作成していますので、以下のXMLを[InputSlip.rsd]というファイル名で保存して、利用してみてください。
保存先フォルダは後ほど使用するので「C:\CData_REST\PCA」といった書き込み可能な任意のフォルダに配置してください。
以下、InputSlip.rsdのサンプルです。
<rsb:script xmlns:rsb="http://www.rssbus.com/ns/rsbscript/2" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- See Column Definitions to specify column behavior and use XPaths to extract column values from JSON. --> <rsb:info title="JSONData" desc="Generated schema file." xmlns:other="http://www.rssbus.com/ns/rsbscript/2/other"> <!-- You can modify the name, type, and column size here. The name must match the values in the rsb:script block below --> <attr name="BEVersion" xs:type="integer" readonly="false" other:xPath="BEVersion" /> <attr name="CrBankTransferState" xs:type="string" readonly="false" other:xPath="{SubRepeatElement}/CrBankTransferState" /> <attr name="CrBuId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/CrBuId" /> <attr name="CrHojoId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/CrHojoId" /> <attr name="CrId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/CrId" /> <attr name="CrKmkId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/CrKmkId" /> <attr name="CrMoney" xs:type="double" readonly="false" other:xPath="{SubRepeatElement}/CrMoney" /> <attr name="CrReserve1" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/CrReserve1" /> <attr name="CrReserve2" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/CrReserve2" /> <attr name="CrReserve3" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/CrReserve3" /> <attr name="CrStamp" xs:type="string" readonly="false" other:xPath="{SubRepeatElement}/CrStamp" /> <attr name="CrTaxCalcMode" xs:type="string" readonly="false" other:xPath="{SubRepeatElement}/CrTaxCalcMode" /> <attr name="CrTaxClassId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/CrTaxClassId" /> <attr name="CrTaxKmkId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/CrTaxKmkId" /> <attr name="CrTaxMoney" xs:type="double" readonly="false" other:xPath="{SubRepeatElement}/CrTaxMoney" /> <attr name="DrBankTransferState" xs:type="string" readonly="false" other:xPath="{SubRepeatElement}/DrBankTransferState" /> <attr name="DrBuId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/DrBuId" /> <attr name="DrHojoId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/DrHojoId" /> <attr name="DrId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/DrId" /> <attr name="DrKmkId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/DrKmkId" /> <attr name="DrMoney" xs:type="double" readonly="false" other:xPath="{SubRepeatElement}/DrMoney" /> <attr name="DrReserve1" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/DrReserve1" /> <attr name="DrReserve2" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/DrReserve2" /> <attr name="DrReserve3" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/DrReserve3" /> <attr name="DrStamp" xs:type="string" readonly="false" other:xPath="{SubRepeatElement}/DrStamp" /> <attr name="DrTaxCalcMode" xs:type="string" readonly="false" other:xPath="{SubRepeatElement}/DrTaxCalcMode" /> <attr name="DrTaxClassId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/DrTaxClassId" /> <attr name="DrTaxKmkId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/DrTaxKmkId" /> <attr name="DrTaxMoney" xs:type="double" readonly="false" other:xPath="{SubRepeatElement}/DrTaxMoney" /> <attr name="JournalHeaderId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/JournalHeaderId" /> <attr name="LabelId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/LabelId" /> <attr name="LabelString" xs:type="unknown" readonly="false" other:xPath="{SubRepeatElement}/LabelString" /> <attr name="LineNumber" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/LineNumber" /> <attr name="Number1" xs:type="unknown" readonly="false" other:xPath="{SubRepeatElement}/Number1" /> <attr name="Number2" xs:type="unknown" readonly="false" other:xPath="{SubRepeatElement}/Number2" /> <attr name="RemId" xs:type="integer" readonly="false" other:xPath="{SubRepeatElement}/RemId" /> <attr name="Summary" xs:type="string" readonly="false" other:xPath="{SubRepeatElement}/Summary" /> <attr name="CrBankTransferState" xs:type="string" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrBankTransferState" /> <attr name="CrBuId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrBuId" /> <attr name="CrHojoId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrHojoId" /> <attr name="CrId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrId" /> <attr name="CrKmkId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrKmkId" /> <attr name="CrMoney" xs:type="double" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrMoney" /> <attr name="CrReserve1" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrReserve1" /> <attr name="CrReserve2" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrReserve2" /> <attr name="CrReserve3" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrReserve3" /> <attr name="CrStamp" xs:type="string" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrStamp" /> <attr name="CrTaxCalcMode" xs:type="string" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrTaxCalcMode" /> <attr name="CrTaxClassId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrTaxClassId" /> <attr name="CrTaxKmkId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrTaxKmkId" /> <attr name="CrTaxMoney" xs:type="double" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/CrTaxMoney" /> <attr name="DrBankTransferState" xs:type="string" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrBankTransferState" /> <attr name="DrBuId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrBuId" /> <attr name="DrHojoId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrHojoId" /> <attr name="DrId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrId" /> <attr name="DrKmkId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrKmkId" /> <attr name="DrMoney" xs:type="double" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrMoney" /> <attr name="DrReserve1" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrReserve1" /> <attr name="DrReserve2" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrReserve2" /> <attr name="DrReserve3" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrReserve3" /> <attr name="DrStamp" xs:type="string" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrStamp" /> <attr name="DrTaxCalcMode" xs:type="string" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrTaxCalcMode" /> <attr name="DrTaxClassId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrTaxClassId" /> <attr name="DrTaxKmkId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrTaxKmkId" /> <attr name="DrTaxMoney" xs:type="double" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/DrTaxMoney" /> <attr name="JournalHeaderId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/JournalHeaderId" /> <attr name="LabelId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/LabelId" /> <attr name="LabelString" xs:type="unknown" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/LabelString" /> <attr name="LineNumber" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/LineNumber" /> <attr name="Number1" xs:type="unknown" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/Number1" /> <attr name="Number2" xs:type="unknown" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/Number2" /> <attr name="RemId" xs:type="integer" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/RemId" /> <attr name="Summary" xs:type="string" readonly="false" other:xPath="InputSlipDataList/BEInputSlipData/Summary" /> <attr name="ApprovalAreaUserId1" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/ApprovalAreaUserId1" /> <attr name="ApprovalAreaUserId2" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/ApprovalAreaUserId2" /> <attr name="ApprovalAreaUserId3" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/ApprovalAreaUserId3" /> <attr name="ApprovalAreaUserId4" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/ApprovalAreaUserId4" /> <attr name="Date_SerializeTarget" xs:type="string" readonly="false" other:xPath="InputSlipHeader/Date/SerializeTarget" /> <attr name="HsId" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/HsId" /> <attr name="Id" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/Id" /> <attr name="InputAreaUserId" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/InputAreaUserId" /> <attr name="InputModuleName" xs:type="unknown" readonly="false" other:xPath="InputSlipHeader/InputModuleName" /> <attr name="JournalClass" xs:type="string" readonly="false" other:xPath="InputSlipHeader/JournalClass" /> <attr name="LockType" xs:type="string" readonly="false" other:xPath="InputSlipHeader/LockType" /> <attr name="ManageClass" xs:type="string" readonly="false" other:xPath="InputSlipHeader/ManageClass" /> <attr name="Number" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/Number" /> <attr name="OldId" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/OldId" /> <attr name="OrgId" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/OrgId" /> <attr name="Reserve1" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/Reserve1" /> <attr name="Reserve2" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/Reserve2" /> <attr name="Reserve3" xs:type="integer" readonly="false" other:xPath="InputSlipHeader/Reserve3" /> <attr name="ReserveMoney1" xs:type="double" readonly="false" other:xPath="InputSlipHeader/ReserveMoney1" /> <attr name="ReserveMoney2" xs:type="double" readonly="false" other:xPath="InputSlipHeader/ReserveMoney2" /> <attr name="ReserveMoney3" xs:type="double" readonly="false" other:xPath="InputSlipHeader/ReserveMoney3" /> <attr name="ReserveString1" xs:type="unknown" readonly="false" other:xPath="InputSlipHeader/ReserveString1" /> <attr name="ReserveString2" xs:type="unknown" readonly="false" other:xPath="InputSlipHeader/ReserveString2" /> <attr name="ReserveString3" xs:type="unknown" readonly="false" other:xPath="InputSlipHeader/ReserveString3" /> <attr name="State" xs:type="string" readonly="false" other:xPath="InputSlipHeader/State" /> <attr name="UpdateTime" xs:type="datetime" readonly="false" other:xPath="InputSlipHeader/UpdateTime" /> <attr name="VanishState" xs:type="boolean" readonly="false" other:xPath="InputSlipHeader/VanishState" /> <attr name="MainDrCrMode" xs:type="string" readonly="false" other:xPath="MainDrCrMode" /> <attr name="PermanentId" xs:type="integer" readonly="false" other:xPath="PermanentId" /> <attr name="SlipState" xs:type="string" readonly="false" other:xPath="SlipState" /> <attr name="TaxOrgMoneyCalcedByAs" xs:type="boolean" readonly="false" other:xPath="TaxOrgMoneyCalcedByAs" /> </rsb:info> <rsb:set attr="outer.uri" value="[_connection.ServerURL][_connection.ApiVersion]/[_connection.ProductCode]/SelectDataArea" /> <rsb:set attr="outer.Method" value="POST"/> <rsb:set attr="outer.ContentType" value="application/json" /> <rsb:set attr="outer.encodepostdata" value="false" /> <rsb:set attr="outer.Data"> { "DataArea":"[_connection.DataAreaID]" } </rsb:set> <rsb:set attr="outer.EnablePaging" value="True" /> <rsb:set attr="inner.uri" value="[_connection.ServerURL][_connection.ApiVersion]/[_connection.ProductCode]/Find/InputSlip" /> <rsb:set attr="inner.RepeatElement" value="/ArrayOfBEInputSlip/BEInputSlip" /> <rsb:set attr="inner.SubRepeatElement" value="/ArrayOfBEInputSlip/BEInputSlip/InputSlipDataList/BEInputSlipData" /> <rsb:set attr="inner.ContentType" value="application/json" /> <rsb:set attr="inner.header:name" value="Accept" /> <rsb:set attr="inner.header:value" value="application/json" /> <!-- The GET method corresponds to SELECT. Within the script block, you can see the URI modified to append a query string parameter. The results of processing are pushed to the schema's output. See SELECT Execution for more information. --> <rsb:script method="GET"> <rsb:call op="jsonproviderGet" input="outer" output="firstOut"> </rsb:call> </rsb:script> <!-- The GET method corresponds to SELECT. Within the script block, you can see the URI modified to append a query string parameter. The results of processing are pushed to the schema's output. See SELECT Execution for more information. --> <rsb:script method="GET"> <rsb:call op="jsonproviderGet" input="inner"> <rsb:push/> </rsb:call> </rsb:script> </rsb:script>
RSDファイルの詳しい設定方法は下記URLのヘルプページに記載しています。
http://cdn.cdata.com/help/HWC/odbc/pg_rsbschemaintro.htm
CData ODBC REST Driverのインストール
TableauとPCA会計クラウドのAPIを繋ぐために必要となるCData ODBC REST Driverをインストールします。
CData REST ODBC Driverの30日間の評価版をダウンロードします。ダウンロードの際には、Emailの登録が必要となります。
ダウンロードしたsetup.exeファイルをBIツールがインストールされているマシンにインストールします。インストールウィザードに従い、EULAを確認したうえでインストールを完了します。
※途中、ライセンスサーバーへのオンラインアクティベーションが行われるためネットワーク環境に接続されている必要があります。
インストールが完了すると、ODBCのDSN設定のウィンドウが立ち上がります。
以下の項目をセットします。
-
OAuth
- OAuth Version : 2.0
- Callback URL :
- OAuth Access Token URL : https://east02.pcawebapi.jp/v1/Acc20/Auth/Token
- OAuth Authorization URL : https://east02.pcawebapi.jp/v1/Acc20/Auth/Authorize
- OAuth Client Id : PCA Developers Console で取得したクライアントID
- OAuth Client Secret : PCA Developers Console で取得したクライアントシークレット
- OAuth Grant Type : CODE
- OAuth Refresh Token UL : https://east02.pcawebapi.jp/v1/Acc20/Auth/Token
-
Schema
- Location : 先程RSDファイルを配置したフォルダパス(例:C:\CData_REST\PCA)
-
その他
- Other : ProductCode=Acc20;ServerURL=https://east02.pcawebapi.jp/;ApiVersion=v1;DataAreaID=P20V01C081ACC0001;
OtherのProductCodeは会計DXの設定値を置いていますが、違うPCAアプリケーションを利用する場合は都度適切な値に書き換えてください。 また、DataAreaIDは試用版の環境となっているので、こちらも都度適切な値へ書き換えてください。
各種URLの接続先はEast02に設定しています。
「接続のテスト」ボタンをクリックするとOAuth認証のため事前に登録したアプリケーションの認証画面がブラウザで立ち上がります。
配布されている[サービスユーザーID][パスワード]を入力し、サービス認証をクリックします。
次に、PCA会計DXのユーザーアカウントの情報を入力し、ログオンを行います。
アクセス許可画面が表示されるので、内容を確認の上[データの利用を許可する]をクリックします。
OAuth Authorization Successful!の画面が表示されれば、認証完了です。
Tableauでの接続確認
Tableau Desktopを起動して、データ接続より「サーバーへ」>「詳細」>「その他データベース(ODBC)」を選択します。
「その他のデータベース(ODBC)」設定ウィンドウが開いたら、接続手段内のDSNから「CData REST Source」を選択して「サインイン」します。
「データソース」画面が開くので、左側のペインで、表「InputSlip (REST.InputSlip) (CData))」を選択して、右上のエリアにドラッグ&ドロップします。抽出を行い、右下のデータプレビューにPCA会計DXの仕訳伝票が表示されることを確認します。
あとはTableauの機能を利用して、各種グラフやマトリクスを作成することが可能です。