11
0

More than 1 year has passed since last update.

はじめに

kintoneのアプリ同士のデータを連結してCSV出力する方法について紹介します!

関連レコードを用いてCSV出力する方法はcybozu developer networkにて紹介されています。こちらのコードを基に自分でカスタマイズを行いました。
関連レコードのデータをCSV出力する方法

今回は関連レコードを用いず、別アプリのテーブルにて複数登録されているデータとの連結方法について紹介を行っていきます。

アプリの構成

サンプル1アプリ

image.png
サンプルアプリ1の申請NOを基にサンプル2アプリとデータの紐づけを行います。

サンプル2アプリ

image.png
サンプル1アプリの申請NOをテーブルにて複数登録できるようにしています。
テーブルのデータを取得しやすいようにカンマ区切りで管理用の項目に値を保持します。

カンマ区切りの保存方法はこちらです:information_desk_person_tone1:

  kintone.events.on([
    'app.record.create.submit',
    'app.record.edit.submit'
  ], function (event) {
    let record = event.record;
    // サンプル1の申請NOをカンマ区切りでつなげて保存するように設定する
    const tableLength = record.テーブル.value.length;
    let sample1ApplyNo = '';
    for (let i = 0; i < tableLength; i++) {
      // カンマで連結
      if (i > 0) {
        sample1ApplyNo += ',';
      }
      sample1ApplyNo
        += record.テーブル.value[i].value.サンプル1の申請NO.value;
    }
    record.サンプル1の申請NO_管理用.value = sample1ApplyNo;
    return event;
  });

画面イメージ(サンプル1アプリ)

image.png
一覧画面にCSV出力ボタンを表示させます。色は左のプルダウンの部分と統一させました。

image.png
ボタンの上にカーソルを乗せた際には色を変化させます。

上記のボタンのCSSはこちらです:information_desk_person_tone1:

#btn-export-csv {
    background: #3498db;
    color: #ffff;
    padding: 2px 10px;
    width: 140px;
    border-radius: 3px;
    border: 4px solid #3498db;
    height: 40px;
    border-bottom: 1px solid rgba(0,0,0, .25);
    box-shadow: 0 1px 3px rgb(0 0 0 / 50%);
}

#btn-export-csv:hover {
    background: #1d6fa5;
    border: 4px solid #1d6fa5;
}

連結するコード

こちらコードはサンプル1アプリに登録します。

