Question

J'utilise HSSF-POI pour lire des données Excel. Le problème est que j'ai dans une cellule des valeurs qui ressemblent à un nombre mais qui sont en réalité des chaînes. Si je regarde la cellule de format dans Excel, elle indique que le type est "texte". Pourtant, la cellule HSSF pense que c'est numérique. Comment puis-je obtenir la valeur sous forme de chaîne?

Si j'essaie d'utiliser cell.getRichStringValue , j'obtiens une exception. si cell.toString , ce n'est pas exactement la même valeur que dans la feuille Excel.

Modifier : jusqu'à ce que cela soit résolu, je vais utiliser

.
new BigDecimal(cell.getNumericCellValue()).toString()
Était-ce utile?

La solution

Vous voulez dire que HSSF-POI dit

cell.getCellType () == Cell.CELL_TYPE_NUMERIC

PAS

Cell.CELL_TYPE_STRING comme il se doit?

Je pense que c’est un bug dans POI, mais chaque cellule contient un Variant et le Variant a un type. C'est un peu difficile de créer un bogue, alors je pense plutôt qu'Excel utilise des données supplémentaires ou une méthode heuristique pour consigner le champ sous forme de texte. Manière habituelle de la sclérose en plaques, hélas.

P.S. Vous ne pouvez utiliser aucun getString () sur un Variant contenant numérique, car la représentation binaire des données du Variant dépend de son type, et tenter d'obtenir une chaîne à partir de ce qui est en réalité un nombre entraînerait des erreurs - - d’où l’exception.

Autres conseils

La classe que vous recherchez dans les POI est DataFormatter

Lorsque Excel écrit le fichier, certaines cellules sont stockées sous forme de chaînes littérales, tandis que d'autres sont stockées sous forme de nombres. Pour ces derniers, une valeur à virgule flottante représentant la cellule est stockée dans le fichier. Ainsi, lorsque vous demandez à POI la valeur de la cellule, c'est ce qu'elle a réellement.

Parfois, cependant, en particulier lors de l'extraction de texte (mais pas toujours), vous souhaitez que la valeur de la cellule ressemble à ce qu'elle est dans Excel. Il n’est pas toujours possible d’obtenir cela exactement dans une chaîne (un remplissage non plein d’espace par exemple), mais la classe DataFormatter vous rappellera.

Si vous recherchez une chaîne de la cellule qui ressemble beaucoup à Excel, il vous suffit de:

 // Create a formatter, do this once
 DataFormatter formatter = new DataFormatter(Locale.US);

 .....

 for(Cell cell : row) {
     CellReference ref = new CellReference(cell);
     // eg "The value of B12 is 12.4%"
     System.out.println("The value of " + ref.formatAsString() + " is " + formatter.formatCellValue(cell));
 }

Le formateur renvoie les cellules String telles quelles et, pour les cellules numériques, applique les règles de mise en forme du style au numéro de la cellule

Si les documents que vous analysez se trouvent toujours dans une mise en page spécifique, vous pouvez modifier le type de cellule en "chaîne". à la volée, puis récupérez la valeur. Par exemple, si la colonne 2 doit toujours contenir des données de chaîne, définissez son type de cellule sur chaîne, puis lisez-la avec les méthodes get de type chaîne.

cell.setCellType(Cell.CELL_TYPE_STRING);

Lors de mes tests, la modification du type de cellule ne modifiait pas le contenu de la cellule, mais permettait de le récupérer avec l'une des approches suivantes:

cell.getStringCellValue();

cell.getRichStringCellValue().getString();

Sans un exemple de valeur qui ne convertit pas correctement, il est difficile de savoir si cela se comportera différemment de l'approche cell.toString () que vous avez décrite dans la description.

Ce code ci-dessous fonctionne bien pour lire n'importe quel type de cellule mais cette cellule doit contenir une valeur numérique

new BigDecimal(cell.getNumericCellValue()));

par exemple

