JavaからGoogle Spreadsheetを参照する

以下を参考にGoogle Spreadsheetのデータを参照してみた。(ほぼそのまま)
GData APIでGoogleスプレッドシートを参照するには (1/3):Spreadsheets Data APIを使うための基礎知識(1) - @IT
https://sites.google.com/site/niusounds/programming/google-data-apinyuumon


本当にそのままコピーして自分のusername/passwordを設定し実行したらエラーになった。
公開範囲の影響(?)なのか分らなかったので自分でデータを作った。

使用したデータはこれ。
https://docs.google.com/spreadsheet/ccc?key=0AkxY01rLRjOfdElOZ3B0YXhQZjk0QkpWYnlPQmNaRkE


SpreadsheetSearch.java

package sample;

import java.io.IOException;

import com.google.gdata.client.spreadsheet.FeedURLFactory;
import com.google.gdata.client.spreadsheet.ListQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.spreadsheet.CustomElementCollection;
import com.google.gdata.data.spreadsheet.ListEntry;
import com.google.gdata.data.spreadsheet.ListFeed;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.data.spreadsheet.WorksheetEntry;
import com.google.gdata.util.ServiceException;

public class SpreadsheetSearch {

    /**
     * @param args
     */
    public static void main(String[] args) throws IOException, ServiceException {
        // このアプリケーションの名称。任意の名前を設定
        String applicationName = "com-SpreadsheetSearch-1";
        // Google AppsもしくはGoogleアカウントのメールアドレスとパスワードを設定
        String username = "";
        String password = "";
        // Spreadsheetsサービスへの認証を行う
        SpreadsheetService service = new SpreadsheetService(applicationName);
        service.setUserCredentials(username, password);

        // 検索対象のスプレッドシートを取得
        FeedURLFactory urlFactory = FeedURLFactory.getDefault();
        SpreadsheetQuery spreadsheetQuery = new SpreadsheetQuery(urlFactory
                .getSpreadsheetsFeedUrl());
        spreadsheetQuery.setTitleQuery("検索データ"); // 検索対象のスプレッドシート名を指定している
        SpreadsheetFeed spreadsheetFeed = service.query(spreadsheetQuery,
                SpreadsheetFeed.class);
        SpreadsheetEntry spreadsheetEntry = spreadsheetFeed.getEntries().get(0);
        System.out.println("名前:" + spreadsheetEntry.getTitle().getPlainText());

        // 検索対象のワークシートを取得
        WorksheetEntry worksheetEntry = spreadsheetEntry.getDefaultWorksheet();

        // ワークシート内を検索
        ListQuery listQuery = new ListQuery(worksheetEntry.getListFeedUrl());
//        listQuery.setSpreadsheetQuery("HEADER1 = HEADER1-1"); エラーになる
//        listQuery.setSpreadsheetQuery("header1 = HEADER1-1"); エラーになる
        listQuery.setSpreadsheetQuery("header1 = \"HEADER1-1\""); // OK
//        listQuery.setSpreadsheetQuery("\"HEADER1\" = \"HEADER1-1\""); ダメでした
//        listQuery.setSpreadsheetQuery("\"header1-9\" = \"HEADER1-1\""); // OK
        ListFeed listFeed = service.query(listQuery, ListFeed.class);
        ListEntry listEntry = listFeed.getEntries().get(0);
        CustomElementCollection elements = listEntry.getCustomElements();
        System.out.println("HEADER1:" + elements.getValue("HEADER1"));
        System.out.println("HEADER2:" + elements.getValue("header2"));
        System.out.println("HEADER3:" + elements.getValue("header3"));
    }

}


実行結果

名前:検索データ
HEADER1:HEADER1-1
HEADER2:HEADER2-1
HEADER3:HEADER3-1


よくわからなかった点
(1)検索時はカラム部分に大文字が使えない?
Spreadsheet上ではカラムをHEADER1と記述しているのにsetSpreadsheetQueryの部分でHEADER1と記述するとエラーになる。
小文字でheader1と記述すると大丈夫だった。
そのわりにはgetValue("HEADER1")でちゃんと値がとれる。

名前:検索データ
Exception in thread "main" com.google.gdata.util.InvalidEntryException: Bad Request
Parse error: Invalid column name: HEADER1

    at com.google.gdata.client.http.HttpGDataRequest.handleErrorResponse(HttpGDataRequest.java:594)
    at com.google.gdata.client.http.GoogleGDataRequest.handleErrorResponse(GoogleGDataRequest.java:563)
    at com.google.gdata.client.http.HttpGDataRequest.checkResponse(HttpGDataRequest.java:552)
    at com.google.gdata.client.http.HttpGDataRequest.execute(HttpGDataRequest.java:530)
    at com.google.gdata.client.http.GoogleGDataRequest.execute(GoogleGDataRequest.java:535)
    at com.google.gdata.client.Service.getFeed(Service.java:1135)
    at com.google.gdata.client.Service.getFeed(Service.java:1077)
    at com.google.gdata.client.GoogleService.getFeed(GoogleService.java:662)
    at com.google.gdata.client.Service.query(Service.java:1237)
    at com.google.gdata.client.Service.query(Service.java:1178)
    at sample.SpreadsheetSearch.main(SpreadsheetSearch.java:48)