(function () {
  'use strict';
  // 紐づけるサンプル2アプリのアプリID
  const appId = 1;

  /*
  * 一覧画面表示イベント
  */
  kintone.events.on('app.record.index.show', function (event) {
      const records = event.records;
      // ボタンの有無をチェック
      if (document.getElementById('btn-export-csv')) {
          return;
      }

      // ボタンを作成
      const spaceEl = kintone.app.getHeaderMenuSpaceElement();
      const cSVButtonEl = document.createElement('button');
      cSVButtonEl.textContent = 'CSV出力';
      cSVButtonEl.id = 'btn-export-csv';
      spaceEl.appendChild(cSVButtonEl);

      // ボタン押下時のイベント
      cSVButtonEl.addEventListener('click', function () {
          try {
              makeLinkedCsv(appId, records).then(function (resp) {
                  downloadFile(resp);
              });
          } catch (error) {
              alert('CSV出力でエラーが発生しました  - error: ' + e.message);
              return false;
          }
      });
  });

  /*
  * CSVデータの作成
  */
  function makeLinkedCsv(appId, sample1Records) {
      const header = [
          'サンプル1の申請NO',
          '担当者',
          '件名',
          'サンプル2の申請NO',
          '担当者',
          '紐づくサンプル1の申請NO',
          '件名'
      ].join(',');
      let csvData = [header];

      return new kintone.Promise(function (resolve, reject) {
          linkData().then(function (resp) {
              csvData = csvData.concat(resp);
              resolve(csvData);
          });
      });

      /*
      * 同じサンプル1アプリの申請NOを持つサンプル2アプリのレコードを連結
      */
      function linkData(index, data) {
          // CSVデータに追加するサンプル1の情報
          const sample1RowIndex = index || 0;
          const sample1Record = sample1Records[sample1RowIndex];
          // 生成済みのCSVデータ
          const detailRows = data || [];
          // サンプル1の申請NO
          const sample1ApplyNo = sample1Record.申請NO.value;
          // サンプル1の申請NOを基に該当関連レコードを部分一致検索で取得
          const query = 'サンプル1の申請NO_管理用 like "' + sample1ApplyNo + '"';
          const params = {
              app: appId,
              query: query
          };
          return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', params)
              .then(function (resp) {
                  let row = [];
                  // サンプル1のレコード情報
                  const sample1Cols = [
                    sample1ApplyNo,
                      sample1Record.担当者.value,
                      sample1Record.件名.value.replace(',', '')
                  ];

                  // 空のサンプル2のレコード情報
                  const sample2Cols = [
                      '',
                      '',
                      '',
                  ];

                  // 紐づくレコード情報
                  const relatedRecords = resp.records;
                  // サンプル1の申請NOに紐づくレコ―ドが存在する場合
                  let targetSample2Count = 0;
                  if (relatedRecords.length > 0) {
                      for (let i = 0; i < relatedRecords.length; i++) {
                          // サンプル2情報のサンプル1の申請NOリストを配列に変換
                          let sample1ApplyNoList =
                              relatedRecords[i].サンプル1の申請NO_管理用.value.split(',');
                          if (sample1ApplyNoList.includes(sample1ApplyNo)) {
                              // サンプル2情報のサンプル1の申請NOリストに同一の申請NOが存在した場合
                              // 出力対象となるサンプル2情報の件数をインクリメント
                              targetSample2Count += 1;
                              // サンプル1情報を追加
                              row.push(sample1Cols);
                              // サンプル2情報を追加
                              row.push([
                                  relatedRecords[i].申請NO.value,
                                  relatedRecords[i].担当者.value,
                                  sample1ApplyNo,
                                  // 半角カンマを全角に変換
                                  relatedRecords[i].件名.value.replace(',', ''),
                              ]);
                              detailRows.push(row.join(','));
                              // 一度空にする
                              row = [];
                          }
                      }

                      if (targetSample2Count === 0) {
                          // 対象のサンプル2情報が1件も存在しない場合
                          row = sample1Cols.concat(sample2Cols);
                          detailRows.push(row.join(','));
                      }
                  } else {
                      // 対象のサンプル2情報が取得できなかった場合
                      row = sample1Cols.concat(sample2Cols);
                      detailRows.push(row.join(','));
                  }
                  // 連結していないサンプル1の情報があれば処理を継続する
                  if (sample1Records.length > sample1RowIndex + 1) {
                      return linkData(sample1RowIndex + 1, detailRows);
                  }
                  return detailRows;
              });
      }
  }

  /*
  * ファイルのダウンロード処理
  */
  function downloadFile(data) {
      const csv = data.join('\r\n');
      // ファイル名
      const filename = getFileName();

      // Blob準備
      const bom = new Uint8Array([0xef, 0xbb, 0xbf]);
      const blob = new Blob([bom, csv], { type: 'text/csv' });

      if (window.navigator.msSaveBlob) {
          window.navigator.msSaveBlob(blob, filename);
      } else {
          const e = new MouseEvent('click', { view: window, bubbles: true, cancelable: true });
          const url = window.URL || window.webkitURL;
          const blobUrl = url.createObjectURL(blob);
          const a = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
          a.href = blobUrl;
          a.download = filename;
          a.dispatchEvent(e);
      }
  }

  /*
  * ファイル名の取得
  * @return yyyymmdd_連結.csv
  */
  function getFileName() {
      const d = new Date();
      const YYYY = d.getFullYear();
      // 10未満の場合は数字の前に0を付ける
      const MM = (d.getMonth() + 1).toString().padStart(2, '0');
      const DD = d.getDate().toString().padStart(2, '0');
      return YYYY + MM + DD + '_連結.csv';
  }
})();

操作方法

1、サンプル1アプリにてデータを絞り込み、CSV出力ボタンを押下します。
image.png

2、指定したファイル名でCSVファイルが出力されます。
image.png

image.png
このような感じで出力されました!!

image.png
複数件データを検索しても問題無く出力できます。ただ、一覧画面に表示しているデータのみしか取得できないため、より多く出力する場合には表示件数を変更する必要があります。

さいごに

アプリ同士でデータの連結をしようとしている方の参考になれば幸いです:point_up_tone1:

11
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
0