Frage an java, excel, apache-poi – Wie kann ich numerische Zeichenfolgen in Excel-Zellen als Zeichenfolge (nicht als Zahlen) lesen?

130

Ich habe eine Excel-Datei mit folgenden Inhalten:

A1: SomeString

A2: 2

Alle Felder sind auf das String-Format eingestellt.

Wenn ich die Datei in Java mithilfe von POI lese, wird angezeigt, dass A2 im numerischen Zellenformat vorliegt.

Das Problem ist, dass der Wert in A2 2 oder 2,0 sein kann (und ich möchte sie unterscheiden können), also kann ich nicht einfach verwenden.toString().

Was kann ich tun, um den Wert als Zeichenfolge zu lesen?

Deine Antwort

20   die antwort
-1

Es sieht so aus, als ob dies in der aktuellen POI-Version nicht möglich ist, da dieser Fehler:

https://issues.apache.org/bugzilla/show_bug.cgi?id=46136

steht noch aus.

0

nala gehen, leider haben sie meine Leistung viel zu sehr beeinflusst. Ich ging für einHACKY Lösung des impliziten Castings:

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

Ich schlage nicht vor, dass Sie dies tun, da es in meiner Situation aufgrund der Funktionsweise des Systems funktioniert hat und ich eine zuverlässige Dateiquelle hatte.

Fußnote: numericColumn Ist ein Int, der aus dem Lesen des Headers der verarbeiteten Datei generiert wird.

0

getStringCellValue gibt NumberFormatException zurück, wenn der Zelltyp numerisch ist. Wenn Sie den Zelltyp nicht in Zeichenfolge ändern möchten, können Sie dies tun.

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

Ja, das funktioniert einwandfrei

empfohlen:

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

alt:

cell.setCellType(Cell.CELL_TYPE_STRING);

auch wenn Sie ein Problem beim Abrufen eines Werts von habencell Formel haben, funktioniert immer noch.

alt sollte seinfalsch MiXT4PE
Aber Sie müssen vorsichtig sein, wenn Sie doppelte Werte verwenden. Für mich hat sich der Wert 7,9 in 7,8999956589965 verwandelt ... Chris
DasApache POI Javadocs sind sehr klar, dass Sie es nicht so machen sollten: Wenn Sie einen String-Wert für Ihre numerische Zelle erhalten möchten, stoppen Sie !. Dies ist nicht der richtige Weg. Verwenden Sie stattdessen DataFormatter, um den Zeichenfolgenwert einer numerischen oder booleschen Zelle oder einer Datumszelle abzurufen. Gagravarr
-1

Das hat bei mir perfekt funktioniert.

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

cell.setCellType (Cell.CELL_TYPE_STRING); funktioniert gut für mich

0

Wenn wir den numerischen Zellenwert von MS Excel mithilfe der Apache-POI-Bibliothek lesen, wird er als numerisch gelesen. Aber irgendwann möchten wir, dass es als Zeichenfolge gelesen wird (z. B. Telefonnummern usw.). So habe ich es gemacht:

Fügen Sie eine neue Spalte mit der ersten Zelle = CONCATENATE ("!", D2) ein. Ich nehme an, D2 ist die Zellen-ID Ihrer Telefonnummernspalte. Neue Zelle bis zum Ende ziehen.

Wenn Sie jetzt die Zelle mit dem POI lesen, wird anstelle des berechneten Werts die Formel gelesen. Jetzt mache folgendes:

Fügen Sie eine weitere Spalte hinzu

Wählen Sie die in Schritt 1 erstellte vollständige Spalte aus und wählen Sie Bearbeiten-> KOPIEREN

Gehen Sie zur obersten Zelle der in Schritt 3 erstellten Spalte und wählen Sie Bearbeiten-> Inhalte einfügen

Wählen Sie im geöffneten Fenster das Optionsfeld "Werte"

Wählen Sie "OK"

Lesen Sie jetzt mit der POI-API ... nach dem Einlesen von Java ... entfernen Sie einfach das erste Zeichen, d. H. "!"

Ja, es kann nicht verwendet werden, wenn man keine Excel-Datei selbst erstellt. Asif Shahzad
Ihre Lösung scheint nicht brauchbar zu sein, wenn man die Excel-Dateien nicht selbst erstellt, oder? (Könnten Sie auch einen Auszug in Ihre Antwort einfügen? Es ist nicht so lange.) Paŭlo Ebermann
44

