Excelセルの数値文字列を数値ではなく文字列として読み取るにはどうすればよいですか?


146
  1. 私はそのような内容のExcelファイルを持っています:

    • A1:SomeString

    • A2:2

    すべてのフィールドは文字列形式に設定されます。

  2. POIを使用してJavaでファイルを読み取ると、A2が数値セル形式であることを示しています。

  3. 問題は、A2の値が2または2.0である可能性がある(そして、それらを区別できるようにしたい)ため、だけを使用できないこと.toString()です。

値を文字列として読み取るにはどうすればよいですか?

回答:


319

同じ問題がありました。cell.setCellType(Cell.CELL_TYPE_STRING);文字列値を読み取る前に行ったので、ユーザーがセルをどのようにフォーマットしたかに関係なく、問題が解決しました。


私はpoi-3.8-beta4を使用していますが、期待どおりに動作しています!TSがこれを答えとして受け入れないのはなぜですか?
swdev

POI数値から文字列への変換ではシステムロケールが考慮されないことに注意してください。小数点は常に小数点として使用されます。たとえば、システムが「、」を使用していて、Excelの数値が「1,9」のように見える場合、POIは代わりに「1.9」を返します。
Alexey Berezkin 2013年

53
Apache POI javadocsはこれを行わないように明示的に言っていることに注意してください彼らは説明として、あなたは代わりにDataFormatterを使用する必要があります
Gagravarr

6
これを行うことに対するGagravarrの警告は正しいです!ドキュメントから:「数値セルの文字列値を取得する場合は、停止してください!これはその方法ではありません。代わりに、数値またはブール値または日付セルの文字列値をフェッチするには、代わりにDataFormatter。」poi.apache.org/apidocs/org/apache/poi/ss/usermodel/… 変更するつもりのないデータを誤って変更してしまうまで、私はこのテクニックを自分で使っていました。(タイプを文字列に設定し、値を読み取り、タイプを数値に戻し、再度読み取り、別の数値を取得してください!)
Chris Finley

6
DataFormatterを使用します。Javadocは、上記の方法を使用しないように警告します。
Balu SKT 2016

96

あなたが質問したときに私たちがこのクラスを取り戻したとは思いませんが、今日は簡単な答えがあります。

やりたいことは、DataFormatterクラスを使用することです。これをセルに渡すと、Excelがそのセルに対して表示する内容を含む文字列を返すことが最善です。文字列セルを渡すと、文字列が返されます。フォーマット規則が適用された数値セルを渡すと、それらに基づいて数値がフォーマットされ、文字列が返されます。

あなたのケースでは、数値セルに整数の書式ルールが適用されていると仮定します。これらのセルをフォーマットするようにDataFormatterに要求すると、整数文字列を含む文字列が返されます。

また、多くの人がそうすることを勧めていますcell.setCellType(Cell.CELL_TYPE_STRING)が、Apache POI JavaDocsはこれを行うべきではないと明確に述べていることに注意してください!こうsetCellTypeとしてコールすることは、書式設定失うことになるのJavadocを説明し、残りの書式設定で文字列に変換する唯一の方法は使用することですDataFormatterクラスを


@Gagravarrに感謝します。私の答えは、<code> cell.setCellType(Cell.CELL_TYPE_STRING); <code>で2.2の値を2.2000000000000002に変換してくれますが、2.2が必要です。何でも文字列形式で返します。おかげで
ankush yadav

dataformatterは数式セルでは機能しないようで、値ではなく数式の文字列表現を返します
gaurav5430

1
マイナーなメモを1つだけ:提供されたリンクに記載されている場合も、そのような回答の短いコードスニペットを提供してください
BAERUS

@ gaurav5430はい、数式ではうまくいきません... docによるとWhen passed a null or blank cell, this method will return an empty String (""). Formulas in formula type cells will not be evaluated.
SaratBhaswanth

53

以下のコードは、どのタイプのセルでも機能しました。

InputStream inp =getClass().getResourceAsStream("filename.xls"));
Workbook wb = WorkbookFactory.create(inp);
DataFormatter objDefaultFormat = new DataFormatter();
FormulaEvaluator objFormulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) wb);

Sheet sheet= wb.getSheetAt(0);
Iterator<Row> objIterator = sheet.rowIterator();

while(objIterator.hasNext()){

    Row row = objIterator.next();
    Cell cellValue = row.getCell(0);
    objFormulaEvaluator.evaluate(cellValue); // This will evaluate the cell, And any type of cell will return string value
    String cellValueStr = objDefaultFormat.formatCellValue(cellValue,objFormulaEvaluator);

}

