開発情報・ナレッジ

投稿者: ShiningStar株式会社 2024年7月31日 (水)

APIで取得したデータをCSVでダウンロードさせるサンプルプログラム

APIで取得したデータをCSVにしてダウンロードが出来るボタンを設置する方法をご紹介いたします。
レコードリストの抽出条件とAPIでデータを取得する条件を一致させるとレコードリストのデータをダウンロードさせる様なボタンを作成することができます。
本記事のプログラムはあくまでサンプルですので、
ダウンロードさせたい項目や並び順等は閲覧者様ご自身で調整して頂く必要がございます。


サンプルプログラム

ページの Javascript、PHP、bodyタブにコードを貼り付けて、設定値を変更してください。
設定値は例で入れていますので、参考に変更をしてください。

PHP
<?php
//------------------------------
// 設定値
//------------------------------
define("API_URL", "https://api.spiral-platform.com/v1");
define("API_KEY", "");
define("APP_ROLE", "");
define("DB_ID", "");
define("APP_ID", "");

//------------------------------
// API実行
//------------------------------
$commonBase = CommonBase::getInstance();

$query = "";
//取得するレコードを絞り込みたい場合やソートを行いたい場合などは記載ください。
//$query .= "?where=@フィールド識別名='値'&sort=_id:asc";
 
//レコードの取得
$resultRecordListSelect = $commonBase->apiCurlAction("GET", "/apps/". APP_ID. "/dbs/". DB_ID. "/records". $query);

$jsonData = json_encode($resultRecordListSelect['items'], JSON_PRETTY_PRINT);
$SPIRAL->setTHValue("response",$jsonData);
//------------------------------
// 共通モジュール
//------------------------------
class CommonBase {
    /**
     * シングルトンインスタンス
     * @var UserManager
     */
    protected static $singleton;

    public function __construct() {
        if (self::$singleton) {
            throw new Exception('must be singleton');
        }
        self::$singleton = $this;
    }
    /**
     * シングルトンインスタンスを返す
     * @return UserManager
     */
    public static function getInstance() {
        if (!self::$singleton) {
            return new CommonBase();
        } else {
            return self::$singleton;
        }
    }
    /**
     * V2用 API送信ロジック
     * @return Result
     */
    function apiCurlAction($method, $addUrlPass, $data = null, $multiPart = null, $jsonDecode = null) {
        $header = array(
            "Authorization:Bearer ". API_KEY,
            "X-Spiral-Api-Version: 1.1",
        );
        if($multiPart) {
            $header = array_merge($header, array($multiPart));
        } else {
            $header = array_merge($header, array("Content-Type:application/json"));
        }
        if(APP_ROLE){
			$header = array_merge($header, array("X-Spiral-App-Role: ".APP_ROLE));
		}
        // curl
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_URL, API_URL. $addUrlPass);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        if ($method == "POST") {
            if ($multiPart) {
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            } else {
                curl_setopt($curl, CURLOPT_POSTFIELDS , json_encode($data));
            }
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        }
        if ($method == "PATCH") {
            curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        }
        if ($method == "DELETE") {
            curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        }
        $response = curl_exec($curl);
        if (curl_errno($curl)) echo curl_error($curl);
        curl_close($curl);
        if($jsonDecode){
			return $response;
		}else{
            return json_decode($response, true);
		}
    }
}
?>

body(HTML)
<button id="download-btn">ダウンロード</button>

<th:block th:if="${cp.result.isSuccess}">
    <!-- PHP正常完了した場合に表示 -->
    <p id="response" style="display:none;" th:text="${cp.result.value['response']}"></p>
</th:block>
<th:block th:if="${!cp.result.isSuccess}">
    <!-- PHPにエラー起こった場合に表示 -->
    <p th:text="${cp.result.errorMessage}">error message</p>
</th:block>

Javascript
document.addEventListener('DOMContentLoaded', function() {
    // CSVファイル名を設定
    const csvFileName = 'data.csv';

    // JSONデータを<p>タグから取得
    const responseElement = document.getElementById('response');
    const jsonData = JSON.parse(responseElement.textContent);

    // JSONデータをコンソールに出力して確認
    console.log(jsonData);

    // ネストされたオブジェクトをフラットにする関数
    function flattenObject(ob) {
        let toReturn = {};

        for (let i in ob) {
            if (!ob.hasOwnProperty(i)) continue;

            if ((typeof ob[i]) === 'object' && ob[i] !== null) {
                let flatObject = flattenObject(ob[i]);
                for (let x in flatObject) {
                    if (!flatObject.hasOwnProperty(x)) continue;
                    toReturn[i + '.' + x] = flatObject[x];
                }
            } else {
                toReturn[i] = ob[i];
            }
        }
        return toReturn;
    }

    // JSONをCSVに変換する関数
    function convertJSONToCSV(jsonData) {
        const flatData = jsonData.map(flattenObject);
        const keys = Object.keys(flatData[0]);
        const csvRows = [];

        // ヘッダー行
        csvRows.push(keys.join(','));

        // データ行
        for (const row of flatData) {
            const values = keys.map(key => JSON.stringify(row[key], null, 2)).join(',');
            csvRows.push(values);
        }

        return csvRows.join('\n');
    }

    // ボタンのクリックイベントにCSVダウンロード処理を設定
    document.getElementById('download-btn').addEventListener('click', function () {
        const csvData = convertJSONToCSV(jsonData);
        const blob = new Blob([csvData], { type: 'text/csv' });
        const url = URL.createObjectURL(blob);

        const a = document.createElement('a');
        a.href = url;
        a.download = csvFileName; // 設定値のファイル名を使用
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);

        // URLオブジェクトのメモリを解放
        URL.revokeObjectURL(url);
    });
});

設定値

Javascript

csvFileNameの値を変更することで、ダウンロードさせるファイル名を変更できます。
PHP

APIでレコードリストを取得しています。
サンプルでは取得したレコードの情報を全てダウンロード対象とさせていますので、
項目を絞りたい場合や、検索条件を指定したい場合は、
apiCurlActionへのwhere文を指定し、データを絞り込んだ上でレコード取得を行ってください。
body(HTML)

id="download-btn"にてダウンロードボタンを配置しています。
デザインを当てたい等カスタマイズをしたい場合はこのボタンに対してCSSを書いてください。

SPIRALのPHP及びthymeLeafの仕様上、
PHPにて取得したレコードをid="response"のpタグ内に一旦出力する必要があります。
そのデータを用いてJavaScriptに渡してダウンロードさせる処理を実現しています。
なのでdisplay:none;をかけています。
サンプル上PHPでエラーが起こった場合はエラーメッセージが出力されるようにしていますが、
実際にお使いになる場合は適切なエラーハンドリングを行ってください。
解決しない場合はこちら コンテンツに関しての
要望はこちら