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)

package com.google.gdata;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.*;
@SuppressWarnings("serial")
public class SpreadServlet extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    resp.setContentType("text/plain");
      resp.setContentType("text/html; charset=utf-8");
      PrintWriter out = resp.getWriter();
      String mode = req.getParameter("mode"); 
      String sheet = req.getParameter("sheet");
      SpreadBean ss = new SpreadBean(); 
      ////////////////////////////////////////////////////////////////////
      //  For Sales data
      if (mode.equals("getdsallshopym")) {
        String rv = ss.getDsAllShopYm(sheet);		//(1)
        out.println(rv);
      } else if (…) {
        :
      }
  }
  
  public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    resp.setContentType("text/plain");
    resp.setContentType("text/html; charset=utf-8");
    PrintWriter out = resp.getWriter();
    String mode = req.getParameter("mode"); 
    String sheet = req.getParameter("sheet");
    SpreadBean ss = new SpreadBean(); 
    ////////////////////////////////////////////////////////////////////
    //  For Sales data
    if (mode.equals("addspreadallshoptodsym")) {
      String rv = ss.addSpreadAllShopToDsYm(sheet);		//(2)
      out.println(rv);
    } else if (…) {
      :
    }
  }
}

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

1.2 ビーンズコード記述

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

public String addSpreadAllShopToDsYm(String sheet)  { 
  // このアプリケーションの名称。任意の名前を設定
  String appliName = "cyberspace-SpreadsheetSearch-1";
  String username = "xxxxxxxxxxxxxxxxxxxxxxxxx";
  String password = "xxxxxxxxxxxxxxx";
  try {
    /////////////////////////////////////////////////////////
    //  [I] Driveにあるスプレッドデータを読み取る
    //  認証処理
    SpreadsheetService spreadsheetservice = new SpreadsheetService(appliName);
    spreadsheetservice.setUserCredentials(username, password);
    // 検索対象のスプレッドシートを特定
    FeedURLFactory feedurlfactory = FeedURLFactory.getDefault();
    SpreadsheetQuery spreadsheetquery = 
    new SpreadsheetQuery(feedurlfactory.getSpreadsheetsFeedUrl());
    spreadsheetquery.setTitleQuery(sheet); // 検索対象のスプレッドシート名を指定している
    SpreadsheetFeed spreadFeed =
      spreadsheetservice.query(spreadsheetquery, SpreadsheetFeed.class);
    SpreadsheetEntry spreadsheetentry = spreadFeed.getEntries().get(0);
    // 検索対象のワークシートを特定
    WorksheetEntry worksheetentry = spreadsheetentry.getDefaultWorksheet();
    //  クエリでワークシート内を検索
    ListQuery listquery = new ListQuery(worksheetentry.getListFeedUrl()); 
    ListFeed listfeed = spreadsheetservice.query(listquery, ListFeed.class); 
    /////////////////////////////////////////////////////////
    //     [II] 読み取ったスプレッドデータをDatastoreに書き込む
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();     		//(1)
    int i = 0;
    for (ListEntry listentry : listfeed.getEntries()) { 
      CustomElementCollection customelementcollection = listentry.getCustomElements();
                                                   	//(2)
      DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
      String moddate = df.format(new Date()); 
      Entity sales = null; 
      if (!customelementcollection.getValue("店舗名").equals("売上合計")) {   	//(3)
        Key saleskey = KeyFactory.createKey								//(4)
        ("salesym", sheet + customelementcollection.getValue("店舗名")); 
        sales = new Entity(saleskey);									  	//(5)
        sales.setProperty("seq", i++); 
      } else {
        Key saleskey = KeyFactory.createKey
        ("salesymtotal", sheet + customelementcollection.getValue("店舗名"));	 //(6)
        sales = new Entity(saleskey);										//(7)
      }
      sales.setProperty("shop", customelementcollection.getValue("店舗名"));		//(8)
      sales.setProperty("yyyymm", sheet);
      sales.setProperty("food", customelementcollection.getValue("食品"));
      sales.setProperty("electric", customelementcollection.getValue("家電"));
      sales.setProperty("bedding", customelementcollection.getValue("寝具")); 
      sales.setProperty("other", customelementcollection.getValue("その他"));
      sales.setProperty("moddate", moddate); 
      ds.put(sales);       													//(9)
    }
    return "スプレッドデータのDatastore登録成功"; 
  } catch (AuthenticationException e) {
    e.printStackTrace();
    return "スプレッドデータのDatastore登録不成功 :" + e;
  } catch (IOException e) {
    e.printStackTrace();
    return "スプレッドデータのDatastore登録不成功 :" + e;
  } catch (ServiceException e) {
    e.printStackTrace();
    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)

public String getDsAllShopYm(String yyyymm) throws IOException, ServiceException { 
  try {
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();				//(1)
    Filter ymFilter = new FilterPredicate("yyyymm", FilterOperator.EQUAL, yyyymm);	//(2)
    Query q = new Query("salesym").setFilter(ymFilter).addSort("seq", SortDirection.ASCENDING);
                                                                                      //(3)
    PreparedQuery pq = ds.prepare(q);												    //(4) 
    String rv = "[";																    //(7)
    for (Entity res : pq.asIterable()) {												//(5)
      String shop = (String) res.getProperty("shop");								    //(6)
      String food = (String) res.getProperty("food");
      String electric = (String) res.getProperty("electric");
      String bedding = (String) res.getProperty("bedding");
      String other = (String) res.getProperty("other");
      rv 	+= "[\"" + shop + "\"," 
          + "\"" + food + "\"," 
          + "\"" + electric + "\"," 
          + "\"" + bedding + "\"," 
          + "\"" + other + "\"],";  					  //(7)
    } 
    rv = rv.substring(0, rv.length() - 1) + "]";										//(7)
    return rv;																	    //(8)
  } catch (Exception e) {
    e.printStackTrace();
    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)でクライアントへ送ります。

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

連載バックナンバー

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

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

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

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