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

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

今回は、App Engine側で読み取ったスプレッドデータのDatastore書き込み、およびそれぞれのデータ読み取り表示をスプレッドシート風のUI表示で行う処理内容について見ていきます。前回からJavaのプログラミングに入っていますが、今回もJavaによるスプレッドデータの処理が中心となります。

図1:Spread Sheet 年月別店舗売上(グリッド表示)(クリックで拡大)

図1のように、スプレッドデータをApp Engineから読み込んで、また簡易形式で画面表示する部分は前回の連載で見てきましたが、今回は読み取ったスプレッドデータをDatastoreに書き込んでみます。またDrive上およびDatastoreに書き込まれたスプレッドデータをグリッド表示するサンプルを紹介します。

スプレッドデータの表示形式では前回は簡易表示でしたが、今回はスプレッドシートの表示を、ActiveWidgetsを使用したサンプルとParamQuery gridを使用したサンプルの2種類紹介します。

1. Drive上のスプレッドデータをApp Engineから読み込みDatastoreに書き込む

最初はスプレッドデータのDatastore書き込みです。前回はスプレッドデータをApp Engineから読み込む処理について解説しましたが、今回は更にそのデータをDatastoreに書き込む処理について見ていきます。

ここで、スプレッドデータのDatastore書き込みでは、App EngineのLow-Level APIを使用しますが、Low-Level APIについてはThinkITにも下記の連載で解説していますので参考にしてください。

Think IT連載『Google App EngineのLow-Level APIを極める』

1.1 サーブレットのコード記述

リスト1 サーブレット(SpreadServlet.java)

01package com.google.gdata;
02import java.io.IOException;
03import java.io.PrintWriter;
04import javax.servlet.http.*;
05@SuppressWarnings("serial")
06public class SpreadServlet extends HttpServlet {
07  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
08    resp.setContentType("text/plain");
09      resp.setContentType("text/html; charset=utf-8");
10      PrintWriter out = resp.getWriter();
11      String mode = req.getParameter("mode");
12      String sheet = req.getParameter("sheet");
13      SpreadBean ss = new SpreadBean();
14      ////////////////////////////////////////////////////////////////////
15      //  For Sales data
16      if (mode.equals("getdsallshopym")) {
17        String rv = ss.getDsAllShopYm(sheet);       //(1)
18        out.println(rv);
19      } else if (…) {
20        :
21      }
22  }
23   
24  public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
25    resp.setContentType("text/plain");
26    resp.setContentType("text/html; charset=utf-8");
27    PrintWriter out = resp.getWriter();
28    String mode = req.getParameter("mode");
29    String sheet = req.getParameter("sheet");
30    SpreadBean ss = new SpreadBean();
31    ////////////////////////////////////////////////////////////////////
32    //  For Sales data
33    if (mode.equals("addspreadallshoptodsym")) {
34      String rv = ss.addSpreadAllShopToDsYm(sheet);     //(2)
35      out.println(rv);
36    } else if (…) {
37      :
38    }
39  }
40}

サーブレットの処理は連載前回のリスト2への追加で行われており、(1)のgetDsAllShopYmメソッドではDatastoreに書き込まれたスプレッドデータの読み取り、(2)のaddSpreadAllShopToDsYmメソッドではDriveから読み込んだスプレッドデータのDatastore書き込み処理を行っています。

1.2 ビーンズコード記述

リスト2 addSpreadAllShopToDsYmメソッド(SpreadBean.java)

