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を適用しているんだが、これが何か影響しているんだろうか?
もう少し詳しく調べてみることにするか。

2010-12-13

MHP3 モンハンポータブル3rd入手!

12/1(水)に発売されて約一週間で200万本を出荷、店頭では売り切れ状態というものすごい売れ行きのようですね。
12/11(土)にやっとMHP3を入手できたので、その経緯を書いておく。

発売日当日は、さすがに予約のみの販売で予約なしの購入は不可でした。
予約申込みのカードが一枚だけ残っていたので息子の分を予約、4日の午後以降来店してくださいとのこと。自分の分は、まだゴッドイーターバーストが終わっていないので、通常販売分が店頭に並んだら買うことにした。
そして4日午後、店に行き無事入手(^^)v
さて自分の分だが、MHP3の販売コーナーに貼り紙があり、“'8日午後入荷予定“とのこと。う~ん土曜日まで残ってるかなぁ?

さて土曜日(12/11)、午前中は用事があったので午後一に店に行った。
あった!\(^^)/ 販売コーナーに10本弱並んでいたので即、手に取りレジへ…
前に2人並んでいて手元を見るとMHP3が! おお!狩仲間!
支払を済ませてゲット!!(^^)v
翌日、別の用事で店に行って見ると販売コーナーには一つもなく次回入荷の貼り紙が…
いゃぁ、買っておいて良かった。

この調子で売れると年内に300万本とか400万本とかいくかもね!?

2010-10-08

X06HT Android2.2インストール失敗?! ビビった(-_-;

今日10時以降に、X06HTのAndroid2.2(Froyo)へのアップデートが始まりました。
中々アップデート通知が来ないので、待ちきれずに11時頃に手動アップデートしてしまいました。(仕事中にも関わらず(^_^ゞ)
無事ダウンロードが終わりインストールが開始された途端...
エラーが発生しインストールができない、とのメッセージが表示された。
メッセージをよく読むと25MB以上の空きメモリが必要とのこと。メモリを食ってる大きなアプリをアンインストールして再チャレンジしてみた。
今度はインストールが続行され、待つこと10分ほどで再起動され、パーセント表示のカウントアップが始まりさらに数分待ち、完了した。
エラーが表示されたので、まさか起動できなくなってしまうのでは? とビビってしまったが無事アップデート完了しました。(^_^)v
しかし、こういう注意事項はダウンロード前に明記しておいて欲しいな。

アプリケーション一覧を見てみると、いくつか新しいアプリケーションが追加されている。
  • お勧めメッセージ
  • ニュースと天気
  • ビデオプレイヤー(2.1からあったかなぁ?)
  • フラッシュライト

SDカードへのアプリケーションインストールをやってみた。マーケットからのインストール時にインストール先を選択できるのかと思ったが違った。
手順は以下のとおり。
インストール済みのアプリをSDカードに移動する場合は"手順2"から実行すればよい。
  1. マーケットから今まで通りインストールする
  2. [menu]-[設定]-[アプリケーション]-[アプリケーションの管理]
  3. アプリケーションをタッチ
  4. [SDカードに移動]をタッチ