Come posso leggere stringhe numeriche nelle celle di Excel come stringa (non numeri)?


146
  1. Ho un file Excel con tali contenuti:

    • A1: SomeString

    • A2: 2

    Tutti i campi sono impostati sul formato stringa.

  2. Quando leggo il file in java usando POI, mi dice che A2 è in formato cella numerico.

  3. Il problema è che il valore in A2 può essere 2 o 2.0 (e voglio essere in grado di distinguerli) quindi non posso semplicemente usarlo .toString().

Cosa posso fare per leggere il valore come stringa?

Risposte:


319

Ho avuto lo stesso problema. Ho fatto cell.setCellType(Cell.CELL_TYPE_STRING);prima di leggere il valore della stringa, che ha risolto il problema indipendentemente da come l'utente ha formattato la cella.


Uso poi-3.8-beta4 e funziona come previsto! Perché TS non lo accetta come risposta?
swdev,

Tenere presente che la conversione da POI numerica a stringa non tiene conto delle impostazioni internazionali del sistema, ma utilizza sempre il punto come separatore decimale. Ad esempio, se il sistema utilizza "," e in Excel i numeri sembrano "1,9", il PDI restituirà invece "1,9".
Alexey Berezkin,

53
Nota che i javadocs PDI di Apache dichiarano esplicitamente di non farlo! Come spiegano, dovresti usare DataFormatter invece
Gagravarr

6
L'avvertimento di Gagravarr di non farlo è giusto! Dai documenti: "Se quello che vuoi fare è ottenere un valore String per la tua cella numerica, fermati !. Questo non è il modo di farlo. Invece, per recuperare il valore stringa di una cella numerica o booleana o data, usa DataFormatter invece. " poi.apache.org/apidocs/org/apache/poi/ss/usermodel/… Stavo usando questa tecnica da solo fino a quando non ho finito per cambiare accidentalmente i dati che non intendevo cambiare. (Imposta il tipo su String, leggi il valore, riporta il tipo su numerico, leggi di nuovo e ottieni un altro valore numerico!)
Chris Finley

6
Usa DataFormatter. Javadoc ci avverte di usare il metodo sopra.
Balu SKT,

96

Non credo che abbiamo avuto questa lezione quando hai posto la domanda, ma oggi c'è una risposta facile.

Quello che vuoi fare è usare la classe DataFormatter . Passa questa cella e fa del suo meglio per restituirti una stringa contenente ciò che Excel ti mostrerà per quella cella. Se le passi una cella stringa, la stringa verrà restituita. Se le passi una cella numerica con le regole di formattazione applicate, formatterà il numero in base a esse e ti restituirà la stringa.

Nel tuo caso, suppongo che alle celle numeriche sia stata applicata una regola di formattazione intera. Se chiedi a DataFormatter di formattare quelle celle, ti restituirà una stringa con la stringa intera al suo interno.

Inoltre, nota che molte persone suggeriscono di farlo cell.setCellType(Cell.CELL_TYPE_STRING), ma i POI JavaDocs di Apache dichiarano chiaramente che non dovresti farlo ! Effettuare la setCellTypechiamata perderà la formattazione, poiché i javadocs spiegano che l'unico modo per convertire in una stringa con la formattazione rimanente è utilizzare la classe DataFormatter .


Grazie a @Gagravarr solo la tua risposta funziona per me, <code> cell.setCellType (Cell.CELL_TYPE_STRING); <code> nel convertire il valore 2.2 in 2.200000000000000002, ma voglio 2.2. restituisce qualsiasi cosa in formato stringa, grazie
ankush yadav,

dataformatter non sembra funzionare per le celle Formula, restituisce una rappresentazione in formato stringa della formula anziché il valore
gaurav5430

1
Solo una nota minore: fornire snippet di codici brevi per tali risposte, anche se sono indicati nei collegamenti forniti
BAERUS

@ gaurav5430 Sì, non va bene con le formule ... Secondo il documento,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

Il codice seguente ha funzionato per me per qualsiasi tipo di cella.

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
Ha funzionato bene! Il mio suggerimento sarebbe di cambiare il modo in cui viene recuperato il FormulaEvaluator. La classe Workbook fornisce un analizzatore di formule tramite il getCreationHelper().createFormulaEvaluator()metodo. In questo modo il codice non verrà associato alla classe HSSFFormulaEvaluator.
Vitor Santos,

