今回は、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)
01 | package com.google.gdata; |
02 | import java.io.IOException; |
03 | import java.io.PrintWriter; |
04 | import javax.servlet.http.*; |
05 | @SuppressWarnings("serial") |
06 | public 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 | //////////////////////////////////////////////////////////////////// |
16 | if (mode.equals("getdsallshopym")) { |
17 | String rv = ss.getDsAllShopYm(sheet); //(1) |
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 | //////////////////////////////////////////////////////////////////// |
33 | if (mode.equals("addspreadallshoptodsym")) { |
34 | String rv = ss.addSpreadAllShopToDsYm(sheet); //(2) |
サーブレットの処理は連載前回のリスト2への追加で行われており、(1)のgetDsAllShopYmメソッドではDatastoreに書き込まれたスプレッドデータの読み取り、(2)のaddSpreadAllShopToDsYmメソッドではDriveから読み込んだスプレッドデータのDatastore書き込み処理を行っています。
1.2 ビーンズコード記述
リスト2 addSpreadAllShopToDsYmメソッド(SpreadBean.java)
01 | public String addSpreadAllShopToDsYm(String sheet) { |
02 | // このアプリケーションの名称。任意の名前を設定 |
03 | String appliName = "cyberspace-SpreadsheetSearch-1"; |
04 | String username = "xxxxxxxxxxxxxxxxxxxxxxxxx"; |
05 | String password = "xxxxxxxxxxxxxxx"; |
07 | ///////////////////////////////////////////////////////// |
08 | // [I] Driveにあるスプレッドデータを読み取る |
10 | SpreadsheetService spreadsheetservice = new SpreadsheetService(appliName); |
11 | spreadsheetservice.setUserCredentials(username, password); |
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); |
21 | WorksheetEntry worksheetentry = spreadsheetentry.getDefaultWorksheet(); |
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) |
29 | for (ListEntry listentry : listfeed.getEntries()) { |
30 | CustomElementCollection customelementcollection = listentry.getCustomElements(); |
32 | DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); |
33 | String moddate = df.format(new Date()); |
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++); |
41 | Key saleskey = KeyFactory.createKey |
42 | ("salesymtotal", sheet + customelementcollection.getValue("店舗名")); //(6) |
43 | sales = new Entity(saleskey); //(7) |
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); |
54 | return "スプレッドデータのDatastore登録成功"; |
55 | } catch (AuthenticationException e) { |
57 | return "スプレッドデータのDatastore登録不成功 :" + e; |
58 | } catch (IOException e) { |
60 | return "スプレッドデータのDatastore登録不成功 :" + e; |
61 | } catch (ServiceException e) { |
63 | return "スプレッドデータのDatastore登録不成功 :" + e; |
[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)
01 | public String getDsAllShopYm(String yyyymm) throws IOException, ServiceException { |
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); |
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 + "\"," |
17 | + "\"" + electric + "\"," |
18 | + "\"" + bedding + "\"," |
19 | + "\"" + other + "\"],"; //(7) |
21 | rv = rv.substring(0, rv.length() - 1) + "]"; //(7) |
23 | } catch (Exception e) { |
25 | return "参照不成功 Exception:" + e; |
Datastoreに書き込まれたスプレッドデータを読み取る処理は、よりシンプルなコード記述になります。
(1)で前と同様にDatastoreServiceのインスタンス(ds)を生成し、(3)でDatastore検索用のQueryを生成しています。Queryはフィルタやソート条件を追加して検索データの絞り込みや、並べ替えを指定することができますが、ここでは(2)のフィルタ指定で年月指定を行い、ソート条件でseq(シークエンス)プロパティを昇順で並べ替える指定を行っています。
次に、(4)prepareで実行するクエリを作成し、(5)ではasIterableで(4)で作成したクエリを実行し、 Entity項目を Iterable(反復可能)として取得します。その後(6)以下のgetPropertyでプロパティ名に対応した値を取得し、(7)でWebクライアントでの処理に対応したJSONの配列形式にフォーマット後(8)でクライアントへ送ります。