Der folgende Code hat bei mir für jeden Zelltyp funktioniert.

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);

}
Dies sollte die akzeptierte Antwort sein. Vielen Dank @ Vinayak Phas1c
KönnenFormulaEvaluator einfach aus dieser lösung entfernt werden? Hat es einen Zweck? P.Brian.Mackey
Der Aufruf von objFormulaEvaluator.evaluate ist nicht erforderlich. Der Rückgabewert davon wird hier nicht verwendet. Radu Simionescu
Hat prima funktioniert! Mein Vorschlag wäre, die Art und Weise zu ändern, wie der FormulaEvaluator abgerufen wird. Die Workbook-Klasse stellt einen Formelauswerter zur VerfügunggetCreationHelper().createFormulaEvaluator() Methode. Auf diese Weise wird Ihr Code nicht mit der Klasse HSSFFormulaEvaluator gekoppelt. Vitor Santos
4

Versuchen:

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

Sollte die Nummer korrekt formatieren.

Soweit ich weiß, möchte der Fragesteller unterscheiden können2 und2.0. Ihre Lösung würde dies nicht tun. (Willkommen bei Stack Overflow!) Paŭlo Ebermann
24

Ich würde den folgenden Ansatz empfehlen, wenn das Ändern des Zelltyps unerwünscht ist:

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

NumberToTextConverter kann doppelte Werte unter Verwendung der Excel-Regeln ohne Genauigkeitsverlust korrekt in einen Text konvertieren.

0

Ich hatte auch ein ähnliches Problem bei einem Datensatz mit Tausenden von Zahlen, und ich glaube, ich habe einen einfachen Weg gefunden, es zu lösen. Ich musste den Apostroph vor einer Zahl einfügen lassen, damit ein separater DB-Import die Zahlen immer als Text sieht. Davor würde die Nummer 8 als 8.0 importiert.

Lösung:

Behalten Sie die gesamte Formatierung als "Allgemein" bei.Hier gehe ich davon aus, dass Zahlen in Spalte A ab Zeile 1 gespeichert sind.Tragen Sie das 'in Spalte B ein und kopieren Sie so viele Zeilen wie nötig. Im Arbeitsblatt wird nichts angezeigt. Wenn Sie jedoch auf die Zelle klicken, wird der Apostophe in der Formelleiste angezeigt.In Spalte C: = B1 & A1.Wählen Sie alle Zellen in Spalte C aus, und fügen Sie mit der Option "Werte" einen Spezialeintrag in Spalte D ein.

Hey Presto alle Nummern aber als Text gespeichert.

86

Ich glaube nicht, dass wir diese Klasse hatten, als Sie die Frage stellten, aber heute gibt es eine einfache Antwort.

Was Sie tun möchten, ist dieDataFormatter-Klasse. Sie übergeben dies eine Zelle, und es ist am besten, Ihnen eine Zeichenfolge zurückzugeben, die enthält, was Excel Ihnen für diese Zelle anzeigen würde. Wenn Sie eine String-Zelle übergeben, erhalten Sie den String zurück. Wenn Sie eine numerische Zelle mit angewendeten Formatierungsregeln übergeben, formatiert sie die Zahl basierend auf diesen und gibt Ihnen die Zeichenfolge zurück.

In Ihrem Fall würde ich davon ausgehen, dass auf die numerischen Zellen eine ganzzahlige Formatierungsregel angewendet wird. Wenn Sie DataFormatter auffordern, diese Zellen zu formatieren, erhalten Sie eine Zeichenfolge mit der darin enthaltenen Ganzzahl.

Beachten Sie auch, dass viele Leute dies vorschlagencell.setCellType(Cell.CELL_TYPE_STRING), aber dieApache POI JavaDocs geben ganz klar an, dass Sie dies nicht tun sollten! Das machensetCellType Der Aufruf verliert die Formatierung, da dieJavadocs erklären Die einzige Möglichkeit zum Konvertieren in einen String mit verbleibender Formatierung ist die Verwendung vonDataFormatter-Klasse.

Der Datenformatierer scheint nicht für Formelzellen zu funktionieren, sondern gibt eine Zeichenfolgendarstellung der Formel anstelle des Werts zurück gaurav5430
Nur eine kleine Anmerkung: Bitte geben Sie kurze Code-Schnipsel für solche Antworten an, auch wenn diese in den bereitgestellten Links angegeben sind BAERUS
@ gaurav5430 Ja, es passt nicht zu Formeln ... Laut 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
Danke @Gagravarr, nur deine Antwort funktioniert für mich, <code> cell.setCellType (Cell.CELL_TYPE_STRING); <code> konvertiert den 2.2-Wert als 2.2000000000000002, aber ich möchte 2.2. es gibt alles im string format zurück danke ankush yadav
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

Solange die Zelle im Textformat vorliegt, bevor der Benutzer die Nummer eingibt, können Sie mit dem POI den Wert als Zeichenfolge abrufen. Ein Schlüssel ist, dass, wenn sich in der oberen linken Ecke der Zelle ein kleines grünes Dreieck befindet, das als Text formatiert ist, Sie den Wert als Zeichenfolge abrufen können (das grüne Dreieck wird angezeigt, wenn etwas als Zahl erscheint) wird in ein Textformat gezwungen). Wenn Sie Zellen im Textformat haben, die Zahlen enthalten, mit dem POI diese Werte jedoch nicht als Zeichenfolgen abgerufen werden können, können Sie die Daten der Kalkulationstabelle folgendermaßen bearbeiten:

