PCA会計DXのデータをCData ODBC REST Driver + Tableauで可視化してみる

by 庄司 里菜 | 2018年05月14日

はじめに

基幹・会計システムのデータ分析・連係の需要はまだまだ尽きることがありませんが、各種アプリケーションが対応している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設定のウィンドウが立ち上がります。

以下の項目をセットします。


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の機能を利用して、各種グラフやマトリクスを作成することが可能です。

関連コンテンツ

トライアル・お問い合わせ

30日間無償トライアルで、CData のリアルタイムデータ連携をフルにお試しいただけます。記事や製品についてのご質問があればお気軽にお問い合わせください。