シリアル値の計算、その2 エクセル - java POI頼み
2014/02/15
excel
java
poi
エクセル
シリアル値
エクセルで使われるシリアル値の計算についてです。
と、実は、自前で計算しようとすると、とても面倒な気が....
これ素直に、ライブラリまかせのほういいと思う。
「下手に手出すと帰ってこれない」いつものパターン
poiに渡すまえに計算して、渡すのではなく、Dateかカレンダーにして渡すのがよいと思う。自前で、計算すると、正しいかどうか、ちょっと検証するのつらそうなのと、実績あるpoiのほうが、3.8888倍(当社比)信頼性が高いと思うのであった。
HSSFCellに実装みると、シリアル値にしてから設定しているのがわかる。
3.10-finalのコード参照
public void setCellValue(Calendar value) { setCellValue( HSSFDateUtil.getExcelDate(value, _book.getWorkbook().isUsing1904DateWindowing()) ); }
public void setCellValue(Date value) { setCellValue(HSSFDateUtil.getExcelDate(value, _book.getWorkbook().isUsing1904DateWindowing())); }
使うエクセルの設定によっては、1900 年日付システムと 1904 年日付システムを区別する必要があるのが上記のコードからもみてとれる。自前で、算出する場合、これも考慮しないといけないので、素直にpoiまかせで。
お試しとして、シリアル値が必要なら、HSSFDateUtilを使うのよいと思う。
変換自体のロジックはorg.apache.poi.ss.usermodel.DateUtilあるようです。
以下、poiのソースコードから
org.apache.poi.ss.usermodel.DateUtil
private static double internalGetExcelDate(Calendar date, boolean use1904windowing) {
if ((!use1904windowing && date.get(Calendar.YEAR) < 1900) ||
(use1904windowing && date.get(Calendar.YEAR) < 1904))
{
return BAD_DATE;
}
// Because of daylight time saving we cannot use
// date.getTime() - calStart.getTimeInMillis()
// as the difference in milliseconds between 00:00 and 04:00
// can be 3, 4 or 5 hours but Excel expects it to always
// be 4 hours.
// E.g. 2004-03-28 04:00 CEST - 2004-03-28 00:00 CET is 3 hours
// and 2004-10-31 04:00 CET - 2004-10-31 00:00 CEST is 5 hours
double fraction = (((date.get(Calendar.HOUR_OF_DAY) * 60
+ date.get(Calendar.MINUTE)
) * 60 + date.get(Calendar.SECOND)
) * 1000 + date.get(Calendar.MILLISECOND)
) / ( double ) DAY_MILLISECONDS;
Calendar calStart = dayStart(date);
double value = fraction + absoluteDay(calStart, use1904windowing);
if (!use1904windowing && value >= 60) {
value++;
} else if (use1904windowing) {
value--;
}
return value;
}
: