Search jakarta

よくある質問 --FAQ on Apache POI

Questions

  1. 何故、単純なシートを読み込むのに時間がかかるのでしょうか?
  2. HSSFの"eventmodel"とは何ですか?
  3. Star Office 5.1を利用して作成した文書が読めないのはなぜ?
  4. シートを読み込もうとすると必ず例外が発生するのは何故?
  5. HSSFは、保護されたエクセルシートをサポートしますか?
  6. HSSFに、ある列が日付を含んでいるかどうかを判断させるには?
  7. XLSファイルのストリームをサーブレットから作ろうとしているのですが、トラブルが発生します。何が問題なのでしょうか?
  8. エクセルシートに、###,###,###.#### あるいは ###,###,###.0000 といった形のセルフォーマット(セルのデータフォーマット)をセットしたいと思っています。POIでそれは可能ですか?
  9. エクセルシートに、テキスト形式のセルフォーマット(セルのデータフォーマット)をセットしたいと思っています。POIでそれは可能ですか?
  10. 結合セルの周りに罫線を加えるには?
  11. エクセルシートの名前に私が使っている言語をセットしようとしたのですが、失敗してしまうのですが・・。
  12. WebSphere3.5を使ってPOIでスプレッドシートを作成しようとすると問題が発生するのですが・・
  13. POIでワークブックを作成する際、styleを使うのですが、ファイルを開く際 Excelが"Too Many Styles"といってファイルを開けません
  14. POIは、いかなるスプレッドシートでも読み込んだり修正する事が出来るのでしょうか?

Answers

1. 何故、単純なシートを読み込むのに時間がかかるのでしょうか?

ログ取得(ロギング)を可能としているのではないでしょうか。ロギングは、単なるデバッグのためのものです。ロギングを可能とする事で、パフォーマンスが少なくとも100倍は悪くなります。ロギングは確かに、POIが何故ファイルを読み込めないかを判断したり、POIの開発の際には有効です。重大なエラーの際は例外を投げますので、ロギングは必要ないかもしれません。

2. HSSFの"eventmodel"とは何ですか?

HSSFの"eventmodel"パッケージは、XLSファイルをより効率よく読み込む為の新しいAPIです。ユーザレベルであれば、深い知識は必要ありませんが、10倍以上メモリの消費を抑えてくれます。SAXと連携した、AWTイベントモデルがベースとなっています。リードオンリーで与えられたXLSファイルにアクセスするのであれば、このパッケージを利用するのが最善の方法です。

3. Star Office 5.1を利用して作成した文書が読めないのはなぜ?

Star Office 5.1 は、古いBIFF標準を使ってレコードを書き込みます。そのため、BIFF8形式しかサポートしないPOIでは問題が発生します。

4. シートを読み込もうとすると必ず例外が発生するのは何故?

そのシートに、HSSEが現在サポートしていない機能が含まれている可能性があります。例えば、リッチテキスト形式のセルを含むシートなどは、現在サポートされていません。

5. HSSFは、保護されたエクセルシートをサポートしますか?

シートをプロテクト(保護)することで、それは暗号化されます。私達は、法律的な勉強をしていませんし、この実装を完璧にする為の方法を知らないため、この暗号化についてはタッチしたくありません。プラグインモジュールでこの機能を加えたいと思うなら、ご自由にお願いしたいと思います。ここには書かないでしょうけれどもね(訳注:相当、筆者は法的なことを気にされているのでしょうね)。

6. HSSFに、ある列が日付を含んでいるかどうかを判断させるには?

Excel では、日付を数値形式で記憶させるため、セルが日付で入力されているかどうかを判断するただ一つの方法は、日付形式を参照する事です。日付形式をチェックするためのHSSFDateUtil (1.7.0-devリリースより)というメソッドを用意しています。 この問題の解決策を提供してくださった、ジャイソン・ホフマン氏に感謝しております。

   case HSSFCell.CELL_TYPE_NUMERIC:
         double d = cell.getNumericCellValue();
         // test if a date!
         if (HSSFDateUtil.isCellDateFormatted(cell)) {
           // format in form of M/D/YY
           cal.setTime(HSSFDateUtil.getJavaDate(d));
           cellText =
             (String.valueOf(cal.get(Calendar.YEAR))).substring(2);
           cellText = cal.get(Calendar.MONTH)+1 + "/" +
                      cal.get(Calendar.DAY_OF_MONTH) + "/" +
                      cellText;
         } 

