2016-03-28 5 views
1

Ich arbeite an einer Funktion, wo ich Nummern gespeichert über eine Excel-Datei hochladen muss. Es ist in Java geschrieben, mit Apache Poi-Bibliothek, unter Spring-Framework (was irrelevant ist).Apache POI liest Textspalte als numerisch

Die Datei, die ich (Beachten Sie, dass die Spalte bereits auf Text eingestellt wurde) zu laden bin versucht:

enter image description here

-Code ist wie folgt:

// function accepts "MultipartFile inputFile" 
InputStream is = inputFile.getInputStream(); 
StreamingReader reader = StreamingReader.builder().rowCacheSize(100).bufferSize(4096).sheetIndex(0) 
         .read(is); 
for (Row row : reader) { 
    System.out.println("Reading next row."); 
    System.out.println("row[0] is of type " + row.getCell(0).getCellType()); 
    Cell cell = row.getCell(0); 
    String value = ""; 
    if (cell.getCellType() == Cell.CELL_TYPE_STRING) { 
     value = cell.getStringCellValue().replaceAll("[\\D]", ""); 
    } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) { 
     value = NumberToTextConverter.toText(cell.getNumericCellValue()); 
    } 
    System.out.println("Value is " + value); 
} 

Und ich m unter Ausgabe bekommen:

Reading next row. 
row[0] is of type 0 // Which is equals to Cell.CELL_TYPE_NUMERIC 
Value is 166609647 

I ssue ist, dass ich es als '0166609647' anstelle von '166609647' lesen müsste, komischerweise passiert dies nur mit xlsx-Datei, wenn ich es als XLS-Format speichern und die Datei erneut hochladen, habe ich kein Problem mit der Erkennung seiner Zelltyp. Irgendwelche Ideen?

Herausgegeben für die Vervielfältigung markiert werden:

  • Gegeben Antwort https://stackoverflow.com/a/19401902/1131470 DataFormatter-Klasse verwendet, die nicht unterstützt wird, wenn wir das Blatt strömen, wie das Objekt Handy abgerufen wird ein StreamingCell Objekt sein, die löst eine Ausnahme aus, wenn wir die Funktion getCellStyle() aufrufen.

Ab dem 29. Mar 2016

Es scheint, dass die Klasse StreamingCell nicht DataFormatter nicht unterstützt, wo DataFormatter die einzige Klasse im Moment zur Verfügung steht, was Excel zeigt zu greifen. Die aktuelle Lösung würde also darin bestehen, die gesamte Excel-Datei in den Speicher einzulesen. Wenn jemand in Zukunft eine Antwort finden sollte, könntest du bitte eine Antwort hier posten, ich würde das sehr schätzen, da die derzeitige Lösung eine absolut schreckliche Lösung ist.

Zum 31. Mar 2016

Besonderen Dank geht an Axel, der seine Bibliothek Version Ausgabe darauf hingewiesen, Streamer JAR-Datei 0.2.12 Aktualisierung löst das Problem. Vielen Dank!

+0

Ich vermute, dass es an der https://github.com/monitorjbl/excel-streaming-reader liegen. Stellen Sie also sicher, dass Sie die neueste Version verwenden. –

+0

@AxelRichter Vielen Dank für den Hinweis, ja, wenn ich in die Klasse von StreamingCell schaue https://github.com/monitorjbl/excel-streaming-reader/blob/master/src/main/java/com/monitorjbl /xlsx/impl/StreamingCell.java, scheint es, dass die meisten Funktionen UnsupportedException werfen. Keine Wahl, aber ich müsste wieder die gesamte Datei lesen und dabei die Upload-Größe begrenzen. –

+0

Was Sie sagen, kann nicht wahr sein. Wenn die Zelle als 'Text' formatiert ist, dann ist der Typ der Zelle bei OpenXML 't =" s "' und der Wert der Zelle zeigt auf 'sharedStrings.xml'. So kann 'row.getCell (0) .getCellType()' nicht 0 sein und der Wert kann nicht 166609647 sein. Das kann nur sein, wenn die Zelle ** nicht ** als 'Text' formatiert ist. Dann und nur dann würden Sie einen Formatierer benötigen. –

Antwort

2

Ihre Datei heruntergeladen. xlsx-streamer-0.2.12.jar, slf4j-api-1.7.20.jar und slf4j-nop-1.7.20.jar heruntergeladen und im Klassenpfad abgelegt.

Mit folgendem Code:

import com.monitorjbl.xlsx.*; 
import org.apache.poi.ss.usermodel.*; 

import java.io.*; 