Questa dovrebbe essere la risposta accettata. Grazie @Vinayak
Phas1c,

Può FormulaEvaluatoressere semplicemente rimosso da questa soluzione? Serve a uno scopo?
P.Brian.Mackey,

1
la chiamata a objFormulaEvaluator.evaluate non è necessaria. Il valore restituito non viene utilizzato qui.
Radu Simionescu,

32

Consiglierei il seguente approccio quando si desidera modificare il tipo di cella:

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

NumberToTextConverter può convertire correttamente il doppio valore in un testo usando le regole di Excel senza perdita di precisione.


Consiglio davvero eccitante! Grazie! Permette di ottenere valori non convertiti in contrasto con l'impostazione di cellType su String.
Gleb Egunov,

Ricevo 44007 come output per un valore di cella di 25/06/2020. Che cosa sto facendo di sbagliato?
Vinay,


10

Sì, funziona perfettamente

consigliato:

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

vecchio:

cell.setCellType(Cell.CELL_TYPE_STRING);

anche se hai un problema con il recupero di un valore dalla cellformula, funziona comunque.


5
Ma devi stare attento usando questo per doppi valori. Per me ha trasformato il valore 7,9 in 7,8999956589965 ...
Chris

2
I javadocs dei POI di Apache sono molto chiari sul fatto che non dovresti farlo in questo modo : se quello che vuoi fare è ottenere un valore String per la tua cella numerica, fermati !. Questo non è il modo di farlo. Invece, per recuperare il valore di stringa di una cella numerica, booleana o di data, utilizzare DataFormatter.
Gagravarr,

4

Provare:

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

Dovrebbe formattare il numero correttamente.


A quanto ho capito, il richiedente vuole essere in grado di distinguere tra 2e 2.0. La tua soluzione non lo farebbe. (Ma comunque, benvenuto in Stack Overflow!)
Paŭlo Ebermann,

1

Finché la cella è in formato testo prima che l'utente digiti il ​​numero, il PDI ti consentirà di ottenere il valore come stringa. Una chiave è che se c'è un piccolo triangolo verde nell'angolo in alto a sinistra della cella formattato come Testo, sarai in grado di recuperare il suo valore come una stringa (il triangolo verde appare ogni volta che qualcosa che sembra essere un numero è costretto in un formato di testo). Se hai celle in formato testo che contengono numeri, ma il PDI non ti consente di recuperare quei valori come stringhe, ci sono alcune cose che puoi fare sui dati del foglio di calcolo per consentire che:

  • Fare doppio clic sulla cella in modo che il cursore di modifica sia presente all'interno della cella, quindi fare clic su Invio (che può essere eseguito solo una cella alla volta).
  • Utilizzare la funzione di conversione del testo di Excel 2007 (che può essere eseguita su più celle contemporaneamente).
  • Taglia i valori offensivi in ​​un'altra posizione, riformatta le celle del foglio di calcolo come testo, quindi reinvia i valori precedentemente tagliati come Valori non formattati nell'area corretta.

Un'ultima cosa che puoi fare è che se stai usando POI per ottenere dati da un foglio di calcolo Excel 2007, puoi il metodo 'getRawValue ()' della classe Cell. Questo non importa quale sia il formato. Restituirà semplicemente una stringa con i dati grezzi.


0

Quando leggiamo il valore della cella numerica di MS Excel utilizzando la libreria POI di Apache, viene letto come numerico. Ma a volte vogliamo che legga come stringa (ad esempio numeri di telefono, ecc.). Ecco come l'ho fatto:

  1. Inserisci una nuova colonna con la prima cella = CONCATENATE ("!", D2). Suppongo che D2 sia l'id della colonna del tuo numero di telefono. Trascina la nuova cella fino alla fine.

  2. Ora se leggi la cella utilizzando PDI, leggerà la formula anziché il valore calcolato. Ora fai quanto segue:

  3. Aggiungi un'altra colonna

  4. Seleziona la colonna completa creata nel passaggio 1. e scegli Modifica-> COPIA

  5. Vai all'inizio della cella della colonna creata al passaggio 3. e seleziona Modifica-> Incolla speciale

  6. Nella finestra aperta, selezionare il pulsante di opzione "Valori"

  7. Seleziona "OK"

  8. Ora leggi usando l'API POI ... dopo aver letto in Java ... basta rimuovere il primo carattere cioè "!"