(2)setSpreadsheetQueryでハイフンを入れるとエラー
文字通りハイフンを入れて検索を行ったらエラーになった。
ただアンスコ(_)は大丈夫だった。

        // ワークシート内を検索
        ListQuery listQuery = new ListQuery(worksheetEntry.getListFeedUrl());
//        listQuery.setSpreadsheetQuery("HEADER1 = HEADER1-1"); //エラーになる
//        listQuery.setSpreadsheetQuery("header1 = HEADER1-1"); //エラーになる
        listQuery.setSpreadsheetQuery("header1 = \"HEADER1-1\""); // OK
//        listQuery.setSpreadsheetQuery("\"HEADER1\" = \"HEADER1-1\""); //ダメでした
//        listQuery.setSpreadsheetQuery("\"header1-9\" = \"HEADER1-1\""); // OK(header1-9というカラム名にした場合)
名前:検索データ
Exception in thread "main" com.google.gdata.util.InvalidEntryException: Bad Request
Parse error: null

    at com.google.gdata.client.http.HttpGDataRequest.handleErrorResponse(HttpGDataRequest.java:594)
    at com.google.gdata.client.http.GoogleGDataRequest.handleErrorResponse(GoogleGDataRequest.java:563)
    at com.google.gdata.client.http.HttpGDataRequest.checkResponse(HttpGDataRequest.java:552)
    at com.google.gdata.client.http.HttpGDataRequest.execute(HttpGDataRequest.java:530)
    at com.google.gdata.client.http.GoogleGDataRequest.execute(GoogleGDataRequest.java:535)
    at com.google.gdata.client.Service.getFeed(Service.java:1135)
    at com.google.gdata.client.Service.getFeed(Service.java:1077)
    at com.google.gdata.client.GoogleService.getFeed(GoogleService.java:662)
    at com.google.gdata.client.Service.query(Service.java:1237)
    at com.google.gdata.client.Service.query(Service.java:1178)
    at sample.SpreadsheetSearch.main(SpreadsheetSearch.java:50)

どうにかならないものかと適当に""でくくってみたら大丈夫だった。
ただカラム部分を大文字にして""でくくってみても駄目だった。

まとめ

  • 検索時はカラム部分を小文字にする。
  • ハイフンを使うときは""でくくる。


Groovy版
参考にしました。
Java使いをGroovyに引き込むサンプル集 - No Programming, No Life
Eclipseで作成。
手順
01.Groovy Projectを作成(Google Spreadsheetを参照するにあたって必要なjarも設定する)
02.SpreadsheetSearch.groovyを作成
03.SpreadsheetSearch.javaのmainメソッドの中をコピー
04.SpreadsheetSearch.groovyのmainメソッドに3.でコピーしたコードを貼り付け
05.ctrl+shift+oでインポートの編成
ここまででひとまず動いた。*1
06.行末のセミコロンを削除
07.String等の型をdefに変更する
08.ctrl+shift+oでインポートの編成
09.インポートするクラスに別名をつける
10.別名をつけたクラスに変更する
11.ちょっと手を加える


SpreadsheetSearch.groovy(コメント部分は削除)

package sample

import com.google.gdata.client.spreadsheet.FeedURLFactory as FUF
import com.google.gdata.client.spreadsheet.ListQuery as LQ
import com.google.gdata.client.spreadsheet.SpreadsheetQuery as SQ
import com.google.gdata.client.spreadsheet.SpreadsheetService as SS
import com.google.gdata.data.spreadsheet.ListFeed as LF
import com.google.gdata.data.spreadsheet.SpreadsheetFeed as SF

class SpreadsheetSearch {

    static main(args) {
        def applicationName = "com-SpreadsheetSearch-1"
        def username = ""
        def password = ""

        def service = new SS(applicationName)
        service.setUserCredentials(username, password)

        def urlFactory = FUF.getDefault()
        def spreadsheetQuery = new SQ(urlFactory.getSpreadsheetsFeedUrl())
        spreadsheetQuery.setTitleQuery("検索データ")
        def spreadsheetFeed = service.query(spreadsheetQuery, SF.class)
        def spreadsheetEntry = spreadsheetFeed.getEntries().get(0)
        println "名前:${spreadsheetEntry.getTitle().getPlainText()}"

        def worksheetEntry = spreadsheetEntry.getDefaultWorksheet()

        def listQuery = new LQ(worksheetEntry.getListFeedUrl())
        listQuery.setSpreadsheetQuery("header1 = \"HEADER1-1\"")
        def listFeed = service.query(listQuery, LF.class)
        def listEntry = listFeed.getEntries().get(0)
        def elements = listEntry.getCustomElements()
        println "HEADER1:${elements.getValue("HEADER1")}"
        println "HEADER2:${elements.getValue("header2")}"
        println "HEADER3:${elements.getValue("header3")}"
    }

}

もっと簡単に書けると思うけど知っている知識ではここまで。
名前の付け方によるかもしれないが別名インポートを使うと分かりにくくなりそう。

*1:SpreadsheetSearch.javaの拡張子を.groovyに変更してGroovy Projectにつっこんでも動く。