さとやn Blog

試合はRuby,勝負はC#!

Java

Javaで複数パターンの日付文字列を厳密にパースする。

Javaで日付文字列をパースする処理が必要になりました。 org.apache.commons.lang.time.DateUtilsを使えば複数のパターンを配列で指定できるそうなので、それを利用してやってみる。
ていうか、ロケールに合わせて yyyy/MM/dd とか yyyy.MM.dd とか yyyy-MM-dd とか、一般的に使用されそうなやつはデフォルトで対応しろよ、とか思うのですが、そこはJavaなのでハナから期待はしていません。

で、下記のようなコードを書いてみました。 区切り文字が /(スラッシュ), .(ドット)、-(ハイフン)という、かなり普通に使用されるであろうパターンです。

	import java.text.ParseException;
	import java.util.Date;
	import org.apache.commons.lang.time.DateUtils;

	public class Main {
	    public static void main(String[] args) {

	        String[] patterns = new String[] {"yyyy-MM-dd", "yyyy.MM.dd", "yyyy/MM/dd"};

	        String[] dateStringList = new String[] {"1973-05-30", "1973.5.30", "1973/5/30", "1972/16/60"};

	        for (String dateString : dateStringList) {
	            try {
	                Date d = DateUtils.parseDate(dateString, patterns);
	                System.out.printf("String=%s, Date=%s\n", dateString, d);
	            } catch (ParseException e) {
	                // TODO Auto-generated catch block
	                e.printStackTrace();
	            }
	        }
	    }
	}
	
で、結果は
53)

う〜ん、、、 1972/16/60 というありえない日付を 1973/05/30
とちゃんと解釈してくれています。ていうか、エラーにしろよ、とか思うのですが、まあ、この言語ではもうこういうのが当たり前なんだと、あきらめモード、、、。

でも、DateUtils.parseDateStrictly を使うと厳密に解釈してくれるそう。
で、やってみると結果は

05)

まあ、これが普通だと思うんだけど、、、。

ちなみにC#では、何もしなくても期待通り、、、。
43)

まあ、Rubyでも
55)

C#やRubyがお利口さんなだけです

Java: POI IF関数でも結果を取得できるか?

結論から言うと、出来る。

 50)

23)

Java POI で関数の値を取得してみる

POIを使ってエクセルのデータを読めることはわかったのですが、関数の値や別セルの参照値はどうなんだろう? 実際ある程度の関数や参照は扱えないと使いものにならない。

調べてみると、ある程度のはサポートされているらしい。
  • References: single cell & area, 2D & 3D, relative & absolute
  • Literals: Number, text, boolean, error and array
  • Operators: arithmetic and logical, some region operators
  • Built-in functions: over 350 recognised, 280 evaluatable
  • Add-in functions: 3 from Analysis Toolpack
とりあえず十分のようです。

FormulaEvaluator というクラスが用意されていて、こいつで計算結果なりを取得できるようです。
取得方法はいくつか用意されているのですが、とりあえず一番簡単な

 FormulaEvaluator.evaluateInCell(Cell cell)

を使ってみる。これは引数で指定されたセルが計算式ならその結果でセルを置き換えてしまいます(元の式は式は結果で上書きされる)。
式でないなら何も起こりません。 
 とりあえず、sum()関数と別シートのセルを参照するようなエクセルファイルを作って試してみました。

 31)
50)
	public class Main {
		public static void main(String[] args){
		    try {
		        InputStream file = new FileInputStream("data/hello_poi.xls");
		        Workbook book = new HSSFWorkbook(file);
		        FormulaEvaluator feval = book.getCreationHelper().createFormulaEvaluator();
		        Sheet sheet = book.getSheetAt(0);
		        for(int rowIndex = 0; rowIndex < 4; rowIndex++) {
		            Row row = sheet.getRow(rowIndex);
		            for (int colIndex = 0; colIndex < 2; colIndex++) {
	                    Cell cell = row.getCell(colIndex);
	                    String rawValue = cell.toString();
	                    feval.evaluateInCell(cell);
	                    System.out.printf("row=%d, cell=%d, rawValue=%s, evaluatedValue=%s\n" ,
	                            rowIndex, 
	                            colIndex,
	                            rawValue,
	                            cell);
	                }
		        }
		        file.close();
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
		}
	}
  • row=2, cell=1, rawValue=Sheet2!A1, evaluatedValue=これは別シート
  • row=3, cell=1, rawValue=SUM(D1:D3), evaluatedValue=6.0
ちゃんと式の部分が評価された結果を取得できているようです。
これが出来ないと問題になりそうだったので、いやーよかったよかった、、、。



28)


Javaでエクセルファイルを読んでみる POIってなんだ?

最近Javaでエクセルファイルをを扱う必要が出てきて、聞いたところによるとPOIというものを使うらしい。
POIは100%Javaで書かれたマイクロソフト製品で作成されたドキュメントを扱うライブラリだそうで、POIという名前には2重の意味が込められているそうです。
詳しくは下記のサイトで。


で、早速最新版の3.7をダウンロード。


Eclipseで新規プロジェクトを作成して、POIライブラリをビルドパスに追加。
05)

サンプル用のエクセルファイルを作成。
55)

ファイル形式はXML形式ではなく旧式の(というか今でも最も一般的な気がする)xlsで保存。
※POI自体は両方のフォーマットに対応しているようです。
59)

クイックガイドを参考にコードを書いてみる。
かなり直感的に扱えるようです。
    1 import java.io.FileInputStream;
2 import java.io.InputStream;
3 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
4 import org.apache.poi.ss.usermodel.Row;
5 import org.apache.poi.ss.usermodel.Sheet;
6 import org.apache.poi.ss.usermodel.Workbook;
7
8
9 public class Main {
10 public static void main(String[] args){
11 try {
12 InputStream file = new FileInputStream("data/hello_poi.xls");
13 Workbook book = new HSSFWorkbook(file);
14 Sheet sheet = book.getSheetAt(0);
15 for(int rowIndex = 0; rowIndex < 2; rowIndex++) {
16 Row row = sheet.getRow(rowIndex);
17 System.out.printf("%s, %s\n", row.getCell(0), row.getCell(1));
18 }
19 file.close();
20 } catch (Exception e) {
21 e.printStackTrace();
22 }
23
}

24 }

25

実行するとちゃんと表示できました。
18)

次は書き出す処理をやってみる。



livedoor プロフィール
QRコード
QRコード
  • ライブドアブログ