La tua soluzione sembra non essere utilizzabile se non si producono i file Excel da soli, vero? (Inoltre, potresti inserire un estratto nella tua risposta? Non è così lungo.)
Paŭlo Ebermann,

Sì, non può essere usato quando non si produce da soli il file Excel.
Asif Shahzad,

0

Ho anche avuto un problema simile su un set di dati di migliaia di numeri e penso di aver trovato un modo semplice per risolvere. Avevo bisogno di inserire l'apostrofo prima di un numero in modo che un'importazione DB separata vedesse sempre i numeri come testo. Prima di questo il numero 8 sarebbe stato importato come 8.0.

Soluzione:

  • Mantieni tutta la formattazione come Generale.
  • Qui presumo che i numeri siano memorizzati nella colonna A a partire dalla riga 1.
  • Inserisci "nella colonna B e copia tutte le righe necessarie. Non viene visualizzato nulla nel foglio di lavoro, ma facendo clic sulla cella è possibile vedere l'aptophe nella barra della formula.
  • Nella colonna C: = B1 e A1.
  • Seleziona tutte le celle nella colonna C ed esegui uno speciale Incolla nella colonna D usando l'opzione Valori.

Ehi Presto, tutti i numeri, ma memorizzati come testo.


0

getStringCellValue restituisce NumberFormatException se il tipo di cella è numerico. Se non vuoi cambiare il tipo di cella in stringa, puoi farlo.

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

0

Molte di queste risposte fanno riferimento alla vecchia documentazione e classi di POI. Nel PDI 3.16 più recente, Cella con i tipi int è stata deprecata

Cell.CELL_TYPE_STRING

inserisci qui la descrizione dell'immagine

Invece è possibile utilizzare l' enum CellType .

CellType.STRING 

Assicurati di aggiornare il tuo pom con la dipendenza poi così come la dipendenza poi-ooxml alla nuova versione 3.16, altrimenti continuerai a ricevere eccezioni. Un vantaggio con questa versione è che puoi specificare il tipo di cella al momento della creazione della cella eliminando tutti i passaggi aggiuntivi descritti nelle risposte precedenti:

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

0

Preferirei di gran lunga seguire la strada della risposta del wil o Vinayak Dornala, sfortunatamente hanno influenzato molto la mia performance. Ho scelto una soluzione HACKY per il casting implicito:

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

Non ti consiglio di farlo, per la mia situazione ha funzionato a causa della natura di come funzionava il sistema e avevo una fonte di file affidabile.

Nota a piè di pagina: numericColumn È un int generato dalla lettura dell'intestazione del file elaborato.


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

Ho provato questo e ha funzionato per me


-1

Controlli comunque il foglio di lavoro Excel? C'è un modello che gli utenti hanno per darti l'input? In tal caso, puoi avere il formato del codice per le celle di input per te.




-1

Questo ha funzionato perfettamente per me.

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

-2

Abbiamo avuto lo stesso problema e abbiamo costretto i nostri utenti a formattare le celle come "testo" prima di immettere il valore. In questo modo Excel memorizza correttamente i numeri pari come testo. Se il formato viene successivamente modificato, Excel cambia solo la modalità di visualizzazione del valore ma non cambia la modalità di memorizzazione del valore a meno che il valore non venga nuovamente inserito (ad esempio premendo Invio quando nella cella).

Se Excel ha memorizzato correttamente il valore come testo è indicato dal piccolo triangolo verde che Excel visualizza nell'angolo in alto a sinistra della cella se pensa che la cella contenga un numero ma è formata come testo.


-3

cast a un int quindi fare a .toString(). È brutto ma funziona.


Il problema è che se in A2 è presente 2.0 devo ottenere la stringa "2.0" e se 2 quindi la stringa "2".
joycollector,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.