Excelデータの読み取りにHSSF-POIを使用しています。問題は、セルに数値のように見えるが実際には文字列である値があることです。 Excelのフォーマットセルを見ると、タイプは「テキスト」であると表示されます。それでも、HSSFセルはそれが数値であると考えています。値を文字列として取得するにはどうすればよいですか?
cell.getRichStringValue
を使おうとすると、例外が発生します。 cell.toString
の場合、Excelシートとまったく同じ値ではありません。
編集:これが解決されるまで、私は使用します
new BigDecimal(cell.getNumericCellValue()).toString()
あなたはHSSF-POIが言うことを意味します
cell.getCellType() == Cell.CELL_TYPE_NUMERIC
ない
_Cell.CELL_TYPE_STRING
_あるべきですか?
POIのバグだと思いますが、すべてのセルにバリアントが含まれており、バリアントにはタイプがあります。そこでバグを作成するのは難しいので、代わりにExcelが追加のデータまたはヒューリスティックを使用してフィールドをテキストとしてレポートすると思います。悲しいかな、通常のMSの方法。
P.S.バリアントデータのバイナリ表現はそのタイプに依存し、実際の数値から文字列を取得しようとするとガベージが発生するため、数値を含むバリアントでgetString()
を使用することはできません。例外。
POIで探しているクラスは DataFormatter
Excelがファイルを書き込むとき、一部のセルはリテラル文字列として保存され、他のセルは数値として保存されます。後者の場合、セルを表す浮動小数点値がファイルに格納されるため、POIにセルの値を要求すると、実際にセルの値が保持されます。
ただし、特にテキスト抽出を実行する場合(常にではありません)、セルの値をExcelの場合と同じように見せたい場合があります。これを文字列で正確に取得できるとは限りません(たとえば、フルスペース以外のパディング)が、DataFormatterクラスで近づけることができます。
セルの文字列を探している場合は、Excelで見たときと同じように、次のようにします。
// Create a formatter, do this once
DataFormatter formatter = new DataFormatter(Locale.US);
.....
for(Cell cell : row) {
CellReference ref = new CellReference(cell);
// eg "The value of B12 is 12.4%"
System.out.println("The value of " + ref.formatAsString() + " is " + formatter.formatCellValue(cell));
}
フォーマッタは文字列セルをそのまま返し、数値セルの場合はスタイルのフォーマット規則をセルの数に適用します
解析しているドキュメントが常に特定のレイアウトにある場合は、セルタイプをその場で「文字列」に変更してから、値を取得できます。たとえば、列2が常に文字列データである必要がある場合は、そのセルタイプを文字列に設定してから、文字列タイプのgetメソッドで読み取ります。
cell.setCellType(Cell.CELL_TYPE_STRING);
私のテストでは、セルタイプを変更してもセルの内容は変更されませんでしたが、次のいずれかの方法でセルを取得できました。
cell.getStringCellValue();
cell.getRichStringCellValue().getString();
適切に変換されていない値の例がないと、これが説明で説明したcell.toString()アプローチとは異なる動作をするかどうかを知ることは困難です。
以下のコードは任意のセルタイプを読み取るために正常に機能しますが、そのセルには数値が含まれている必要があります
new BigDecimal(cell.getNumericCellValue()));
例えば.
ase.setGss(new BigDecimal(hssfRow.getCell(3).getNumericCellValue()));
ここで、変数gssはBigDecimalタイプです。
Excelは、文字列から数値、日付、または時刻のように見えるものをすべて変換します。 MSナレッジベースの記事 を参照してください。これは基本的に、文字列になる余分な文字を使用して数値を入力することを提案しています。
あなたはおそらくExcelの問題を扱っています。スプレッドシートを作成するとき、デフォルトのセルタイプは汎用です。このタイプでは、Excelは入力に基づいてタイプを推測し、このタイプは各セルに保存されます。
後でセル形式をテキストに変更すると、デフォルトが変更されるだけです。 Excelは、すべてのセルのタイプを自動的に変更するわけではありません。これを自動的に行う方法が見つかりませんでした。
これを確認するには、Excelに移動して、数値の1つを再入力し、それがHSSFのテキストであるかどうかを確認します。
この関数を使用して、実際のセルタイプを確認することもできます。
@Cell("type", A1)
A1は数値のセルです。テキストの場合は「l」、数字の場合は「v」と表示されます。
Excelの問題は、デフォルトの形式が汎用であるということです。この形式では、Excelはセルに入力された数値を数値として保存します。形式をテキストに変更する必要があります前値を入力します。フォーマットを変更した後に値を再入力することもできます。
コンテンツがExcelの数字のように見える場合、セルの左上隅に小さな緑色の三角形が表示されます。この場合、値は実際にはテキストとして保存されます。
新しいBigDecimal(cell.getNumericCellValue())。toString()を使用すると、まだ多くの問題が発生します。たとえば、識別番号(部品番号や分類番号など)がある場合、getNumericCellValue()アプローチで問題となる先行ゼロがある場合があります。
POIで処理する必要のあるファイルを作成する当事者にExcelを正しく作成する方法を徹底的に説明しようとしています。ファイルがエンドユーザーによってアップロードされた場合、事前に列を知っていれば、予想されるセルタイプをチェックする検証プログラムを作成しました。副産物として、提供されたファイルの他のさまざまなことを確認することもできます(たとえば、提供された正しい列や必須の値)。
「問題は、セルに数値のように見える値があることです」=> Excelで表示すると、数値のように見えますか?
「しかし、実際には文字列です」=>それはどういう意味ですか?それらが本当に文字列であることをどうやって知るのですか?
「フォーマットセルを見ると」=>「フォーマットセル」とは何ですか?
'... Excelでは、タイプは「テキスト」と表示されます' =>説明してください。
「それでもHSSFセルはそれが数値だと考えています。」 => the_cell.getCellType()がCell.CELL_TYPE_NUMERICを返すという意味ですか?
「値を文字列として取得するにはどうすればよいですか?」 => NUMERICの場合は、the_cell.getNumericCellValue()を使用して数値を取得し、任意の方法で文字列としてフォーマットします。
「cell.getRichStringValueを使おうとすると、例外が発生します。」 =>だからそれは文字列ではありません。
「cell.toStringの場合、Excelシートとまったく同じ値ではありません。」 =>したがって、cell.toString()は、Excelがフォーマットする方法でフォーマットしません。
ヒューリスティックExcelがタイプを決定するために使用するものは何でも、あなたには関係ありません。重要なのは、ファイルに保存され、getCellType()によって明らかにされたその決定の結果です。