Doppelklicken Sie auf die Zelle, sodass sich der Bearbeitungscursor in der Zelle befindet, und klicken Sie dann auf die Eingabetaste (dies kann jeweils nur für eine Zelle erfolgen).Verwenden Sie die Excel 2007-Textkonvertierungsfunktion (die für mehrere Zellen gleichzeitig ausgeführt werden kann).Schneiden Sie die fehlerhaften Werte an einer anderen Stelle aus, formatieren Sie die Tabellenzellen als Text und fügen Sie die zuvor ausgeschnittenen Werte erneut als einUnformatierte Werte zurück in den richtigen Bereich.

Als letztes können Sie Folgendes tun: Wenn Sie mit dem POI Daten aus einer Excel 2007-Tabelle abrufen, können Sie die Methode 'getRawValue ()' der Cell-Klasse verwenden. Dies ist egal, was das Format ist. Es wird einfach eine Zeichenfolge mit den Rohdaten zurückgegeben.

0

Viele dieser Antworten beziehen sich auf alte POI-Dokumentationen und -Klassen. Im neuesten POI 3.16Zelle mit den Int-Typen wurde veraltet

Cell.CELL_TYPE_STRING

Stattdessen dieCellType-Aufzählung kann verwendet werden.

CellType.STRING 

Stellen Sie einfach sicher, dass Sie Ihr pom mit der poi-Abhängigkeit sowie der poi-ooxml-Abhängigkeit auf die neue 3.16-Version aktualisieren, da sonst weiterhin Ausnahmen auftreten. Ein Vorteil dieser Version ist, dass Sie den Zelltyp zum Zeitpunkt der Erstellung der Zelle angeben können, ohne die in den vorherigen Antworten beschriebenen zusätzlichen Schritte ausführen zu müssen:

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

Steuern Sie das Excel-Arbeitsblatt trotzdem? Gibt es eine Vorlage, die die Benutzer für die Eingabe haben? In diesem Fall können Sie die Eingabezellen im Code formatieren.

Nein, das ist unmöglich ... Sie erstellen xls selbst ... joycollector
292

Ich hatte das gleiche problem Ich tatcell.setCellType(Cell.CELL_TYPE_STRING); vor dem Lesen des Zeichenfolgenwerts, wodurch das Problem unabhängig von der Formatierung der Zelle durch den Benutzer behoben wurde.

Diese Antwort sollte eindeutig herabgesetzt und / oder entfernt werden, da sie falsch ist. maxxyme
Ich frage mich, ob dieses Konto für die Formatierung verwendet wird. Wenn die Excel-Datei immer bis zu 2 Dezimalstellen enthält, ist der Zeichenfolgenwert dann genau gleich? ryvantage
@Wil cell.setCellType (Cell.CELL_TYPE_STRING); Funktioniert nicht für XLSX-Blätter. Irgendeine andere Lösung dafür? Meenaxi
Hervorragende Lösung. Ich verwende Version 3.14 und für diese cell.setCellType (XSSFCell.CELL_TYPE_STRING); wird Werke sein Harsha
15

Wie bereits in den JavaDocs von Poi erwähnt (https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#setCellType%28int%29) benutze nicht:

cell.setCellType(Cell.CELL_TYPE_STRING);

aber benutze:

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

Weitere Beispiele aufhttp://massapi.com/class/da/DataFormatter.html

-1

Wir hatten das gleiche Problem und haben unsere Benutzer gezwungen, die Zellen als "Text" zu formatieren.Vor Eingabe des Wertes. Auf diese Weise speichert Excel gerade Zahlen korrekt als Text. Wenn das Format danach geändert wird, ändert Excel nur die Art und Weise, wie der Wert angezeigt wird, ändert jedoch nicht die Art und Weise, wie der Wert gespeichert wird, es sei denn, der Wert wird erneut eingegeben (z. B. durch Drücken der Eingabetaste in der Zelle).

Ob Excel den Wert korrekt als Text gespeichert hat oder nicht, wird durch das kleine grüne Dreieck angezeigt, das Excel in der linken oberen Ecke der Zelle anzeigt, wenn es denkt, dass die Zelle eine Zahl enthält, aber als Text formatiert ist.

Habe auch das Problem gehabt Romain Hippeau
-1

umgewandelt in ein int dann mache a.toString(). Es ist hässlich, aber es funktioniert.

Das Problem ist, dass wenn es 2.0 in A2 gibt, ich den String "2.0" bekommen muss, und wenn 2 dann den String "2". joycollector

Verwandte Fragen