Deep Insider の Tutor コーナー
>>  Deep Insider は本サイトからスピンオフした姉妹サイトです。よろしく! 
GrapeCity GARAGE: SpreadJS機能概説(3)[PR]

GrapeCity Garage GrapeCity GARAGE: SpreadJS機能概説(3)[PR]

ExcelライクなスプレッドシートUIを持つWebアプリの開発に挑戦してみた(SpreadJS活用)[PR]

2017年2月22日

JSONデータを活用した表とグラフの作成や、Excel互換関数による計算、印刷・CSVファイル出力といった機能を持つシングルページWebアプリの開発を体験してみよう。

デジタルアドバンテージ 一色 政彦
  • このエントリーをはてなブックマークに追加

 前々回はSpreadJSの概要・特徴・強みを紹介し、前回は機能一覧として、実際のスクリーンキャプチャ画像と、それを実現するためのサンプルコードを示した。特に機能一覧は、SpreadJS開発を始めるうえで必要最小限の知識を、できるだけコンパクトかつ使いやすい形でまとめるように心掛けた。使いこなせば、SpreadJS開発をスムーズに始められるはずだ。ぜひ活用してほしい。

 さて今回は、筆者自身も初めてのSpreadJSサンプルアプリ開発にチャレンジしてみる。一番時間がかかったのはデータ処理や計算処理で、SpreadJSを扱う部分は機能一覧からコードをコピーして書き換えつつ進めたのでそれほど苦労はしなかった。本稿では、そのサンプルアプリ開発の内容とポイントを紹介する。

 まずはトライアル版(期限は30日)をダウンロードして、本稿を読んで手を動かしながら、SpreadJS開発を試し、その本質を体感していただきたい。ライセンスなど、製品についてはグレープシティ公式のSpreadJS製品ページを参照してほしい。

 それではさっそく、初めてのSpreadJSサンプルアプリ開発を始めよう。

作成するSpreadJSサンプルアプリ

 個人的なことで恐縮だが筆者は最近、人間ドックを受ける日までにできるだけ痩せておこうと、ダイエットを始めた(動機が不純である……)。ダイエットをしている間は表データやグラフを毎日見るわけだが、体重計に付属のアプリ(図1)では「自分が見たい情報のみ」という表示はできない。そこで、自作のExcelファイルで独自の体重管理UI(ユーザーインターフェイス)を実現したりしている。

図1 体重の表データやグラフが表示される体重計に付属のスマートフォンアプリの例

 「このようなUIをWebで実現したり、さらに独自の機能を追加したりしていきたい」となると、かなり大変だ。こういった場面ではSpreadJSが役立つのではないかと思い付いた。そこで今回は、体重計の表データや簡易グラフを表示するサンプルアプリを作ることにした。

 体重計や体組成計(=体脂肪率や筋肉量も計れる体重計)で測定したデータをどこかしらに蓄積している人も少なくないと思う。ぜひ自分のデータを活用してSpreadJS開発を試してほしいところだが、今回は本稿のサンプル開発を手軽に体験できるように、本稿と同じ内容のJSONファイル「weight.json」を用意した*1。これを事前に「http://localhost」(=サンプルを実行するサーバーのURL)上にホストしてほしい

  • *1 このJSONファイルの取得には、「タニタ」が運営するWebサービス「Health Planet(ヘルスプラネット)」のAPIを使っている。同じようにAPIを使って独自のJSONファイルを取得して自身のリアルデータでサンプルを試したい場合には、こちらのサンプルコード「SpreadJsSamplewithHealthPlanet」全体を参考に実装してみてほしい。Health Planet上に既存のデータがなく、体組成データを外部からインポートしたい場合には、筆者自作のデータインポートツール「DataUploderToHealthPlanet」も参考にしてほしい。いずれも本稿の趣旨から外れる内容なので説明を割愛する。

 では、さっそくSpreadJSを利用してアプリ開発をしてみよう。

SpreadJSアプリの開発

 まずはどのような外観・機能のSpreadJSアプリを作成するかについて説明する。