01public String addSpreadAllShopToDsYm(String sheet)  {
02  // このアプリケーションの名称。任意の名前を設定
03  String appliName = "cyberspace-SpreadsheetSearch-1";
04  String username = "xxxxxxxxxxxxxxxxxxxxxxxxx";
05  String password = "xxxxxxxxxxxxxxx";
06  try {
07    /////////////////////////////////////////////////////////
08    //  [I] Driveにあるスプレッドデータを読み取る
09    //  認証処理
10    SpreadsheetService spreadsheetservice = new SpreadsheetService(appliName);
11    spreadsheetservice.setUserCredentials(username, password);
12    // 検索対象のスプレッドシートを特定
13    FeedURLFactory feedurlfactory = FeedURLFactory.getDefault();
14    SpreadsheetQuery spreadsheetquery =
15    new SpreadsheetQuery(feedurlfactory.getSpreadsheetsFeedUrl());
16    spreadsheetquery.setTitleQuery(sheet); // 検索対象のスプレッドシート名を指定している
17    SpreadsheetFeed spreadFeed =
18      spreadsheetservice.query(spreadsheetquery, SpreadsheetFeed.class);
19    SpreadsheetEntry spreadsheetentry = spreadFeed.getEntries().get(0);
20    // 検索対象のワークシートを特定
21    WorksheetEntry worksheetentry = spreadsheetentry.getDefaultWorksheet();
22    //  クエリでワークシート内を検索
23    ListQuery listquery = new ListQuery(worksheetentry.getListFeedUrl());
24    ListFeed listfeed = spreadsheetservice.query(listquery, ListFeed.class);
25    /////////////////////////////////////////////////////////
26    //     [II] 読み取ったスプレッドデータをDatastoreに書き込む
27    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();            //(1)
28    int i = 0;
29    for (ListEntry listentry : listfeed.getEntries()) {
30      CustomElementCollection customelementcollection = listentry.getCustomElements();
31                                                    //(2)
32      DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
33      String moddate = df.format(new Date());
34      Entity sales = null;
35      if (!customelementcollection.getValue("店舗名").equals("売上合計")) {    //(3)
36        Key saleskey = KeyFactory.createKey                             //(4)
37        ("salesym", sheet + customelementcollection.getValue("店舗名"));
38        sales = new Entity(saleskey);                                       //(5)
39        sales.setProperty("seq", i++);
40      } else {
41        Key saleskey = KeyFactory.createKey
42        ("salesymtotal", sheet + customelementcollection.getValue("店舗名"));   //(6)
43        sales = new Entity(saleskey);                                       //(7)
44      }
45      sales.setProperty("shop", customelementcollection.getValue("店舗名"));       //(8)
46      sales.setProperty("yyyymm", sheet);
47      sales.setProperty("food", customelementcollection.getValue("食品"));
48      sales.setProperty("electric", customelementcollection.getValue("家電"));
49      sales.setProperty("bedding", customelementcollection.getValue("寝具"));
50      sales.setProperty("other", customelementcollection.getValue("その他"));
51      sales.setProperty("moddate", moddate);
52      ds.put(sales);                                                        //(9)
53    }
54    return "スプレッドデータのDatastore登録成功";
55  } catch (AuthenticationException e) {
56    e.printStackTrace();
57    return "スプレッドデータのDatastore登録不成功 :" + e;
58  } catch (IOException e) {
59    e.printStackTrace();
60    return "スプレッドデータのDatastore登録不成功 :" + e;
61  } catch (ServiceException e) {
62    e.printStackTrace();
63    return "スプレッドデータのDatastore登録不成功 :" + e;
64  }
65}

[I] Driveにあるスプレッドデータを読み取る

Drive上のスプレッドデータ読み取りは、前回記事のリスト3と同じですので省略します。

[II] 読み取ったスプレッドデータをDatastoreに書き込む

(1)DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
App EngineのDatastoreにアクセスする場合は、最初にDatastoreServiceのインスタンス(ここではds)を生成します。

(2)次に、読み込んだスプレッドデータを1行ずつ読み取っての繰り返し処理に入ります。

(3)if~else文
・読み取ったデータが売上合計でない場合はif文内の(4)でキーを作成した後、kind名が「salesym」のエンティティをDatastore書き込み用に生成します(5)。
・読み取ったデータが売上合計の場合はelse以下で処理しており、(6)でキーを作成した後、(7)で「salesymtotal」のエンティティを生成しています。
その後は(8)以下で書き込むエンティティ(sales)にプロパティ項目をセットし、(9)のputメソッドで書き込み処理を行います。

2.Datastoreに書き込まれたスプレッドデータをApp Engineから読み取る

リスト3 getDsAllShopYmメソッド (SpreadBean.java)

01public String getDsAllShopYm(String yyyymm) throws IOException, ServiceException {
02  try {
03    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();                //(1)
04    Filter ymFilter = new FilterPredicate("yyyymm", FilterOperator.EQUAL, yyyymm);  //(2)
05    Query q = new Query("salesym").setFilter(ymFilter).addSort("seq", SortDirection.ASCENDING);
06                                                                                      //(3)
07    PreparedQuery pq = ds.prepare(q);                                                   //(4)
08    String rv = "[";                                                                    //(7)
09    for (Entity res : pq.asIterable()) {                                                //(5)
10      String shop = (String) res.getProperty("shop");                                   //(6)
11      String food = (String) res.getProperty("food");
12      String electric = (String) res.getProperty("electric");
13      String bedding = (String) res.getProperty("bedding");
14      String other = (String) res.getProperty("other");
15      rv    += "[\"" + shop + "\","
16          + "\"" + food + "\","
17          + "\"" + electric + "\","
18          + "\"" + bedding + "\","
19          + "\"" + other + "\"],";                        //(7)
20    }
21    rv = rv.substring(0, rv.length() - 1) + "]";                                        //(7)
22    return rv;                                                                      //(8)
23  } catch (Exception e) {
24    e.printStackTrace();
25    return "参照不成功 Exception:" + e;
26  }
27}

Datastoreに書き込まれたスプレッドデータを読み取る処理は、よりシンプルなコード記述になります。

(1)で前と同様にDatastoreServiceのインスタンス(ds)を生成し、(3)でDatastore検索用のQueryを生成しています。Queryはフィルタやソート条件を追加して検索データの絞り込みや、並べ替えを指定することができますが、ここでは(2)のフィルタ指定で年月指定を行い、ソート条件でseq(シークエンス)プロパティを昇順で並べ替える指定を行っています。

次に、(4)prepareで実行するクエリを作成し、(5)ではasIterableで(4)で作成したクエリを実行し、 Entity項目を Iterable(反復可能)として取得します。その後(6)以下のgetPropertyでプロパティ名に対応した値を取得し、(7)でWebクライアントでの処理に対応したJSONの配列形式にフォーマット後(8)でクライアントへ送ります。

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

連載バックナンバー

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

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

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

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