4
うまくいきました!私の提案は、FormulaEvaluatorの取得方法を変更することです。Workbookクラスは、getCreationHelper().createFormulaEvaluator()メソッドを介して数式エバリュエーターを提供します。この方法では、コードはHSSFFormulaEvaluatorクラスと結合されません。
Vitor Santos、

これは受け入れられる答えになるはずです。ありがとう@Vinayak
Phas1c

FormulaEvaluatorこのソリューションから簡単に削除できますか?それは目的を果たしますか?
P.Brian.Mackey 2017

1
objFormulaEvaluator.evaluateを呼び出す必要はありません。その戻り値はここでは使用されていません。
Radu Simionescu、2018年

32

セルのタイプの変更が望ましくない場合は、次の方法をお勧めします。

if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
    String str = NumberToTextConverter.toText(cell.getNumericCellValue())
}

NumberToTextConverterは、精度を失うことなく、Excelのルールを使用してdouble値をテキストに正しく変換できます。


本当にエキサイティングなアドバイス!ありがとうございました!cellTypeをStringに設定するのとは対照的に、変換されていない値を取得できます。
Gleb Egunov

セル値2020年6月25日の出力として44007を取得しています。何が悪いのですか?
Vinay


10

はい、これは完全に機能します

推奨:

        DataFormatter dataFormatter = new DataFormatter();
        String value = dataFormatter.formatCellValue(cell);

古い:

cell.setCellType(Cell.CELL_TYPE_STRING);

cell数式からの値の取得に問題がある場合でも、これは機能します。


5
ただし、これをdouble値に使用する場合は注意が必要です。私にとっては値7.9を7.8999956589965に変えました...
Chris

2
ApacheのPOIのjavadocをあなたがそのようにそれをやってはならないことを非常に明確である何がやりたいことは、あなたの数値セルの文字列値を取得する場合には、ストップ!これはそれを行う方法ではありません。代わりに、数値セル、ブール値セル、または日付セルの文字列値をフェッチするには、代わりにDataFormatterを使用してください。
Gagravarr 2016

4

試してください:

new java.text.DecimalFormat("0").format( cell.getNumericCellValue() )

数値を正しくフォーマットする必要があります。


私は理解しているように、アスカーは区別できるようにしたいと考えて22.0。あなたの解決策はこれをしません。(それでも、Stack Overflowへようこそ!)
PaŭloEbermann、2011

1

ユーザーが数値を入力する前にセルがテキスト形式である限り、POIは値を文字列として取得できるようにします。1つのキーは、セルの左上隅にテキストとして書式設定された小さな緑色の三角形がある場合、その値を文字列として取得できることです(数値のように見えるものがあるときはいつでも、緑色の三角形が表示されます)テキスト形式に強制変換されます)。数値を含むテキスト形式のセルがあるが、POIでこれらの値を文字列として取得できない場合は、スプレッドシートデータに対していくつかのことを行うと、次のことが可能になります。

  • セルをダブルクリックして編集カーソルがセル内に表示されるようにしてから、Enterキーを押します(一度に実行できるセルは1つだけです)。
  • Excel 2007のテキスト変換関数を使用します(一度に複数のセルで実行できます)。
  • 問題の値を別の場所に切り取り、スプレッドシートのセルをテキストとして再フォーマットしてから、以前に切り出した値を「フォーマットされていない値」として適切な領域に貼り付けます。

最後にできることの1つは、POIを使用してExcel 2007スプレッドシートからデータを取得している場合、Cellクラスの「getRawValue()」メソッドを使用できることです。これはフォーマットが何であるかを気にしません。生データの文字列を返すだけです。


0

Apache POIライブラリを使用してMS Excelの数値セル値を読み取ると、数値として読み取られます。しかし、文字列として読み取ることを希望する場合があります(電話番号など)。これは私がそれをした方法です:

  1. 最初のセル= CONCATENATE( "!"、D2)の新しい列を挿入します。D2は電話番号列のセルIDだと思います。最後まで新しいセルをドラッグします。

  2. POIを使用してセルを読み取ると、計算された値ではなく数式が読み取られます。次のようにします。

  3. 別の列を追加

  4. 手順1で作成した完全な列を選択し、[編集]-> [コピー]を選択します。

  5. 手順3で作成した列の一番上のセルに移動し、[編集]-> [形式を選択して貼り付け]を選択します。

  6. 開いたウィンドウで、「値」ラジオボタンを選択します

  7. 「OK」を選択

  8. 今POI APIを使用して読んでください... Javaで読んだ後...最初の文字、すなわち「!」を削除するだけです