作成するSpreadJSサンプルアプリとソースコード

図2 作成するSpreadJSサンプルアプリ

 図2に示したのが今回作成するSpreadJSサンプルアプリである。ページの左半分に、体組成測定情報(90日分*2)が表示され、右側に簡易グラフが表示されている。グラフの上が「体重の推移」、下が「体脂肪率の推移」となっている。特に体脂肪率には誤差が含まれやすいので3日移動平均線を、SpreadJSの関数を用いて実現している。BMI(=体格を評価する国際基準)はコメントとして表示できるようにしている。ページ上部にはボタンがあり、[印刷]や[CSV形式ファイルのダウンロード]ができる。

  • *2 Health Planet APIで取得できるデータ件数の上限。

 以上、今回のサンプルで用いたSpreadJSの機能は以下のとおりとなる。

 今回のサンプルアプリであれば、上記のリンク先を読めばほとんど作れてしまうだろう……。SpreadJSを使用したアプリの開発は本当に簡単だ。以下では、コードの全文を示しながら、押さえておきたいポイントのみを解説していく。

 ソースコード全体は、

でダウンロードできる。

スプレッドシートを表示するHTMLファイル

 まずはSpreadJSのHTMLファイルの内容をリスト1に掲載する。理解のヒントとなるコメントをコード内に多く記載しており、HTMLファイルの内容に関しては前回とかぶるので説明は割愛する。

HTML
<!DOCTYPE html>
<html>
  <head>
    <meta name="spreadjs culture" content="ja-jp">
    
    <!-- スプレッドシートに「Excel 2016 カラフル」テーマを指定 -->
    <link  href="http://localhost/spreadjs/9201610/css/gc.spread.sheets.excel2016colorful.9.20161.0.css" rel="stylesheet">
        
    <!-- スプレッドシートの表示領域のサイズを指定 -->
    <style>
      html { height:100%; }
      body { height:98%; }
      #ss { height:100%; width:1180px; }
    </style>
    
    <!-- SpreadJSの全機能ライブラリをロード -->
    <script src="http://localhost/spreadjs/9201610/scripts/gc.spread.sheets.all.9.20161.0.min.js"></script>
    
    <!-- SpreadJSの日本語リソースをロード -->
    <script src="http://localhost/spreadjs/9201610/scripts/resources/ja/gc.spread.sheets.resources.ja.9.20161.0.min.js"></script>
    
    <!-- 印刷モジュールのインポート -->
    <script src="http://localhost/spreadjs/9201610/scripts/pluggable/gc.spread.sheets.print.9.20161.0.min.js"></script>
    
    <!-- SpreadJSを操作する処理(外部ファイル化した) -->
    <script src="http://localhost/spreadjsapp.js"></script>
    
  </head>
  <body>
    
    <!-- 印刷/CSVファイルダウンロード用のボタン -->
      <input type="button" id="buttonPrint" value="印刷">
      <input type="button" id="buttonCsvFile" value="CSV形式ファイルのダウンロード">
    
    <!-- スプレッドシートが表示される場所 -->
    <div id="ss"></div>
  </body>
</html>
リスト1 スプレッドシートを表示するHTMLファイル(index.html)

 今回はSpreadJSを操作する処理を、spreadjsapp.jsという名前で外部ファイル化した。

SpreadJSを操作するJavaScriptファイル

 spreadjsapp.jsファイルには全ての機能が実装されているので、さすがにコードは長くなっている。まとめて読める長さではないので、以下では開発を進めた順に、小さなまとまりごとに分けて説明していく。