7. XLSファイルのストリームをサーブレットから作ろうとしているのですが、トラブルが発生します。何が問題なのでしょうか?

通常、意味不明な文字列が画面上に見えることから、この問題の存在が明らかになります。この問題は、正しいMIME-Typeをセットしたとしても残り続けます。

簡単な回答としては・・サーブレットを通じてストリームを作ろうとする場合、バイナリファイルタイプのものを表示させるのにIEに頼ってはいけない、ということです。マイナーバージョンのIE(訳注:確か、IE5.5もそう)には、必ずと言っていいほど、この類のバグがあります。

殆どのバージョンのIEでのこの問題は、ファイルの種類を特定するのにHTTPレスポンスでMIME-Typeを使わず、むしろリクエスト(HTTP要求)のファイルタイプで特定しようとする事から生じています。従って、リクエスト文字列に .xls という文字列を加えたいと思う事でしょう。例えば、http://yourserver.com/myServelet.xls?param1=xxのように。これによって、あらゆるサーブレットコンテナにてURLマッピングが容易に達成されます。また、 http://yourserver.com/myServelet?param1=xx&dummy=file.xls という形のリクエストも、機能することが知られています。

ExcelファイルをIEから適切に開く事を保証するためには、サーブレットからweb rootの下にテンポラリファイルを生成してみるのも良いでしょう。そのテンポラリファイルにクライアント側がリダイレクトするようなHTTP RESPONSEを送る、というわけです (RequestDispatcherを使ってサーバー側でリダイレクトさせる場合、上で示したように.xls文字列をリクエスト文字列に付け加えなければなりません)。

外部ハンドラで開かれる文書をリクエストする場合、よく、IEがウェブサーバに二つのリクエストをする、という事を覚えておいてください。ですから、もし生成プロセスが重ければ、テンポラリファイルを書き出す方が賢明です(静的なファイルに対してだと、複数のリクエストが同時に起こる可能性がありますので)。

これは、Excelに限った事ではありません。IEのクライアントでバイナリファイルを直接生成する場合にも同じ問題が発生します。例えばFOPを使用してPDFファイルを生成しようとすれば、きっと同じ問題に遭遇する事でしょう。

8. エクセルシートに、###,###,###.#### あるいは ###,###,###.0000 といった形のセルフォーマット(セルのデータフォーマット)をセットしたいと思っています。POIでそれは可能ですか?

はい、可能です。先ず始めに、HSSFDataFormatオブジェクトをワークブックから得る必要があり、また、お望みのフォーマットのgetFormatを呼ぶ必要があります。こちらに、いくつかのサンプルがあります。

9. エクセルシートに、テキスト形式のセルフォーマット(セルのデータフォーマット)をセットしたいと思っています。POIでそれは可能ですか?

はい、可能です。これは、Excelのビルトインの形式でありまして、フォーマット用の文字列"@"を使うことでHSSFDataFormatオブジェクトから得ることの出来る形式です。また、文字列"text"もこの形式のエイリアスとなっています。

10. 結合セルの周りに罫線を加えるには?

空白のセルをセルが通常ある場所の周りに追加し、各々のセルに個別に罫線をセットします。おそらく私たちは将来的にHSSFを拡張し、この処理を容易になるようにする事でしょう。

11. エクセルシートの名前に私が使っている言語をセットしようとしたのですが、失敗してしまうのですが・・。

デフォルトで、HSSFはcompressed unicodeとしてシート名やセル値を使います。よって、ローカライゼーションをサポートするためには、Unicodeを使わなければなりません。それを行うには、手動でやります:

                // for sheet name
                HSSFWorkbook wb = new HSSFWorkbook();
                HSSFSheet s = wb.createSheet();
                wb.setSheetName( 0, "SomeUnicodeName", HSSFWorkbook.ENCODING_UTF_16 );

                // for cell value
                HSSFRow r = s.createRow( 0 );
                HSSFCell c = r.createCell( (short)0 );
                c.setCellType( HSSFCell.CELL_TYPE_STRING );
                c.setEncoding( HSSFCell.ENCODING_UTF_16 );
                c.setCellValue( "\u0422\u0435\u0441\u0442\u043E\u0432\u0430\u044F" ); 

