App Engineから読み取ったデータの書き込みと、スプレッドシートのUIで表示する処理

2013年11月28日(木)
清野 克行

3.DriveおよびDatastoreのスプレッドデータをUI表示する

3.1 ブラウザ上の操作と表示

次に、ここまで見てきたスプレッドデータのサーバ側処理結果を、ブラウザでUI表示する処理について見ていきますが、最初に画面操作と表示内容を見てみます。
画面操作の参照用サイト

図2:Spreadsheetデータの登録・参照画面(リンク)(クリックで拡大)

図2は、Spreadsheetデータ登録・参照の初期表示画面です。この画面から、ここまで見てきた

  1. スレッド登録のaddSpreadAllShopToDsYmメソッド
  2. Datastoreに書き込まれたスプレッドデータ読み取りのgetDsAllShopYmメソッド
  3. 前回紹介したDrive上のスプレッドデータ読み取りのgetSpreadAllShopYmメソッド

をサーブレット経由で呼び出して表示処理を行います。

3.2 Drive上スプレッドデータのDatastore登録

図3:スプレッドデータのDatastore登録(クリックで拡大)

図3はスプレッドデータのDatastore登録処理表示で、年月指定によってSpreadsheetデータを(前回の連載で見てきた)addSpreadAllShopToDsYmメソッドによって読み取り、次にDatastoreへの登録処理を行っています。

3.3 Drive上のスプレッドデータ参照

図4:Spreadsheetデータの登録・参照およびDatastore書き込みデータの参照画面(クリックで拡大)

図2の画面で年月指定後、「スプレッド参照」ボタンをクリックするとDrive上のスプレッドデータが図4の画面のようにグリッド形式で表示されます。Drive上スプレッドデータを簡易形式で表示するサンプルは前回の記事で紹介しており、サーバ側ビーンズの処理コードは前回のものと全く同じです。

また図4のようなスプレッド風画面表示では、ここで使用しているActicewidgetsのgridコントロールの他にも幾つかあってjQueryの追加プラグインなどもあり、その内のParamQuery gridについて最後に紹介します。

3.4 Datastoreスプレッドデータの参照

図5:Datastoreスプレッドデータの参照(クリックで拡大)

次に図5は、図3の処理でDatastoreに書き込まれたスプレッドデータを参照しています。書き込みは5月度のデータですので図3の参照データとは値が異なっているのが確認できます。

3.5 ActiveWidgetsが提供するWebコンポーネント