JSONデータを取得する部分のコード(spreadjsapp.js)
JavaScript
window.onload = function() {
  
  // JSONデータ "weight.json" を同一ドメインのサーバーから取得する
  fetch("http://localhost/weight.json").then(function(response) {
    return response.json();
  }).then(function(json) {
    
    var jsonData = json.data;               // 計測データ
    var birth_date = json.birth_date;       // 誕生日
    var height = Number(json.height) / 100; // 身長(m単位に変換)
    var sex = json.sex;                     // 性別
    
    ……省略1……
  });
  
};
リスト2 JSONデータを取得する部分のコード(spreadjsapp.js)

 まず上記のリスト2では、ページがロードされたタイミングで、JSONファイルであるhttp://localhost/weight.jsonにアクセスしてJSONデータを取得し、JSONデータの中身を各変数に代入している。変数jsonDataには、オブジェクト配列(Arrayオブジェクト)で体組成計測データが格納されている。

各種初期化を行うコード(リスト2の省略1の部分)

 次に下記のリスト3では、SpreadJSのスプレッドシートを作成するときに定型的な初期化処理と、以降のコーディングで用いる各種変数の宣言を行っている。スプレッドシート全体に関わる「タブストリップの非表示」や「ユーザーによる編集を不可にする設定」は、スプレッドシートの初期化オプションとして指定している。

JavaScript
// スプレッドシートを生成するための初期化処理
var spread = new GC.Spread.Sheets.Workbook(
  document.getElementById("ss"), { 
    tabStripVisible: false,         // タブストリップを非表示
    showHorizontalScrollbar: false, // 水平スクロールバーを非表示
    canUserEditFormula: false,      // 編集不可
    hideSelection: true,            // 選択状態を隠す(ユーザー選択は可能)
    grayAreaBackColor: "white"      // 無効領域の色指定
  }); 
var sheet = spread.getActiveSheet();

// インデックス番号の定義
var colMLid = 0; // 1列目:左余白(Margin-Left)
var colTDid = 1; // 2列目:テーブル-測定日(Table-Date)
var colTWid = 2; // 3列目:テーブル-体重(Table-Weight)
var colTFid = 3; // 4列目:テーブル-体脂肪率(Table-Fat)
var colTMid = 4; // 5列目:テーブル-筋肉量(Table-Muscle)
var colMCid = 5; // 6列目:中央余白(Margin-Center)
var colSLid = 6; // 7列目:スパークライン(Spark-Line)
var colMRid = 7; // 8列目:右余白(Margin-Right)
var colGWid = 8; // 9列目:グラフ用体重(Graph-Weight)=体重の逆順
var colGMid = 9; // 10列目:グラフ用3日移動平均(Graph-MovingAverage) =体脂肪率(3日移動平均)の逆順
var rowGTid = 0; // 1行目:通常タイトル(General-Title)
var rowTHid = 1; // 2行目:テーブルヘッダー(Table-Header)
var rowTDid = 2; // 3行目~:テーブルデータ(Table-Data)

// スパークライン関連の定義
var rowS1id =  1;    //  2行目:スパークライン1つ目(Sparkline-1)
var rowS2id = 22;    // 23行目:スパークライン2つ目(Sparkline-2)
var slRowCount = 20; // 20行:スパークラインの行数
var slColCount =  1; // 1行:スパークラインの列数

// アプリで使うフォント関連の定義
var appFont = "bold 12pt Meiryo"; // アプリ用フォント
var appColor = "#70AD47";         // アプリ用文字色
var invisible = "white";          // 見えないようにする文字色

// フォーマッターに指定する書式の定義
var fmtDate = 'yyyy年MM月dd日(ddd)'; // 日付
var fmtKgP2 = '#.00 "kg"';           // キログラム(小数点2桁)
var fmtPtP1 = '#.0 "%"';             // パーセント(小数点1桁)

sheet.suspendPaint();  // 描画をいったん停止。まとめて描画で高速に

……省略2描画処理)……

sheet.resumePaint();  // 描画を再開。まとめて描画で高速に

……省略3印刷とファイル出力)……
リスト3 各種初期化を行うコード(リスト2の省略1の部分)

 リスト3のsheet.suspendPaint();sheet.resumePaint();というコードの存在は、パフォーマンスを考えると重要である。いったん描画を停止して再開時に描画をまとめて行うためのものだが、この2行のコードを削除してしまうと、とたんにページの描画が極端に遅くなってしまうからだ。

