Pergunta sobre apache-poi, excel, java – Como posso ler cadeias numéricas em células do Excel como string (não números)?

130

Eu tenho o arquivo excel com esse conteúdo:

A1: SomeString

A2: 2

Todos os campos estão configurados para o formato String.

Quando eu leio o arquivo em java usando o POI, ele diz que A2 está no formato de célula numérica.

O problema é que o valor em A2 pode ser 2 ou 2.0 (e eu quero ser capaz de distingui-los), então não posso simplesmente usar.toString().

O que posso fazer para ler o valor como string?

Sua resposta

20   a resposta
292

Eu tive o mesmo problema. eu fizcell.setCellType(Cell.CELL_TYPE_STRING); antes de ler o valor da string, que resolveu o problema, independentemente de como o usuário formatou a célula.

@Wil cell.setCellType (Cell.CELL_TYPE_STRING); não funciona para folha .xlsx. Alguma outra solução para isso? Meenaxi
Essa resposta deve ser claramente degradada e / ou removida, pois está incorreta. maxxyme
Use o DataFormatter. O Javadoc nos adverte de usar o método acima. Balu SKT
Note que oApache POI javadocs explicitamente dizem para não fazer isso! Como eles explicam, você deve usar o DataFormatter Gagravarr
-1

Você controla a planilha do excel de qualquer maneira? Existe um modelo que os usuários têm para lhe dar a entrada? Nesse caso, você pode ter o formato de código das células de entrada para você.

Não. Isso é impossível ... Eles criam os próprios xls ... joycollector
0

Eu também tive um problema semelhante em um conjunto de dados de milhares de números e acho que encontrei uma maneira simples de resolver. Eu precisava inserir o apóstrofo antes de um número, para que uma importação separada do DB sempre visse os números como texto. Antes disso, o número 8 seria importado como 8.0.

Solução:

Mantenha toda a formatação como Geral.Aqui estou assumindo números são armazenados na coluna A começando na linha 1.Coloque na coluna Coluna B e copie quantas linhas forem necessárias. Nada aparece na planilha, mas clicando na célula você pode ver o apostolado na barra de Fórmula.Na Coluna C: = B1 e A1.Selecione todas as Células na Coluna C e faça um Colar Especial na Coluna D usando a opção Valores.

Hey Presto todos os números, mas armazenados como texto.

24

Eu recomendaria a seguinte abordagem quando modificar o tipo de célula é indesejável:

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

NumberToTextConverter pode converter corretamente o valor duplo para um texto usando as regras do Excel sem perda de precisão.

0

Quando lemos o valor da célula numérica do MS Excel usando a biblioteca do Apache POI, ele a leu como numérica. Mas às vezes queremos que ele leia como string (por exemplo, números de telefone, etc.). Foi assim que eu fiz:

Insira uma nova coluna com a primeira célula = CONCATENATE ("!", D2). Presumo que D2 seja o ID da célula da coluna do seu número de telefone. Arraste a nova célula até o final.

Agora, se você ler a célula usando POI, ela lerá a fórmula em vez do valor calculado. Agora faça o seguinte:

Adicione outra coluna

Selecione a coluna completa criada no passo 1. e escolha Editar-> COPY

Ir para o topo da coluna da coluna criada no passo 3. e Selecione Editar-> Colar Especial

Na janela aberta, selecione o botão de opção "Valores"

Selecione "OK"

Agora leia usando a API de POI ... depois de ler em Java ... apenas remova o primeiro caractere, ou seja, "!"

Sua solução parece não ser utilizável se você não produzir os arquivos do Excel, é? (Além disso, você poderia colocar um extrato em sua resposta? Não é tão longo.) Paŭlo Ebermann
Sim, não pode ser usado quando não se está produzindo o arquivo excel. Asif Shahzad
44

O código abaixo funcionou para mim para qualquer tipo de célula.

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

}
Esta deve ser a resposta aceita. Obrigado @Vinayak Phas1c
a chamada para objFormulaEvaluator.evaluate não é necessária. O valor de retorno disso não está sendo usado aqui. Radu Simionescu
Trabalhou muito bem! Minha sugestão seria mudar a forma como o FormulaEvaluator é recuperado. A classe Workbook fornece um avaliador de fórmulas emboragetCreationHelper().createFormulaEvaluator() método. Dessa forma, seu código não será acoplado à classe HSSFFormulaEvaluator. Vitor Santos
podeFormulaEvaluator simplesmente ser removido desta solução? Isso serve a um propósito? P.Brian.Mackey
1

Desde que a célula esteja em formato de texto antes de o usuário digitar o número, o POI permitirá que você obtenha o valor como uma string. Uma chave é que, se houver um pequeno triângulo verde no canto superior esquerdo da célula formatada como Texto, você poderá recuperar seu valor como uma string (o triângulo verde aparece sempre que algo parece ser um número é coagido para um formato de texto). Se você tiver células formatadas em texto que contenham números, mas o POI não permitirá que você obtenha esses valores como sequências, há algumas coisas que você pode fazer nos dados da planilha para permitir que:

Clique duas vezes na célula para que o cursor de edição esteja presente dentro da célula e, em seguida, clique em Enter (que pode ser feito apenas uma célula de cada vez).Use a função de conversão de texto do Excel 2007 (que pode ser feita em várias células ao mesmo tempo).Recorte os valores incorretos para outro local, reformate as células da planilha como texto e repita os valores recortados anteriormente comoValores não formatados de volta para a área apropriada.