setCellValue()を呼ぶ前に、setEncoding()を呼ぶことを忘れないで下さい。さもないと、通そうとした値が適切に解釈されない可能性があります。

12. WebSphere3.5を使ってPOIでスプレッドシートを作成しようとすると問題が発生するのですが・・

fix pack 4 がインストールされているか確認してください。

13. POIでワークブックを作成する際、styleを使うのですが、ファイルを開く際 Excelが"Too Many Styles"といってファイルを開けません

セルを作成するループの「外で」styleを作成してください。

良い例:

 HSSFWorkbook wb = new HSSFWorkbook();
 HSSFSheet sheet = wb.createSheet("new sheet");
 HSSFRow row = null;

 // Aqua background
 HSSFCellStyle style = wb.createCellStyle();
 style.setFillBackgroundColor(HSSFColor.AQUA.index);
 style.setFillPattern(HSSFCellStyle.BIG_SPOTS);
 HSSFCell cell = row.createCell((short) 1);
 cell.setCellValue("X");
 cell.setCellStyle(style);

 // Orange "foreground", foreground being the fill foreground not the font color.
 style = wb.createCellStyle();
 style.setFillForegroundColor(HSSFColor.ORANGE.index);
 style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

 for (int x = 0; x < 1000; x++) {

 // Create a row and put some cells in it. Rows are 0 based.
	 row = sheet.createRow((short) k);

	 for (int y = 0; y < 100; y++) {
		cell = row.createCell((short) k);
 		cell.setCellValue("X");
		cell.setCellStyle(style);
	 }
 }

 // Write the output to a file
 FileOutputStream fileOut = new FileOutputStream("workbook.xls");
 wb.write(fileOut);
 fileOut.close(); 

悪い例:

 HSSFWorkbook wb = new HSSFWorkbook();
 HSSFSheet sheet = wb.createSheet("new sheet");
 HSSFRow row = null;

 for (int x = 0; x < 1000; x++) {
	 // Aqua background
	 HSSFCellStyle style = wb.createCellStyle();
	 style.setFillBackgroundColor(HSSFColor.AQUA.index);
	 style.setFillPattern(HSSFCellStyle.BIG_SPOTS);
	 HSSFCell cell = row.createCell((short) 1);
	 cell.setCellValue("X");
	 cell.setCellStyle(style);

	 // Orange "foreground", foreground being the fill foreground not the font color.
	 style = wb.createCellStyle();
	 style.setFillForegroundColor(HSSFColor.ORANGE.index);
	 style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

	 // Create a row and put some cells in it. Rows are 0 based.
	 row = sheet.createRow((short) k);

	 for (int y = 0; y < 100; y++) {
		 cell = row.createCell((short) k);
		 cell.setCellValue("X");
		 cell.setCellStyle(style);
	 }
 }

 // Write the output to a file
 FileOutputStream fileOut = new FileOutputStream("workbook.xls");
 wb.write(fileOut);
 fileOut.close(); 

14. POIは、いかなるスプレッドシートでも読み込んだり修正する事が出来るのでしょうか?

POIを使ってあらゆるスプレッドシートの内容を読み込む保証はありません。ある機能(スプレッドシートの機能)によってスプレッドシートの読み込みが失敗する場合もあります。もっと問題となるのは、スプレッドシートの再書き込みです。POIは、出来る限りオリジナルのスプレッドシートのレコードを保存しようとしますが、いくつかの機能により問題が起こる可能性があります。後々の段階で驚かれたりしない為にも、貴方が処理するスプレッドシートのフォーマッティングに制限をかけておくことをお奨めいたします。

Original English Page would be found from HERE     --    BBS/ApacheNews
Terra-International, Inc. -- テラ・インターナショナル
Special Thanks -- 【お問い合わせ/テキスト広告】