kintoneで他アプリのレコードデータをcsv化して添付ファイルフィールドに保存する

# 本記事の目的
kintoneには、アプリのレコードデータをファイルに書き出してダウンロードできる標準機能があります。
<a href="https://jp.cybozu.help/k/ja/user/app_collectdata/export/data_export.html">kintoneヘルプ-ファイルにデータを書き出す</a>

今回は、任意アプリのレコードデータをcsvファイルに書き出して添付ファイルフィールドに保存する、という機能をボタン１つで実行できるアプリをJavaScriptで作ってみます。

# 準備するもの
アプリを新規作成し、下記フィールドを追加します。
・ボタン配置用の「スペース」フィールド
・csvファイル保存先の「添付ファイル」フィールド
・ダウンロード実行日時を登録するための「日時」フィールド
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526064/31bf98ff-d2fc-2f21-89b1-a39b6df99ec4.jpeg">

またサンプルデータ用にkintoneアプリストアより「営業支援パック」を追加します。
![スクリーンショット 2021-10-04 5.21.27.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526064/13e5c90b-b8ca-4c6d-7cd7-d218fe3d5be1.jpeg)


# JavaScript記述
「JSEdit for kintone」でJavaScriptを書いていきます。
あらかじめ下記ライブラリを追加しておきましょう。
・kintoneUtility.min.js
・jQuery
・Moment.js

#### ボタンの設置
ダウンロード機能実行用のボタンを設置します。

```javascript
    var mySpaceFieldButton = document.createElement('button');
    mySpaceFieldButton.id = 'my_space_field_button';
    mySpaceFieldButton.innerText = 'ダウンロード'; //画面に表示される文字
    kintone.app.record.getSpaceElement('my_space_field').appendChild(mySpaceFieldButton);//要素ID「my_space_field」
```

![スクリーンショット 2021-10-04 5.19.26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526064/21cceb9f-90ba-c82c-eb4b-55eaadf45ea6.jpeg)

#### データ取得
次に、データを取得します。

```javascript
  // ボタン押下時のイベント
    mySpaceFieldButton.onclick = function(){
      var input_appid = 182; //取得先アプリID
      var outputfields = [
        '顧客名',
        '案件名',
        '確度',
        '受注予定日',
      ];  //出力フィールドのフィールドコード
      var filename = "download" + moment().format("YYYYMMDDHHmmss");
      var getinfo = {
        app: input_appid,
        query: '',
        fields: outputfields
      };
      
      kintoneUtility.rest.getAllRecordsByQuery(getinfo).then(function(resp) {
        var tmpRecords = resp.records;
        var totalCount = resp.records.length;
        console.log('tmpRecords');
        console.log(tmpRecords);
```

![スクリーンショット 2021-10-04 5.26.41.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526064/eff5da21-9691-9f03-f9b5-cacea32f0db3.jpeg)

#### データ整形
取得データを整形します。
フッター的なものも追加してみましょう。

```javascript
var csvdata_raw = outputfields.map(function(outputfield){
          return '"' + outputfield + '"';
        }).join(',') + "\n" +
        tmpRecords.map(function(record){
          return outputfields.map(function(outputfield){
            var value = record[outputfield].value;
            return '"' + (Array.isArray(value) ? value.join(',') : value) + '"';
          }).join(',');
        }).join("\n");
        console.log('csvdata_raw');
        console.log(csvdata_raw);
      
      // フッター情報追加
        var user = kintone.getLoginUser();
        var row_count = (csvdata_raw.match( /\n/g) || [] ).length;
        var csvdata_footer = csvdata_raw + "\n\n"
                            + '抽出日時' + ',' + moment().format("YYYYMMDDHHmmss") + "\n"
                            + '抽出ユーザー' + ',' + user.name + "\n"
                            + '件数' + ',' + Number(totalCount);
        console.log('csvdata_footer');
        console.log(csvdata_footer);
```

![スクリーンショット 2021-10-04 5.46.56.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526064/ee23a3d4-9091-6474-3ab9-f5a638e0d4cc.jpeg)

#### csv化して添付ファイルフィールドに保存

```javascript
var bom  = new Uint8Array([0xEF, 0xBB, 0xBF]); //文字コード
        var blob = new Blob([bom, csvdata_footer], {type: 'text\/csv'});
        var formData = new FormData();
        var date = new Date();
        var date_today = moment(date).format('YYYYMMDD');
        var current_time = moment().format("YYYY-MM-DDTHH:mm:ssZ"); //実行日時
        
        formData.append('__REQUEST_TOKEN__', kintone.getRequestToken());
        formData.append('file', blob, filename + '.csv');
        
        var url = 'https://サブドメイン名.cybozu.com/k/v1/file.json'; //環境
        var xhr = new XMLHttpRequest();
        xhr.open('POST', url);
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xhr.onload = function() {
          if (xhr.status === 200) {
            // success
            console.log(JSON.parse(xhr.responseText));
          } else {
            // error
            window.alert("予期せぬエラーが発生しました。システム管理者まで問合せ下さい。");
            console.log(JSON.parse(xhr.responseText));
          }
        };
        xhr.send(formData);
        console.log(xhr.status);
        xhr.onload = function() {
          if (xhr.status === 200) {
            var key = JSON.parse(xhr.responseText).fileKey;
            console.log("ファイルキー");
            console.log(key);
            var json = {
              app: kintone.app.getId(),
              id: kintone.app.record.getId(),
              record: {
                添付ファイル: {
                  value: [{fileKey: key}]
                },
                実行日時: {
                  value: current_time
                },
              }
            };
            kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', json);
          }
        };
        setTimeout("location.reload()",1000);
```

![スクリーンショット 2021-10-04 5.51.58.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526064/888d51ed-3e3d-05d2-7ab2-3e2399cc82a1.jpeg)

添付ファイルフィールドに保存することが出来ました。

![スクリーンショット 2021-10-04 5.53.06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526064/ac390419-e1db-096d-7e35-f7096f9f4c64.jpeg)

中身も良い感じです。

# まとめ
今回は出来るだけシンプルな機能としましたが、作り込むことで機能性の向上や、データの細かい整形など色々カスタマイズすることが可能です。

# 参考
<a href="https://developer.cybozu.io/hc/ja/community/posts/360043150672-CSV%E5%87%BA%E5%8A%9B%E3%82%92%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA">cybozu developer network：CSV出力をカスタマイズ</a>