集計したデータを CSV でダウンロードするには?

著者名: KADOYA Ryo (External link) (サイボウズ)

目次

はじめに

kintoneにはデータをCSV形式でダウンロードする機能があります。
通常の場合これで十分なのですが、場合によってはアプリをまたがるデータを集計したり、kintone.proxy()を使って他のサービスから取得したデータをダウンロードしたいことがあります。

ここは、kintoneカスタマイズを使って、CSVファイルをダウンロードするテクニックを紹介します。
このサンプルでは単純に、column1、column2というフィールドをもったレコードをCSVに出力していますが、このテクニックを応用することで、kintoneで扱えるどんなデータでもファイルに出力できます。

サンプルプログラム

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
 * Download aggregated data as csv sample program
 * Copyright (c) 2014 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */

(function() {
  'use strict';

  // 一覧ビューの表示イベント
  kintone.events.on('app.record.index.show', (events) => {

    let $link = $('#download-csv');
    if ($link.length === 0) {
      // ヘッダにリンクを作成
      const $header = $(kintone.app.getHeaderMenuSpaceElement());
      $link = $('<a id="download-csv" href="#">CSVでダウンロード</a>');
      $header.append($link);
    }

    // エスケープ
    const escapeStr = function(value) {
      return '"' + (value ? value.replace(/"/g, '""') : '') + '"';
    };

    if ((window.URL || window.webkitURL).createObjectURL == null) {
      // サポートされていないブラウザ
      return;
    }

    // CSVデータを作成
    const csv = [];
    let row = ['ID', 'column1', 'column2'];
    csv.push(row);
    for (let i = 0; i < events.records.length; i++) {
      const record = events.records[i];
      row = [];
      row.push(escapeStr(record['レコード番号'].value));
      row.push(escapeStr(record.column1.value));
      row.push(escapeStr(record.column2.value));
      csv.push(row);
    }

    // BOM付でダウンロード
    const csvbuf = csv.map((e) =>{
      return e.join(',');
    }).join('\r\n');

    const bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
    const blob = new Blob([bom, csvbuf], {type: 'text/csv'});

    const url = (window.URL || window.webkitURL).createObjectURL(blob);

    const fileName = 'download.csv';
    if (window.navigator.msSaveOrOpenBlob) {
      // for IE
      $link.unbind();
      $link.click(() => {
        const retVal = window.navigator.msSaveOrOpenBlob(blob, fileName);
      });
    } else {
      $link.attr('download', fileName);
      $link.attr('href', url);
    }
  });
})();

適用手順

このサンプルはjQueryを読み込む必要があるので、jQueryライブラリとサンプルプログラムを順番に指定します。

  • まずは、 Cybozu CDNからjQueryライブラリを指定します。
    アプリの設定画面から「JavaScript / CSSによるカスタマイズ」を開き、「PC用のJavaScriptファイル」にURL指定で次のURLを指定します。
    https://js.cybozu.com/jquery/3.7.1/jquery.min.js
  • 指定したライブラリの下に、今回の「サンプルプログラム」のファイルを追加します。
    サンプルプログラム部分のコードをエディターにコピーして、ファイル名を「sample.js」、文字コードを「UTF-8」、BOMなしで保存します。
    ファイル名は任意ですが、ファイルの拡張子は「js」にしてください。

解説

Url 生成メソッド

このサンプルでは、window.URL.createObjectUrlメソッドを利用してBlobオブジェクトのダウンロードURLを生成しています。
window.URL.createObjectUrlの説明やサポートブラウザーについては MDN のドキュメント (External link) を参照してください。

文字エンコーディング

kintoneではUTF-8の文字エンコーディングが使用されています。
UTF-8で出力したCSVファイルをそのままではExcelで開けないので、ファイルの先頭にBOM(Byte Order Mark)を付けることで、Excelで開けるようにしています。

もしどうしてもShift-JISで出力したい場合は、外部ライブラリを利用することでエンコーディングを変換できます。
ここではぽりごん氏作の encoding.js (External link) (MIT or GPL v2 licenses)を利用した例を紹介します。

encoding.js

encoding.jsはぽりごん氏によりオープンソースで提供されているライブラリです。
自己責任で利用してください。

47行目から54行目を以下のように編集してください。

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 文字列を配列に
const str2array = function(str) {
  const array = [];
  let i;
  const il = str.length;
  for (i = 0; i < il; i++) array.push(str.charCodeAt(i));
  return array;
};

// SJISの配列に変換
const csvbuf = csv.map((e) =>{
  return e.join(',');
}).join('\r\n');

const array = str2array(csvbuf);
const sjis_array = Encoding.convert(array, 'SJIS', 'UNICODE');
const uint8_array = new Uint8Array(sjis_array);
const blob = new Blob([uint8_array], {type: 'text/csv'});

const url = (window.URL || window.webkitURL).createObjectURL(blob);

おわりに

上記のテクニックを使うことで、お手軽にファイルのダウンロードをカスタマイズで実現できます。
ぜひお試しください。

information

このTipsは、2014年4月版kintoneで動作を確認しています。