タイトル設定や行・列のサイズを調整するコード(リスト3の省略2の部分)

 リスト4は、表データやスパークラインの上のセルにタイトルを設定したり、行の高さや列の幅を調整したりしている。

JavaScript
sheet.getCell(rowGTid, colTDid).
  text("体組成測定情報(過去90日)").
  font(appFont).
  foreColor(appColor);

sheet.getCell(rowGTid, colSLid).
  text("変化の推移を示すグラフ(上:体重、下:体脂肪率)").
  font(appFont).
  foreColor(appColor);

// 行の高さと列の幅を設定
sheet.setRowHeight(rowGTid, 25);
sheet.setColumnWidth(colMLid, 20);
sheet.setColumnWidth(colTDid, 150);
sheet.setColumnWidth(colTWid, 80);
sheet.setColumnWidth(colTFid, 70);
sheet.setColumnWidth(colTMid, 80);
sheet.setColumnWidth(colMCid, 20);
sheet.setColumnWidth(colSLid, 600);
sheet.setColumnWidth(colMRid, 20);
sheet.setColumnWidth(colGWid, 60);
sheet.setColumnWidth(colGMid, 50);

……省略4(続く)……
リスト4 タイトル設定や行・列のサイズを調整するコード(リスト3の省略2の部分)
データ加工を行うコード(リスト4の省略4の部分)

 続いてリスト5は、変数jsonDataに代入した体組成計測データを解析しながら、テーブルのデータソースとして使える形に加工しているコードである。元の体組成計測データは少し特殊な構造になっているので、このような処理が必要になる。SpreadJS開発とは無関係なコードなので説明は割愛する(分かりにくい部分には、コードにコメントを入れているので参考にされたい)。

JavaScript
// ▼▼▼ ここからデータ加工処理 ▼▼▼

// 年月日順に今日を含めて過去90日間の初期データを作成
var dateMap = new Map();
var thisDate = new Date();
thisDate.setHours(0, 0, 0, 0);
for (var i = 0; i < 90; i++) {
  // 年月日のキーと文字列を作成する
  var yyyy = String(thisDate.getFullYear());
  var mm = String(thisDate.getMonth() + 1); // 0スタートなので注意
  if (Number(mm) < 10) { mm = "0" + mm }
  var dd = String(thisDate.getDate());
  if (Number(dd) < 10) { dd = "0" + dd }
  var dateKey = yyyy + mm + dd;
   // 日付番号を基準に、JSONデータから各項目値を設定できるようにMapを使う
  dateMap.set(dateKey, { 
    "測定日": thisDate,
    "体重": null,
    "体脂肪率": null,
    "筋肉量": null });
  // 日にちを1日進める
  var thisDateTime = thisDate.getTime();
  var prevDateTime = thisDateTime - 86400000; // = 60 * 60 * 24 * 1000
  thisDate = new Date(prevDateTime);
}

// JSONデータから、日付番号を基準に各項目値を設定する
jsonData.forEach(function(jsonValue) {
  var dateKey = jsonValue.date.substring(0, 8); // 年月日のみ抽出
  if (dateMap.has(dateKey) == false) return;
  var mapValue = dateMap.get(dateKey);
  switch (jsonValue.tag) {
    case "6021":
      mapValue.体重 = Number(jsonValue.keydata);
      break;
    case "6022":
      mapValue.体脂肪率 = Number(jsonValue.keydata);
      break;
    case "6023":
      mapValue.筋肉量 = Number(jsonValue.keydata);
      break;
    default:
      return;
  }
  dateMap.set(dateKey, mapValue);
});

// 作成できた計測データの一覧をArrayオブジェクト化してデータソースとして使う
var dataSource = Array.from(dateMap.values());

// ▲▲▲ ここまでデータ加工処理 ▲▲▲

……省略5(続く)……
リスト5 データ加工を行うコード(リスト4の省略4の部分)

 なお、加工後のデータは、変数dataSourceに代入されている。

