2011-08-16

Google+の招待状入手!!

Google+の招待状を入手した。(^^)v
しかし... 夏期休暇中なのでサークルに入れる人がいない(;_;)
子供のアカウントに招待状を送ってみたが未成年はNGみたい。(生年月日を正直に入力したので)
とりあえず何人かフォローしてストリームを眺めてる。(^^;
夏期休暇が終わったら何人か招待して色々試してみよう。

2011-03-05

JExcelAPI:GAE/J+Slim3でExcel作成、日本語データを入れてみた

JExcelAPIの続き。
作成するExcelシートのセルに日本語データを入れてみた。
cell = sheet.getWritableCell(0, 0);
Label lbl = new Label(0, 0, "あいうえお");
sheet.addCell(lbl);
ダウンロードしたExcelファイルを開いてみると、ちゃんと設定した値がセルに格納されていた。
なんか簡単すぎて拍子抜けした感じ...

2011-02-11

JExcelAPI:GAE/J+Slim3でExcel作成、ちょっと困った(~_~)

GAE/J+Slim3で作っているアプリでExcelを操作する必要があったので「JExcelAPI」を調べてみた。
ちょっと困ったことが起きたが最終的に目的の動作は確認できたので、その経過をメモしておく。(まだ実際のGAE/J環境で動作確認していない)

とりあえず"tutorial"を読みながら、
  • 新規にExcel Workbookを作成
  • シートを作成
  • セルに値を入力
という処理を作ってみた。
コードはこんな感じ。
ByteArrayOutputStream os = new ByteArrayOutputStream();
WritableWorkbook workbook = Workbook.createWorkbook(os);
WritableSheet sheet = workbook.createSheet("SheetA", 0);
Label label = new Label(0, 0, "ABC");
sheet.addCell(label);
workbook.write();
workbook.close();
ダウンロードしたファイルをExcelで開いてみると、ちゃんと[A1]のセルに"ABC"の文字が入っている。(^^)v
ここでポイントはWorkbookを作成するところで、"tutorial"では
Workbook.createWorkbook(new File("output.xls")); 
とFileオブジェクトを使用している代わりにByteArrayOutputStreamを使用しているところ。
GAE/JではファイルI/O関連の使用に制約がありファイル出力が行えない。したがってファイルへ出力する代わりにByteArrayOutputStreamでバイトストリームに出力する。

本来やりたかったことはテンプレートとなるExcelファイルを用意しておいて、特定のセルに処理結果の値を入力しダウンロードできるようにすること。
次はこの処理を試してみる。
"tutorial"の"Copying and Modifying Spreadsheets"の説明を参考にコードを書いてみた。
String templatePath = servletContext.getRealPath("/template/sample.xls");
File file = new File(templatePath);
Workbook template = Workbook.getWorkbook(file);
ByteArrayOutputStream os = new ByteArrayOutputStream();
WritableWorkbook workbook = Workbook.createWorkbook(os, template);
WritableSheet sheet = workbook.getSheet(0);
WritableCell cell = sheet.getWritableCell(1, 2);
if (cell.getType() == CellType.LABEL) {
  Label l = (Label) cell;
  l.setString("modified cell");
}
workbook.write();
workbook.close();
さっそく実行してみると
java.lang.ArrayIndexOutOfBoundsException
    at java.lang.System.arraycopy(Native Method)
    at jxl.biff.StringHelper.getBytes(StringHelper.java:127)
    at jxl.write.biff.WriteAccessRecord.<init>(WriteAccessRecord.java:59)
    at jxl.write.biff.WritableWorkbookImpl.write(WritableWorkbookImpl.java:726)
    at jp.technosite.election.controller.pp.DlController.getExcelReport(DlController.java:73)
    at jp.technosite.election.controller.pp.DlController.run(DlController.java:41)
とArrayIndexOutOfBoundsExceptionが発生してしまった。
JExcelAPI側で落ちてるし、セルへ値を設定せずにwriteしても同じ結果になったので、JExcelAPI側に問題がありそうだ。
ということでデバッガで追ってみる。

まずは
jxl.write.biff.WriteAccessRecord.<init>(WriteAccessRecord.java:59)
の部分...
public WriteAccessRecord(String userName) {
    super(Type.WRITEACCESS);
    data = new byte[112];
    String astring = userName == null ? (new StringBuilder()).append("Java Excel API v").append(Workbook.getVersion()).toString() : userName;
    StringHelper.getBytes(astring, data, 0);
    for(int i = astring.length(); i < data.length; i++)
        data[i] = 32;
}
"StringHelper.getBytes()"の箇所で落ちている。
ここでは astringを dataにコピーしていて、dataはサイズが112となっている。
ということはastringが怪しい。デバッガで内容を確認すると150byte以上あったのでこれが原因だ。
この元になっているのはメソッド引数 userNameなので呼び元の
jxl.write.biff.WritableWorkbookImpl.write(WritableWorkbookImpl.java:726)
を調べてみると、
WriteAccessRecord wr = new WriteAccessRecord(settings.getWriteAccess());
となっていて settings.getWriteAccess()の値が使われている。
userNameが'null'なら適当な値を設定してくれるので、settings.getWriteAccess()の値をnullになるようにすれば動きそうだ。
settingsはWorkbookSettingsクラスなのでJavadocで調べてみると、setWriteAccess(String)があって
setWriteAccess(null);
とすればよさそうだ。

結局、こんなコードになった。
String templatePath = servletContext.getRealPath("/template/sample.xls");
File file = new File(templatePath);
Workbook template = Workbook.getWorkbook(file);
ByteArrayOutputStream os = new ByteArrayOutputStream();
WorkbookSettings settings = new WorkbookSettings();
settings.setWriteAccess(null);
WritableWorkbook workbook = Workbook.createWorkbook(os, template, settings);
WritableSheet sheet = workbook.getSheet(0);
WritableCell cell = sheet.getWritableCell(1, 2);
if (cell.getType() == CellType.LABEL) {
  Label l = (Label) cell;
  l.setString("modified cell");
}
workbook.write();
workbook.close();
実行してみると、めでたくsample.xlsがコピーされたExcelファイルがダウンロードできた。\(^o^)/

後は日本語の扱いが気になるのでもう少し調べてみる必要があるな。

2011-02-03

Slim3+mobyletで困った(+o+)

今つくっているGAE/J+Slim3アプリで携帯電話対応することになったので、以前から目を付けていた『mobylet』を本格的に調査することにした。
タイムリーなことに@ITに『Google App EngineとSlim3とMobyletで始める携帯Web入門』が掲載されたので、この記事を参考にしながら試行錯誤してみた。

携帯絵文字などは問題なく表示された。
続いて携帯キャリア判定を試してみるために
Mobylet mobylet = MobyletFactory.getInstance();
を実行してみたら"NullPointerException"となってしまった。(;_;)
おそらくrequestがMobyletに渡っていないからだろうと予想して
RequestUtils.set(request);
としてみたらMobyletオブジェクトが取得できた。

URL"/m/*"だけにMobyletFilterを適用しているんだが、これが何か影響しているんだろうか?
もう少し詳しく調べてみることにするか。