class StreamingReaderTest { 

public static void main(String[] args) throws Exception { 

    try (
    InputStream is = new FileInputStream(new File("/home/axel/Downloads/test_formatted_number.xlsx")); 
    StreamingReader reader = StreamingReader.builder() 
      .rowCacheSize(100) 
      .bufferSize(4096) 
      .sheetIndex(0) 
      .read(is); 
) { 
    for (Row row : reader) { 
    System.out.println("row[0] is of type " + row.getCell(0).getCellType()); 
    Cell cell = row.getCell(0); 
    String value = ""; 
    if (cell.getCellType() == Cell.CELL_TYPE_STRING) { 
     value = cell.getStringCellValue(); 
    } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) { 
     value = "" + cell.getNumericCellValue(); 
    } 
    System.out.println("Value is " + value); 
    } 
    } 
} 
} 

Gebe ich:

enter image description here

Also hier kein Problem.

Wenn ich DataFormatter mit numerischen Zellenwerte:

import com.monitorjbl.xlsx.*; 
import org.apache.poi.ss.usermodel.*; 

import java.io.*; 

class StreamingReaderTest { 

public static void main(String[] args) throws Exception { 

    try (
    InputStream is = new FileInputStream(new File("/home/axel/Downloads/test_formatted_number.xlsx")); 
    StreamingReader reader = StreamingReader.builder() 
      .rowCacheSize(100) 
      .bufferSize(4096) 
      .sheetIndex(0) 
      .read(is); 
) { 
    for (Row row : reader) { 
    System.out.println("row[0] is of type " + row.getCell(0).getCellType()); 
    Cell cell = row.getCell(0); 
    String value = ""; 
    if (cell.getCellType() == Cell.CELL_TYPE_STRING) { 
     value = cell.getStringCellValue(); 
    } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) { 
     value = new DataFormatter().formatCellValue(cell); 
    } 
    System.out.println("Value is " + value); 
    } 
    } 
} 
} 

und beziffern die Zahl 166.609.647 in A2 als 0000000000 formatiert. Ich bekomme dann:

enter image description here

+0

Wow, absolut genial, lass mich später mit deiner Version der Streamer-Jar-Datei versuchen, hoffe, es würde mein Problem lösen. –

+0

Es war in der Tat Versionsproblem. Mein Projekt verwendete eine veraltete Version 0.2.3, die Aktualisierung löst mein Problem sofort, danke! –

0

Warum .replaceAll ("[\ D]", "");

Funktioniert gut für mich, nur versucht. Frage mich, was das Problem hier ist.

fis = new FileInputStream(inputFile); 
XSSFWorkbook inputWorkBook = new XSSFWorkbook (fis); 
XSSFSheet inputSheet = inputWorkBook.getSheetAt(0); 
Iterator<Row> rowIterator = inputSheet.iterator(); 

while(rowIterator.hasNext()) 
{ 
    Row row = rowIterator.next(); 
    Iterator<Cell> cellIterator = row.cellIterator(); 

    while (cellIterator.hasNext()) 
    { 
     Cell cell = cellIterator.next(); 

     switch (cell.getCellType()) 
     { 
      case Cell.CELL_TYPE_STRING: 
       System.out.print(cell.getStringCellValue() + "\t"); 
       break; 
      case Cell.CELL_TYPE_NUMERIC: 
       System.out.print(cell.getNumericCellValue() + "\t"); 
       break; 
      case Cell.CELL_TYPE_BOOLEAN: 
       System.out.print(cell.getBooleanCellValue() + "\t"); 
       break; 
      default : 
     } 
    } 
    System.out.println(""); 
} 
+0

Äh, vielen Dank, dass du auf die seltsamen Sachen hingewiesen hast =) aber egal, was meine Frage betrifft, werde ich es einfach im Moment lassen. –

+0

Hallo, vielen Dank nochmal für die Mühe und Entschuldigung in der Frage nicht sehr klar. Wenn ich eine XLS-Datei akzeptiere, würde ich den ähnlichen Ansatz verwenden, um die Datei zu verarbeiten, und wenn ich das tue, erscheint '0166609647' in Ordnung. Das Problem tritt auf, wenn ich die XLSX-Datei akzeptiere, die extrem groß sein kann, daher wird Streaming bevorzugt, anstatt die ganze Datei in den Speicher zu schreiben, und das ist der Punkt, an dem das Problem auftritt. –

+0

Ich habe den Teil hinzugefügt, auf dem ich das Streaming-Objekt auf meiner Frage deklariere, du hast es nochmal dort angeschaut. –