データ確定後の初期化やワークシートのオプション設定を行うコード(リスト5の省略5の部分)

 データが確定して数も判明したので、その数値に基づき、リスト6では、行数と列数を設定したり、ワークシートに対する各種オプションをまとめて指定したりしている。

JavaScript
// 行数と列数を確定する
var dataLen = dataSource.length;
var rowCount = dataLen + 3; // =上余白+見だし+下余白の3行
sheet.setRowCount(rowCount);
sheet.setColumnCount(10); // =左余白+4列のテーブル+中央余白+グラフ+右余白+2列のグラフ表示用データ

// 行と列のヘッダーやグリッド線を非表示に
sheet.options.rowHeaderVisible = false;
sheet.options.colHeaderVisible = false;
sheet.options.gridline = { showVerticalGridline: false, showHorizontalGridline: false};
sheet.options.tabStripVisible = false;

// シート全体をロックして保護する
sheet.options.isProtected = true;
// 隣接セルへのオーバーフロー表示
sheet.options.allowCellOverflow = true;

……省略6(続く)……
リスト6 データ確定後の初期化やワークシートのオプション設定を行うコード(リスト5の省略5の部分)
データソースからテーブルの作成と書式の設定を行うコード(リスト6の省略6の部分)

 データソースからテーブルを作成するのは、addFromDataSourceメソッドを呼び出すだけでよく簡単だ。リスト7では、テーマを選択したり、フィルターボタンを非表示にしたり、各列の書式を設定したりしている。

JavaScript
// テーブルテーマを選択(一部のスタイルをカスタマイズした)
var tableTheme = GC.Spread.Sheets.Tables.TableThemes.medium7;
var lineStyle = GC.Spread.Sheets.LineStyle.dotted;
var lineBorder = new GC.Spread.Sheets.LineBorder(appColor, lineStyle);
tableTheme._ps.wholeTableStyle.borderVertical = lineBorder;

// データソースからテーブルを自動作成
var tableName = "過去90日の体組成測定情報";
var table = sheet.tables.addFromDataSource(tableName, rowTHid, colTDid, dataSource, tableTheme);
table.filterButtonVisible(0, false).  // テーブル内の1列目(測定日)
      filterButtonVisible(1, false).  // テーブル内の2列目(体重)
      filterButtonVisible(2, false).  // テーブル内の3列目(体脂肪率)
      filterButtonVisible(3, false);  // テーブル内の4列目(筋肉量)
    
    // テーブル内の書式をセット(1列ずつ)
    sheet.getRange(rowTDid, colTDid + 0, dataLen, 1).formatter(fmtDate);
    sheet.getRange(rowTDid, colTDid + 1, dataLen, 1).formatter(fmtKgP2);
    sheet.getRange(rowTDid, colTDid + 2, dataLen, 1).formatter(fmtPtP1);
    sheet.getRange(rowTDid, colTDid + 3, dataLen, 1).formatter(fmtKgP2);
    // テーブル以外(グラフ表示用の2列)の書式もついでにセット(1列ずつ)
    sheet.getRange(rowTDid, colGWid, dataLen, 1).formatter(fmtKgP2).foreColor(invisible);
    sheet.getRange(rowTDid, colGMid, dataLen, 1).formatter(fmtPtP1).foreColor(invisible);
    var tableLen = dataLen + 1; // テーブル全体の行数。ヘッダー分の「1」を足す
    sheet.getRange(rowTHid, colTDid, tableLen, 4).  // 4列全てに対してセンタリング
      hAlign(GC.Spread.Sheets.HorizontalAlign.center);