ActiveWidgets社(http://www.activewidgets.com/)は図4~図5のようなグリッドコンポーネントの他にも、図6のようなさまざまなWebコンポーネントを提供しており、これ等を使用することによってWebUIのリッチ化を行うことができます。

図6:ActiveWidgetsが提供するGrid以外のWebコンポーネント(クリックで拡大)

ところでActivewidgetsについては、筆者は以前にもThink ITに下記のような連載記事を書いています。この連載では、サーバ側で DWR(Direct Web Remoting)を使用した場合のActivewidgetsクライアントとの連携や表計算機能の追加、グラフ表示などについても解説していますので、興味のある方は是非参照してみてください。

Think IT連載『読んで試して!ActiveWidgets!』

3.6 Spreadsheetデータの登録・参照スクリプト

リスト3はSpreadsheetデータ登録・参照のHTMLおよびJavaScript記述でこの記述で図3~図5の表示処理すべてを行っています。

リスト4 Spreadsheetデータの登録・参照スクリプト(modDsSpreadAllShopYm.htm)

  <!DOCTYPE html>
  <html>
  <head>
  <meta charset="utf-8"/>
  <title> modDsSpreadAllShopYm </title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <link rel="stylesheet" href="../css/aw.css"/>
  <style type="text/css"/>
  #sgrid .aw-grid-row {height: 20px; border-bottom: 1px solid #ccc}
  #sgrid .aw-alternate-even {background: #fff;}
  #sgrid .aw-alternate-odd {background: #ddf;}
  #sgrid .aw-alternate-even .aw-column-0 {background: #ddf;}
  #sgrid .aw-alternate-odd .aw-column-0 {background: #ccf;}
  #sgrid .aw-rows-selected {background: #316ac5;}
  #sgrid .aw-rows-selected .aw-column-1 {background: #316ac5;}
  #sgrid .aw-column-0 {width: 75px; text-align: center; border-right: 1px dotted #ccc;}
  #sgrid .aw-column-1 {width: 65px; text-align: center; border-right: 1px dotted #ccc;}
  #sgrid .aw-column-2 {text-align: right}
  #sgrid .aw-column-3 {text-align: right}
  #sgrid .aw-column-4 {text-align: right}
  #sgrid .aw-column-5 {text-align: right}
  #sgrid .aw-column-6 {text-align: right}
  #sgrid .aw-mouseover-cell {color: red;} 
  #sgrid .aw-grid-row .aw-cells-selected {background: #316ac5;}
  #sgrid .aw-grid-headers {color: blue}
  #sgrid .aw-grid-headers .aw-column-1 {font-weight: bold}
  #sgrid .aw-mouseover-header {color: red;}
  #sgrid .aw-mousedown-header {color: yellow;}
  #sgrid .aw-header-1 {background: #def}
  #sgrid .aw-row-selector {width: 20px; text-align: center}
  #sgrid .aw-row-2 .aw-row-selector {font-weight: bold}
  #sgrid .aw-mouseover-row .aw-row-selector {color: red;}
  #sgrid .aw-mouseover-selector {background: green;}
  #sgrid .aw-mousedown-selector {background: yellow;}
  #sgrid {font-size: 10pt}
  </style>
  <script type="text/javascript" src="../js/jquery-2.0.3.min.js"></script>
  <script type="text/javascript" src="../js/aw.js"></script>
  <script type="text/javascript">
  $(function() {
    $("#addDs").click(function() {								//(1)スプレッド登録
      $("#dsp").html("<div id='stat'></div>")
      var query = {};
      query["mode"] = "addspreadallshoptodsym";
      query["sheet"] = $("#year").val() + $("#month").val();
      $.post("/spread", query, function(res) {
        $("#stat").text(res);
      });
    });
    $("#revSp").click(function() {					//(2)ドライブのスプレッドデータ参照
      getdata("getspreadallshopym");
    });
    $("#revDs").click(function() {					//(3)Datastoreのスプレッドデータ参照
      getdata("getdsallshopym");
    }); 
    function getdata(mode) {						//(4) 参照処理関数
      $("#dsp").html("<div id='sgrid'></div>")
      var query = {};
      query["mode"] = mode;
      query["sheet"] = $("#year").val() + $("#month").val();
      $.get("/spread", query, function(resp) {
        var r = $.parseJSON(resp);		//(5)受信したJSONデータをjavaScriptオブジェクトに変換  			var rows = 16;
        var cols = 7;
        var cdat = new Array(rows); 
        for (j = 0; j < rows; j++) { 
          cdat[j] = new Array(cols);			//(6)表示データ格納用に2次元配列生成
        }
        cdat[0][0] = "関東地区";
        cdat[5][0] = "近畿地区";
        cdat[10][0] = "中国地区";
        if (mode == "getspreadallshopym") {		//(7)Driveスプレッドデータの配列セット
          for (var i = 0; i < r.wsdat.length ; i++) {
            var idat = r.wsdat[i].data.split(",");		//(8)
            for (var j = 0; j < idat.length; j++) {
            var vdat = idat[j].split(":")[1];		//(9)
              cdat[i][j+1] = vdat;				//(10)
            }
          }
        } else if (mode == "getdsallshopym") {	//(11)Datastore格納スプレッドの配列セット
          for (var i = 0; i < r.length; i++) { 
            var rtotal = 0;
            for (var j = 0; j < r[i].length; j++) {
              if (j > 0) { 
                rtotal += parseInt(r[i][j]);     		//(11)	行合計の加算 
              }
              cdat[i][j+1] = r[i][j];					//(12)セル値の配列セット 
            } 
          cdat[i][j+1] = rtotal;							//(13)行合計の集計値セット
          }
          cdat[15][1] = "売上合計"; 
          for (var i = 2; i < cols; i++) { 		//(14)列合計値の計算
              var ctotal = 0;
              for (var j = 0; j < rows - 1 ;j++) {
                  ctotal += parseInt(cdat[j][i]); 
              } 
              cdat[rows -1][i] = ctotal;		//(15)列合計の集計値セット
            }
          }
          var headers = ["地域名", "店舗名", "食品", "家電", "寝具", "その他", "合計"]; 
                                              //(16) 
          var grid = new AW.Grid.Extended;
          grid.setId("sgrid");
          var gridw = 28 + 93 * cols;
          var gridh = 28 + 26 * rows;
          grid.setControlSize(gridw, gridh);      	// グリッド幅と高さ指定
          grid.setCellText(cdat);               	//表示データの配列を指定
          grid.setCellEditable(true);            	//グリッドのセルを編集可能に指定
          grid.setHeaderText(headers);         	//ヘッダ表示の配列を指定
          grid.setRowCount(rows);             	// 行数指定
          grid.setColumnCount(cols);           	// 列数指定
          grid.setSelectorText(function(i){return this.getRowPosition(i);}); // 行ヘッダ表示
          grid.setSelectorVisible(true);          	//行ヘッダの表示指定
          document.getElementById("sgrid").innerHTML = grid;   	//(17) 
        });
      }
    });
    </script>
    </head>
    <body>
    <h3>Spreadsheet データ登録・参照</h3>
    年<select id="year">
      <option value="">=年選択=</option>
      <option value="2013">2013年</option>
      <option value="2012">2012年</option>
      <option value="2011">2011年</option>
    </select>
    月<select id="month">
        <option value="">=月選択=</option>
      <option value="01">1月</option>
      <option value="02">2月</option>
      <option value="03">3月</option>
      <option value="04">4月</option>
      <option value="05">5月</option>
      <option value="06">6月</option>
      <option value="07">7月</option>
      <option value="08">8月</option>
      <option value="09">9月</option>
      <option value="10">10月</option>
      <option value="11">11月</option>
      <option value="12">12月</option>
    </select>
    <input type="button" id="addDs" value=" スプレッド登録  " />
     <input type="button" id="revSp" value=" スプレッド参照  " />
    <input type="button" id="revDs" value="データストア参照 " />
    <hr />
    <div id="dsp"></div>
    </body>
  </html>

リスト4で、(1)のスプレッド登録は一般的なjQueryの$.post通信なので問題ないでしょう。(2)と(3)はドライブとDatastoreのスプレッドデータの参照処理で、(4)のgetdataメソッドを、処理モード(”mode”)を引数に指定して呼び出しています。

処理内容はどちらも同様で、受信したスプレッドデータをセル項目毎に分割し、2次元配列にセットした後に表示処理(レンダリング)を行います。ただし、受信するデータフォーマットがDriveからとDatastoreからでは異なるため、配列へデータをセットする部分のコード記述が異なっています。

[Driveからのスプレッドデータを配列にセット]

Driveからのスプレッドデータの場合は、各セル項目がカンマ区切り(CSV)形式でセットされているため、(8)においてカンマ区切りでsplit処理したデータを配列idatにセットし、更に”セル名:セル値”になっている配列idatの各項目から(9)でセル値を取り出して、(10)で配列にセットしています。

[Datastoreからのスプレッドデータを配列にセット]

Datastoreからのスプレッドデータの場合は、リスト2の(7)でクライアントに送信されるJSONデータが2次元配列形式にフォーマットされているので、(5)でJavaScriptオブジェクトに変換された配列値を(11)で行合計値を加算した後、個別のセル値を(12)で配列にセットし、集計の終わった行合計値を(13)でセットしています。

その後、列合計の集計を(14)の繰り返し処理で行い、(15)で集計値をセットしています。ここで行合計の欄も列合計の計算で集計されるので、総合計値が行合計欄の最後の項目として配列にセットされます。

[グリッド表示の編集]

(16)のヘッダ項目指定以下は、グリッドの表示形式を設定するメソッドが並んでおり、最後に(17)のinnerHTMLでグリッドのWeb画面への表示(レンダリング)が行われます。

有限会社サイバースペース
慶應義塾大学工学部電気科卒。日本IBM、日本HPなどにおいて、製造装置業を中心とした業務系/基幹業務系システムのSE/マーケティングや、3階層C/Sアーキテクチャによる社内業務システム開発などに携わる。現在は、Ajax/Web 2.0関連のセミナー講師/コンサルティング、書籍執筆などを行っている。情報処理学会会員。http://www.at21.net/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています