スプレッドシートからデータを取得する時の注意事項

ググると、どうやったらスプレッドシートにデータをセットできるか、とかデータを取得するか、という簡単なサンプルは腐るほど見つかるんだが、じゃー一回でどんなけデータを取得できんのよ、とか、大量のデータを更新する最速の方法は?とか、少し突っ込んだことは全然見つからない。きっとそういう記事もあるんだろうけど、ウンコみたいな超簡単なサンプルページばっか上位に来るせいで、お目にかかれない。ウンコ情報を垂れ流すなよ、ほんと。

というわけで、10分ググって全然見つからなかったので自分で調べた結果をまとめておく。

セルが空でも取得する

デフォルトだとセルの値が空の場合、CellFeed.getEntries() で取得できない。

query.setReturnEmpty(true);

セルが空かどうかの判定

setReturnEmpty(true)にしている場合しか関係ないけど、getValue() を呼ぶと例外が発生するので、getInputValue() で様子を見る

for( CellEntry e : cellFeed.getEntries() )
{
  Cell c = e.getCell();
  if( !c.getInputValue().isEmpty() )
  {  // このセルは何か入ってる
    String val = c.getValue();
    ;
    ;
  }
}

CellQuery.setRange でセル指定する上限

行、列ともに限界は無いっぽい。(2013/09/14 現在)
ただし、シートの行数、列数を超える値を指定すると例外が飛ぶので、事前に行数、列数を取得しておく

WorksheetEntry worksheetEntry = spreadsheetEntry.getDefaultWorksheet();
int numRow = worksheetEntry.getRowCount();
int numCol = worksheetEntry.getColCount();

CellQuery query = new CellQuery(cellFeedUrl);
query.setRange("R1C1:R"+numRow+"C"+numCol);

CellFeed.getEntries() でイテレーションする順番

左上から右下。
たとえば、query.setRange("A1:C2"); としたら、

  1. A1
  2. A2
  3. B1
  4. B2
  5. C1
  6. C2

という順番となる

ListQuery で指定できるカラム名

これは知らないとドはまりするので要注意。

そもそもListQueryっちゅーのはスプレッドシートの1行目(仕様として固定されているみたい)をヘッダ行とみなして、指定したカラム名のデータで一致するものを検索できる。その時、指定できるカラム名に色々制限があるみたいで、ざっと調べた限りこんな法則があるようだ。(きっとまだ他に謎仕様があるだろうことが予想される)

  • アルファベットは大文字でも小文字でもOKだが半角じゃないとだめ。ただしクエリ文字列に渡す時は小文字で指定する。
  • 記号は半角でも全角でも使用できる。ただしクエリ文字列に渡す時は記号を消す必要がある。
  • 同じカラム名の場合は先に出てくるカラムが採用される

ではいくつかサンプルを挙げておく(適当に端折ってるのでこのままでは動きませんが意図は伝わるかと・・)

ヘッダが「ユーザID」の場合
listQuery.setSpreadsheetQuery("ユーザid=\"123\"");
ListFeed listFeed = service.query(listQuery, ListFeed.class);
for( int i=0; i<listFeed.getEntries().size(); ++i )
{
    ListEntry entry = listFeed.getEntries().get(i);
    CustomElementCollection e = entry.getCustomElements();
    System.out.println(e.getValue("ユーザid"));
}
ヘッダが「曜日(月)」の場合
listQuery.setSpreadsheetQuery("曜日月=\"\"");
ListFeed listFeed = service.query(listQuery, ListFeed.class);
for( int i=0; i<listFeed.getEntries().size(); ++i )
{
    ListEntry entry = listFeed.getEntries().get(i);
    CustomElementCollection e = entry.getCustomElements();
    System.out.println(e.getValue("曜日月"));
}

※「()」は全角でも半角でも同じ