……省略7(続く)……
リスト7 データソースからテーブルの作成と書式の設定を行うコード(リスト6の省略6の部分)
日付/数値の書式指定文字列について

 リスト7で使われているformatterメソッドは、日付や数値の書式設定を行うためのものだ。前回は説明を省略したので、ここで詳しく説明しておこう。

 リスト7でformatterメソッドに指定されている書式化文字列とその結果は、以下のとおり。

  • formatter('yyyy年MM月dd日(ddd)'): 日付データ(DateTimeオブジェクト)が「2017年02月01日(水)」のように文字列化される
  • formatter('#.00 "kg"): 数値データ(Numberオブジェクト)が「65.37 kg」のように小数点2桁までで文字列化される
  • formatter('#.0 "%"'): 数値データ(Numberオブジェクト)が「15.6 kg」のように小数点1桁までで文字列化される

 この例を見ると、日時書式指定文字列で4桁の年を表すyyyyであったり、数値書式指定文字列における桁プレースホルダーの#やゼロプレースホルダーの0などが使われたりしている。日付/数値の書式指定文字列には、

とほぼ同じものが使える。日時書式指定子では、表1に示すものが使える。

書式指定子 意味と例
ggg 年号の名前。例:「平成」。当然、カルチャは「ja-jp」を選択する
gg 年号の略称。例:「平」
g 年号の記号。例:「H」
ee 2桁の年号の年。例:「29」
e 2桁の年号の年。例:「29」
yyyy 4桁の年。例:「2017」
yyy 4桁の年。例:「2017」
yy 2桁の年。例:「17」
y 2桁の年。例:「17」
MMMM 月の名前。例:「1月」/「January」
MMM 月の略称。例:「1」/「Jan」
MM 2桁の月。例:「01」
M 1桁の月。例:「1」
dd 2桁の日。例:「01」
d 1桁の日。例:「1」
dddd 曜日の名前。例:「日曜日」
ddd 曜日の略称。例:「日」
hh 12時間制で2桁のとき。例:「01」
h 12時間制で1桁のとき。例:「1」
HH 24時間制で2桁のとき。例:「01」
H 12時間制で1桁のとき。例:「1」
tt 12時間制の午前・午後。例:「午前」
mm 2桁の分。例:「01」
m 1桁の分。例:「1」
ss 2桁の秒。例:「01」
s 1桁の秒。例:「1」
f 秒の小数部が1桁。例:「0.1」
ff 秒の小数部が2桁。例:「0.01」
fff 秒の小数部が3桁。例:「0.001」
zzz 標準時との時差。例:「+09:00」
zz 標準時との時差を2桁で。「+09」
z 標準時との時差を1桁で。「+9」
表1 SpreadJSで使える主な日時書式指定子

 脱線したが話を開発に戻そう。

各セルへの関数の設定とスパークライン用データの作成を行うコード(リスト7の省略7の部分)

 スパークライン(=セル内に表示される小さな簡易グラフ)を表示するために、リスト8のコードでは、既存の列データを逆順に並べ替えている(コードが長く煩雑だが、SpreadJSの機能ではないので説明を割愛)。さらに、setFormulaメソッドによりセルに関数を設定していくことで、3日移動平均線用のデータも作成している。

JavaScript
var tblRowIndex = dataLen - 1;           // 現在(=最終行)のテーブルデータ内インデックス
var revRowIndex = tblRowIndex + rowTDid; // 現在の全セルデータ内インデックス(逆順用)
var prevFat = null;
var thisFat = sheet.getValue(revRowIndex, colTFid); // 末尾行取得。インデックスは0番スタートなので+2ではなく「+1」にする

var fwdRowIndex = rowTDid; // 3行目~:テーブルデータ(Table-Data)インデックス(昇順用)
for (; revRowIndex >= rowTDid; revRowIndex--) { // 下から走査していく
  
  var prevRowIndex = revRowIndex - 1; // 1つ上のデータ
  var nextFat = sheet.getValue(prevRowIndex, colTFid);
  if (!thisFat || thisFat == 0) { 
    prevFat = thisFat;
    thisFat = nextFat;
    continue;
  }
  
  // グラフ用体重データ
  sheet.setFormula(fwdRowIndex, colGWid, "C" + (revRowIndex + 1));
  // インデックスが「0」スタートなのに対し、C1形式のセル参照は「1」スタートなので「1」を足す必要がある。
  
  // グラフ用3日移動平均データ
  var dividedBy = 3 - ((!Number(prevFat) || prevFat == 0) ? 1 : 0) - ((!Number(nextFat) || nextFat == 0) ? 1 : 0);
  sheet.setFormula(fwdRowIndex, colGMid, "=SUM(D" + (revRowIndex) + ":D" + (revRowIndex + 2) + ")/" + dividedBy);
  // 「0」「1」スタートの違いから、1つ上のセル参照は何も足さず、1つ下のセル参照は「2」を足す必要がある。
  
  prevFat = thisFat;
  thisFat = nextFat;
  
  ……省略8(続く)……
  
  fwdRowIndex++;
}

……省略9(続く)……
リスト8 各セルへの関数の設定とスパークライン用データの作成を行うコード(リスト7の省略7の部分)
コメントを設定するコード(リスト8の省略8の部分)

 ワークシートのcomments.addメソッドで指定セルに、BMI情報をコメントとして設定している。

JavaScript
// BMIをコメントで設定
var thisWeight = sheet.getValue(revRowIndex, colTWid);
var bmi = thisWeight / ( height * height );
sheet.comments.add(revRowIndex, colTWid, "BMI: " + bmi.toFixed(2));
リスト9 コメントを設定するコード(リスト8の省略8の部分)
スパークラインを作成するコード(リスト8の省略9の部分)

 ワークシートのsetSparklineメソッドで指定セルに、スパークラインを作成している。

JavaScript
var setting = new GC.Spread.Sheets.Sparklines.SparklineSetting();
setting.options.showMarkers = true;
setting.options.lineWeight = 3;

// スパークライン(体重)
var graphDataW  = new GC.Spread.Sheets.Range(2, 8, dataLen, 1);
sheet.addSpan(rowS1id, colSLid, slRowCount, slColCount);
var sparkline = sheet.setSparkline(rowS1id, colSLid, graphDataW, GC.Spread.Sheets.Sparklines.DataOrientation.vertical, GC.Spread.Sheets.Sparklines.SparklineType.line, setting);

// スパークライン(体脂肪率)
var graphDataF  = new GC.Spread.Sheets.Range(2, 9, dataLen, 1);
sheet.addSpan(rowS2id, colSLid, slRowCount, slColCount);
var sparkline = sheet.setSparkline(rowS2id, colSLid, graphDataF, GC.Spread.Sheets.Sparklines.DataOrientation.vertical, GC.Spread.Sheets.Sparklines.SparklineType.line, setting);
リスト10 スパークラインを作成するコード(リスト8の省略9の部分)

 この後、いったん停止していた描画処理を再開してページが表示される。ここまで、コードは少し長くなっているが、難しいところはなかっただろう。

 最後に、ボタンクリック時に行われる処理(印刷とCSVファイルの保存)を見ていこう

印刷を実行するコード(リスト3の省略3の部分)

 ワークシートのprintメソッドを呼び出すだけである。

JavaScript
// データの印刷
document.getElementById("buttonPrint").onclick = function() {
  spread.print(0);
};

……省略10(続く)……
リスト10 印刷を実行するコード(リスト3の省略3の部分)
CSVファイルを保存するコード(リスト10の省略10の部分)

 ワークシートのgetCsvメソッドを呼び出すことで、CSV形式の文字列データを取得する。さらにリスト11のように、取得したCSV形式文字列データをファイルとして保存する処理を記述する(SpreadJSの機能ではないので説明を割愛)。

JavaScript
// CSV形式でのデータの保存
document.getElementById("buttonCsvFile").onclick = function() {
  var csvString = sheet.getCsv(
    1, 1, trc, 4, // データが対象
    "\n", ","); // 行区切りと列区切りの文字
  var filename = "spreadjs.csv";
  var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
  var blob = new Blob([ bom, csvString ], { "type" : "text/csv" });
  var a = document.createElement('a');
  a.download = name;
  a.target   = '_blank';
  a.style = "display: none";
  if (window.navigator.msSaveBlob) { 
    window.navigator.msSaveBlob(blob, filename);
  } else if (window.URL && window.URL.createObjectURL) {
    a.href = window.URL.createObjectURL(blob);
    a.click();
    document.body.removeChild(a);
  } else if (window.webkitURL && window.webkitURL.createObject) {
    a.href = window.webkitURL.createObjectURL(blob);
    a.download = filename;
    a.click();
  } else {
    window.open("data:text/csv;base64," + window.Base64.encode(csvString), "_blank");
  }
  alert(filename + "ファイルをダウンロードしました。");
};
リスト11 CSVファイルを保存するコード(リスト10の省略10の部分)

 以上でサンプルアプリは完成だ。http://localhost/index.htmlというURLにアクセスすれば、図2のアプリが起動する。

まとめ

 以上、できるだけ多くの人にとって身近な例でSpreadJSのサンプルアプリを開発してみた。感想はいかがだろうか。確かにコードはそれなりの行数になるものの、実装したいことが素直にコーディングできるので、一度作って慣れてしまえば、SpreadJS開発は難しくないと感じられるのではないだろうか。

 本連載では、「SpreadJSの概要」から、「主要機能とコードの一覧」、「アプリ開発の実践」という全3回のステップで、SpreadJSを深く知り、実際に開発を始めるために必要十分な内容を説明できた(と筆者は考えている)。筆者自身、第2回で示した「主要機能とコードの一覧」でほとんどの機能を試せたことで、「なるほど、これで何でも開発できそうだ」という自信を持てた。一通りの機能とコードを試せば、よりSpreadJSの機能性や開発のイメージが湧きやすくなるので、まずは第2回の記事SpreadJS公式のチュートリアルデモを全て試してみるのがお勧めだ。その次はぜひ、独自のSpreadJSアプリの開発に進んでみてほしい。

GrapeCity GARAGE: SpreadJS機能概説(3)[PR]
1. Excelライクなグリッド表示(スプレッドシート、表計算)を簡単に作れるJavaScriptライブラリ「SpreadJS」の機能概要[PR]

Web上でもExcel形式の表計算型のデータ入力やデータ表示を実現したい?! それならJavaScript UIウィジットの「SpreadJS」が利用できる。そのSpreadJSの特徴と機能概要をまとめる。

GrapeCity GARAGE: SpreadJS機能概説(3)[PR]
2. SpreadJSで何が開発できるのか? 主要機能とコードをまとめて知ろう[PR]

Web向けスプレッドシートUIが簡単に作れるSpreadJS。具体的には何が実現できるのか? スクリーンキャプチャ画像とシンプルなコードで、主要機能と開発のイメージを手っ取り早くつかもう。

GrapeCity GARAGE: SpreadJS機能概説(3)[PR]
3. 【現在、表示中】≫ ExcelライクなスプレッドシートUIを持つWebアプリの開発に挑戦してみた(SpreadJS活用)[PR]

JSONデータを活用した表とグラフの作成や、Excel互換関数による計算、印刷・CSVファイル出力といった機能を持つシングルページWebアプリの開発を体験してみよう。

GrapeCity GARAGE: SpreadJS機能概説(3)[PR]
4. SpreadJSで使える関数の一覧(カテゴリ・機能別)[Excel関数互換][PR]

SpreadJSで使える関数をカテゴリ・機能別で紹介。Excelユーザーに優しいExcel互換の関数になっているので、対応しているExcel関数ページのリンク付き。

GrapeCity GARAGE: SpreadJS機能概説(3)[PR]
5. SpreadJSで使える関数の一覧(アルファベット順)[Excel関数互換][PR]

SpreadJSで使える関数をアルファベット順で紹介。Excelユーザーに優しいExcel互換の関数になっているので、対応しているExcel関数ページのリンク付き。

サイトからのお知らせ

Twitterでつぶやこう!