ase.setGss(new BigDecimal(hssfRow.getCell(3).getNumericCellValue()));

où la variable gss est de type BigDecimal.

Excel convertira tout ce qui ressemble à un nombre ou à une date ou une heure à partir d'une chaîne. Voir article de la base de connaissances MS , qui suggère en principe de saisir le numéro avec un caractère supplémentaire qui le rend une chaîne.

Vous avez probablement un problème avec Excel. Lorsque vous créez la feuille de calcul, le type de cellule par défaut est Générique. Avec ce type, Excel détermine le type en fonction de l’entrée et ce type est enregistré avec chaque cellule.

Lorsque vous modifiez ultérieurement le format de cellule en Texte, vous modifiez simplement le paramètre par défaut. Excel ne change pas automatiquement le type de chaque cellule. Je n'ai pas trouvé le moyen de le faire automatiquement.

Pour le confirmer, vous pouvez accéder à Excel, ressaisir l'un des chiffres et voir s'il s'agit de texte dans HSSF.

Vous pouvez également consulter le type de cellule réel à l'aide de cette fonction,

  @Cell("type", A1)

A1 est la cellule pour le nombre. Il montre " l " pour le texte, " v " pour les nombres.

Le problème avec Excel est que le format par défaut est générique. Avec ce format, Excel enregistre sous forme numérique les nombres entrés dans la cellule. Vous devez modifier le format en texte avant avant d'entrer les valeurs. Réintégrer les valeurs après avoir changé le format fonctionnera également.
Cela conduira à de petits triangles verts dans le coin supérieur gauche des cellules si le contenu ressemble à un nombre pour Excel. Si tel est le cas, la valeur est réellement stockée sous forme de texte.

Avec le nouveau BigDecimal (cell.getNumericCellValue ()). toString (), vous aurez toujours beaucoup de problèmes. Par exemple, si vous avez des numéros d'identification (par exemple, des numéros de référence ou des numéros de classification), vous avez probablement des cas avec des zéros non significatifs qui poseront un problème avec l'approche getNumericCellValue ().

J'essaie d'expliquer en détail comment créer correctement Excel à la partie qui crée les fichiers que je dois gérer avec des points d'intérêt. Si les fichiers sont téléchargés par les utilisateurs finaux, j'ai même créé un programme de validation pour vérifier les types de cellules attendus si je connais les colonnes à l'avance. En tant que sous-produit, vous pouvez également vérifier divers autres éléments des fichiers fournis (par exemple, les colonnes de droite fournies ou les valeurs obligatoires).

"Le problème est que j'ai des valeurs dans une cellule qui ressemblent à un nombre" = > ressemble à un numéro vu dans Excel?

"mais ce sont vraiment des chaînes" = > Qu'est-ce que ça veut dire? Comment SAVEZ-VOUS qu’il s’agit vraiment de chaînes?

"Si je regarde la cellule de format" = > quelle est la "cellule de format" ???

'... dans Excel, il est indiqué que le type est "texte". = > S'il vous plaît expliquer.

"La cellule HSSF pense toujours qu’elle est numérique." = > voulez-vous dire que the_cell.getCellType () retourne Cell.CELL_TYPE_NUMERIC?

"Comment puis-je obtenir la valeur sous forme de chaîne?" = > s'il s'agit de NUMERIC, obtenez la valeur numérique à l'aide de the_cell.getNumericCellValue (), puis formatez-la sous forme de chaîne comme vous le souhaitez.

"Si j'essaie d'utiliser cell.getRichStringValue, j'obtiens une exception;" = > donc ce n'est pas une chaîne.

"Si cell.toString, ce n'est pas exactement la même valeur que dans la feuille Excel." = > donc cell.toString () ne le formate pas comme Excel le formate.

Quelle que soit l'heuristique employée par Excel pour déterminer le type, cela n'a aucune importance pour vous. C'est le résultat de cette décision, tel qu'il est stocké dans le fichier et révélé par getCellType (), qui compte.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top