Uma última coisa que você pode fazer é que, se estiver usando o POI para obter dados de uma planilha do Excel 2007, você pode usar o método 'getRawValue ()' da classe Cell. Isso não importa qual seja o formato. Ele simplesmente retornará uma string com os dados brutos.

-1

Isso funcionou perfeito para mim.

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

Experimentar:

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

Deve formatar o número corretamente.

Pelo que entendi, o consulente quer ser capaz de distinguir entre2 e2.0. Sua solução não faria isso. (Mas ainda assim, bem-vindo ao Stack Overflow!) Paŭlo Ebermann
0

Muitas destas respostas fazem referência a documentação e classes de POI antigas. No mais novo POI 3.16,Célula com os tipos int foi descontinuado

Cell.CELL_TYPE_STRING

Em vez dissoEnum CellType pode ser usado.

CellType.STRING 

Apenas certifique-se de atualizar seu pom com a dependência poi, bem como a dependência poi-ooxml para a nova versão 3.16, caso contrário, você continuará recebendo exceções. Uma vantagem dessa versão é que você pode especificar o tipo de célula no momento em que a célula é criada, eliminando todas as etapas adicionais descritas nas respostas anteriores:

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

cell.setCellType (Cell.CELL_TYPE_STRING); está funcionando bem para mim

5

Sim, isso funciona perfeitamente

recomendado:

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

velho:

cell.setCellType(Cell.CELL_TYPE_STRING);

mesmo se você tiver um problema com a recuperação de um valor decell tendo fórmula, ainda isso funciona.

velho deveria estarerrado MiXT4PE
oApache POI javadocs são muito claros que você não deveria estar fazendo assim: Se o que você deseja fazer é obter um valor String para sua célula numérica, pare !. Esta não é a maneira de fazê-lo. Em vez disso, para buscar o valor da string de uma célula numérica ou booleana ou data, use DataFormatter. Gagravarr
Mas você tem que ter cuidado ao usar isso para valores duplos. Para mim, transformou o valor 7,9 em 7,8999956589965 ... Chris
0

getStringCellValue retorna NumberFormatException se o tipo de célula for numérico. Se você não quiser alterar o tipo de célula para string, você pode fazer isso.

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

Nós tivemos o mesmo problema e forçamos nossos usuários a formatar as células como 'texto'antes inserindo o valor. Dessa forma, o Excel armazena corretamente números pares como texto. Se o formato for alterado posteriormente, o Excel apenas altera a maneira como o valor é exibido, mas não altera a maneira como o valor é armazenado, a menos que o valor seja inserido novamente (por exemplo, pressionando-se retornar quando na célula).

Se o Excel armazenou corretamente o valor como texto é indicado pelo pequeno triângulo verde exibido no canto superior esquerdo da célula se ele acha que a célula contém um número, mas é formatado como texto.

Também tive o problema Romain Hippeau
86

Eu não acho que nós tivemos essa aula de volta quando você fez a pergunta, mas hoje há uma resposta fácil.

O que você quer fazer é usar oClasse DataFormatter. Você passa essa célula e faz o possível para retornar uma string contendo o que o Excel mostraria para essa célula. Se você passar uma célula de string, você receberá a string de volta. Se você passar uma célula numérica com as regras de formatação aplicadas, ela formatará o número com base nelas e retornará a string.

Para o seu caso, eu diria que as células numéricas têm uma regra de formatação de número inteiro aplicada a elas. Se você pedir ao DataFormatter para formatar essas células, ele retornará uma string com a string inteira nela.

Além disso, observe que muitas pessoas sugerem fazercell.setCellType(Cell.CELL_TYPE_STRING), mas oApache POI JavaDocs afirmam claramente que você não deve fazer isso! Fazendo osetCellType chamada perderá formatação, como ojavadocs explicam a única maneira de converter para uma String com formatação restante é usar oClasse DataFormatter.

formatformatter não parece funcionar para células de fórmula, ele retorna uma representação de seqüência de caracteres da fórmula em vez do valor gaurav5430
Obrigado @Gagravarr apenas sua resposta funciona para mim, <code> cell.setCellType (Cell.CELL_TYPE_STRING); <code> em converter o valor 2.2 como 2.2000000000000002, mas eu quero 2.2. ele retorna qualquer coisa em formato de cadeia de agradecimento ankush yadav
@ gaurav5430 Sim, não vai bem com fórmulas ... Segundo o 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
Apenas uma nota menor: forneça snippets de código curtos para essas respostas, também se essas forem mencionadas nos links fornecidos BAERUS
15

Como já mencionado nos JavaDocs do Poi (https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#setCellType%28int%29) não use:

cell.setCellType(Cell.CELL_TYPE_STRING);

mas use:

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

Mais exemplos emhttp://massapi.com/class/da/DataFormatter.html

0

Eu prefiro muito mais seguir a rota da resposta do wil ou Vinayak Dornala, infelizmente eles afetaram muito meu desempenho. Eu fui por umHACKY solução de casting implícito:

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

Eu não sugiro que você faça isso, pois minha situação funcionou devido à natureza de como o sistema funcionava e eu tinha uma fonte confiável de arquivos.

Nota de rodapé: numericColumn É um int gerado a partir da leitura do cabeçalho do arquivo processado.

-1

Parece que isto não pode ser feito na versão atual do POI, com base no fato de que este bug:

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

ainda está pendente.

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

Eu tentei isso e funcionou para mim

-1

lançar a um int, em seguida, fazer um.toString(). É feio mas funciona.

O problema é que, se houver 2.0 em A2, eu preciso pegar a string "2.0", e se 2, em seguida, string "2". joycollector

Perguntas relacionadas