自分でExcelファイルを作成しないと、あなたの解決策は使えないと思われますか?(また、あなたの答えに抜粋を入れてもらえますか?それはそれほど長くはありません。)
PaŭloEbermann

はい、Excelファイルを自分で作成していない場合は使用できません。
Asif Shahzad 2011

0

私も数千の数値のデータセットで同様の問題を抱えていて、解決する簡単な方法を見つけたと思います。番号の前にアポストロフィを挿入して、別のDBインポートで常に番号がテキストとして認識されるようにする必要がありました。これ以前は、8は8.0としてインポートされていました。

解決:

  • すべてのフォーマットを「一般」のままにします。
  • ここでは、行1から始まる数値が列Aに格納されていると想定しています。
  • 列Bに 'を入れ、必要な数の行をコピーします。ワークシートには何も表示されませんが、セルをクリックすると、数式バーにアポストロフィが表示されます。
  • 列C:= B1&A1。
  • 列Cのすべてのセルを選択し、値オプションを使用して列Dに形式を選択して貼り付けます。

Hey Prestoすべての数値ですが、テキストとして保存されます。


0

セルタイプが数値の場合、getStringCellValueはNumberFormatExceptionを返します。セルの種類を文字列に変更したくない場合は、これを行うことができます。

String rsdata = "";
try {
    rsdata = cell.getStringValue();
} catch (NumberFormatException ex) {
    rsdata = cell.getNumericValue() + "";
}

0

これらの回答の多くは、古いPOIドキュメントとクラスを参照しています。最新のPOI 3.16では、int型のCellは非推奨になりました

Cell.CELL_TYPE_STRING

ここに画像の説明を入力してください

代わりに、CellType列挙型を使用できます。

CellType.STRING 

pomをpoi依存関係とpoi-ooxml依存関係で新しい3.16バージョンに更新してください。そうしないと、例外が引き続き発生します。このバージョンの1つの利点は、セルの作成時にセルタイプを指定できることです。これにより、前の回答で説明した追加の手順がすべて削除されます。

titleRowCell = currentReportRow.createCell(currentReportColumnIndex, CellType.STRING);

0

私はむしろウィルの答えやビナヤック・ドルナラのルートに行きたいですが、残念ながら彼らは私のパフォーマンスにはるかに影響を与えました。私は暗黙のキャストのHACKYソリューションに行きました:

for (Row row : sheet){
String strValue = (row.getCell(numericColumn)+""); // hack
...

私がこれを行うことはお勧めしません。私の状況では、システムがどのように機能するかという性質と、信頼できるファイルソースがあったためです。

脚注:numericColumnは、処理されたファイルのヘッダーの読み取りから生成されるintです。


0
public class Excellib {
public String getExceldata(String sheetname,int rownum,int cellnum, boolean isString) {
    String retVal=null;
    try {
        FileInputStream fis=new FileInputStream("E:\\Sample-Automation-Workspace\\SampleTestDataDriven\\Registration.xlsx");
        Workbook wb=WorkbookFactory.create(fis);
        Sheet s=wb.getSheet(sheetname);
        Row r=s.getRow(rownum);
        Cell c=r.getCell(cellnum);
        if(c.getCellType() == Cell.CELL_TYPE_STRING)
        retVal=c.getStringCellValue();
        else {
            retVal = String.valueOf(c.getNumericCellValue());
        }

私はこれを試しました、そしてそれは私のために働きました


-1

とにかくあなたはExcelワークシートを制御していますか?ユーザーが入力するためのテンプレートはありますか?その場合は、入力セルのコード形式を設定できます。




-1

これは私にとって完璧に機能しました。

Double legacyRow = row.getCell(col).getNumericCellValue();
String legacyRowStr = legacyRow.toString();
if(legacyRowStr.contains(".0")){
    legacyRowStr = legacyRowStr.substring(0, legacyRowStr.length()-2);
}

-2

同じ問題があり、ユーザーに値を入力するにセルを「テキスト」としてフォーマットすることを強制しました。これにより、Excelは偶数をテキストとして正しく保存します。後でフォーマットが変更された場合、Excelは値の表示方法のみを変更しますが、値を再入力しない限り(値がセルにあるときにReturnキーを押すなどして)値を保存する方法は変更しません。

Excelが値をテキストとして正しく保存したかどうかは、セルに数値が含まれているがテキストとして書式設定されているとExcelがセルの左上隅に表示する小さな緑色の三角形で示されます。


-3

intにキャストしてから.toString()。醜いですが動作します。


問題は、A2に2.0がある場合、文字列「2.0」を取得する必要があり、2の場合、文字列「2」を取得することです。
joycollector 2009
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.