L'objectif est que les personnes souhaitant utiliser Apache POI puissent travailler avec des fichiers Excel lors de la copie. L'exemple d'implémentation présenté ici n'est que l'implémentation minimale pour exécuter Apache POI, et la gestion des erreurs est requise séparément. La version qui a été confirmée pour fonctionner avec le code est 4.1.0.
Vous pouvez le préparer à partir d'ici. https://poi.apache.org/download.html
ʻOrg.apache.poi.ss.usermodel.Workbook` représente le classeur entier du fichier xlsx.
Pour que le fichier xlsx soit lu ou écrit, spécifiez d'abord la feuille cible après avoir créé l'objet Workbook
. C'est ʻorg.apache.poi.ss.usermodel.Sheet`.
Après avoir récupéré l'objet Sheet
de l'objet Workbook
, spécifiez la ligne à lire / écrire. C'est ʻorg.apache.poi.ss.usermodel.Row`.
Après avoir obtenu l'objet Row
de l'objet Sheet
, spécifiez la cellule à lire ou à écrire. Spécifiez la colonne et spécifiez la cellule. C'est ʻorg.apache.poi.ss.usermodel.Cell`.
Après avoir obtenu l'objet Cell
de l'objet Row
, vous pouvez lire et écrire des valeurs dans la cellule comme vous le feriez normalement dans Excel.
Tout d'abord, récupérez l'objet Workbook
à partir du chemin du fichier.
Workbook workbook = WorkbookFactory.create(new FileInputStream(filePath));
L'objet Sheet
peut être obtenu à partir du nom et de l'index de la feuille (à partir de 0 à partir de la feuille la plus à gauche).
//Obtenu à partir du nom de la feuille
Sheet sheet = workbook.getSheet(name);
//Obtenir de l'index
Sheet sheet = workbook.getSheetAt(index);
A partir de l'objet Sheet
, récupérez l'objet Row
puis l'objet Cell
.
Row row = sheet.getRow(rowIndex);
Cell cell = row.getCell(columIndex);
Fondamentalement, pour obtenir l'objet Row
et l'objet Cell
, il est nécessaire de spécifier l'index de 0 start tel que la ligne et la colonne, mais en utilisant CellReference
, c'est familier dans Excel. Il est également possible de spécifier au format A1.
CellReference reference = new CellReference(a1Position);
Row row = sheet.getRow(reference.getRow());
Cell cell = row.getCell(reference.getCol());
Après avoir obtenu l'objet Cell
, si vous voulez obtenir le contenu de la cellule sous forme de chaîne de caractères, exécutez la méthode Cell.getCellType ()
pour obtenir le type de valeur contenue dans la cellule, et combien en fonction de chaque Ou vous devez concevoir la méthode correspondante individuellement.
Si le contenu de la cellule est une chaîne (STRING
), il peut être lu avec le standard Cell.getStringCellValue ()
.
Dans le cas d'une valeur numérique (NUMERIC
), la date est également traitée comme une valeur numérique, il est donc préférable de faire attention à cela et de préparer votre propre méthode.
Dans le cas des dates, dans la plupart des cas, vous voudrez une valeur qui a un format d'affichage stylisé, afin que vous puissiez gérer cela avec votre propre méthode.
Dans le cas de la valeur de vérité (BOOLEAN
), vous pouvez obtenir la valeur de boolean
avec le standardCell.getBooleanCellValue ()
, alors convertissez-le en chaîne de caractères.
Pour une valeur de fonction (FORMULA
), si vous voulez simplement que l'expression de la fonction soit une chaîne, vous pouvez l'obtenir avec Cell.getCellFormula ()
.
Cependant, en général, je pense que dans la plupart des cas, vous voulez le résultat du calcul de la fonction, alors dans ce cas, préparez votre propre méthode.
S'il n'y a pas de valeur (BLANK
), il s'agit souvent d'une cellule fusionnée. La cellule fusionnée est censée avoir une valeur dans la cellule supérieure gauche de la zone fusionnée, donc la lecture d'une autre cellule dans la zone fusionnée sera traitée comme vide.
Étant donné que les cellules fusionnées sont enregistrées de manière spéciale lors de l'utilisation d'Excel, nous préparerons une méthode distincte pour gérer cela.
Voici une implémentation simple d'une méthode qui prend un objet Cell
et renvoie une String
: Nous parlerons de nos propres méthodes ci-dessous.
String readCell(Cell cell) {
switch (cell.getCellType()) {
//Chaîne(la norme)
case STRING:
return cell.getStringCellValue();
//Valeur numérique(Posséder)
case NUMERIC:
return getStringNmericValue(cell);
//Valeur de vérité(la norme)
case BOOLEAN:
return Boolean.toString(cell.getBooleanCellValue());
//Valeur de la fonction(Posséder)
case FORMULA:
return getStringFormulaValue(cell);
//Vide(Posséder)
case BLANK:
return getStringRangeValue(cell);
default:
System.out.println("Unexpected Type: "+cell.getCellType());
return null;
}
}
NUMERIC
)Si la valeur de la cellule n'est qu'un nombre, vous pouvez la convertir en chaîne et la renvoyer, mais s'il s'agit d'une date, adaptez le style, puis récupérez-la sous forme de chaîne.
Pour les formats de date standard, vous pouvez l'obtenir sous forme de chaîne en utilisant java.time
, mais pour les types définis par l'utilisateur, utilisez ʻorg.apache.poi.ss.format.CellFormat` pour le styliser. Obtient la valeur de ce texte après l'adaptation.
Voici un exemple de mise en œuvre simple.
//Obtenez le numéro en tenant compte de la date
String getStringNmericValue(Cell cell) {
//Pour les dates standard
if(DateUtil.isCellDateFormatted(cell)) {
Date date = cell.getDateCellValue();
//java.time.Stringify avec DateTimeFormatter
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS");
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
return dateTimeFormatter.format(localDateTime);
}
//Si vous avez défini la date dans un type défini par l'utilisateur
if(BuiltinFormats.FIRST_USER_DEFINED_FORMAT_INDEX <= cell.getCellStyle().getDataFormat()) {
CellFormat cellFormat = CellFormat.getInstance(cell.getCellStyle().getDataFormatString());
return cellFormat.apply(cell).text;
}
//S'il ne s'agit pas d'une date, elle renvoie un nombre.
return Double.toString(cell.getNumericCellValue());
}
FORMULA
)Pour obtenir le résultat du calcul de la fonction, passez l'objet cible Cell
à l'objet FormulaEvaluator
et obtenez le résultat du calcul.
Cependant, comme le résultat du calcul est renvoyé sous la forme d'un objet CellValue
au lieu d'une chaîne de caractères, le fait que le résultat du calcul soit une chaîne de caractères, une valeur numérique ou une valeur de vérité est à nouveau jugé par CellValue.getCellType ()
, et chacun est déterminé. , Lisez la valeur avec la méthode POI standard.
Notez également que certaines fonctions ne sont pas prises en charge par l'objet FormulaEvaluator
.
Veuillez consulter la liste des fonctions actuellement prises en charge à la fin.
Si vous exécutez une fonction non prise en charge, ʻEvaluationException` sera lancée.
Si vous souhaitez exécuter une fonction définie par l'utilisateur, veuillez vous reporter ici. https://poi.apache.org/components/spreadsheet/user-defined-functions.html
Ce qui suit est un exemple d'implémentation simple de la propre méthode de la propre méthode de FORMULA
.
//Exécuter la fonction et lire
String getStringFormulaValue(Cell cell) {
try {
//Exécution de la fonction
CreationHelper helper = workbook.getCreationHelper();
FormulaEvaluator evaluator = helper.createFormulaEvaluator();
CellValue value = evaluator.evaluate(cell);
//Modifiez la destination d'appel de la méthode en fonction du contenu du résultat du calcul.
switch (value.getCellType()) {
case STRING:
return value.getStringValue();
case NUMERIC:
return Double.toString(value.getNumberValue());
case BOOLEAN:
return Boolean.toString(value.getBooleanValue());
default:
System.out.println("Unexpected Type: "+value.getCellType());
return null;
}
}catch(Exception e) {
return cell.getCellFormula();
}
}
BLANK
) viergeDans le cas de BLANK
, ce n'est pas un problème s'il ne peut pas être lu s'il s'agit simplement d'une cellule vide, mais dans le cas d'une cellule fusionnée, c'est un problème si elle ne peut pas être lue, alors faites-la correspondre à la cellule fusionnée.
Les cellules fusionnées sont stockées collectivement dans une zone spéciale de la feuille, et pour déterminer si la cellule à lire est une cellule fusionnée, retirez la liste de la zone de cellule fusionnée et lisez-la. Détermine s'il existe une zone fusionnée contenant les cellules dans.
S'il y a une zone fusionnée où la cellule à lire est incluse dans la zone, spécifiez le coin supérieur gauche de la zone pour lire la valeur.
Pour le moment, le type de contenu de la cellule ne peut pas être déterminé sans utiliser Cell.getCellType ()
, donc la cellule supérieure gauche est à nouveau transmise à la méthode qui renvoie String
from Cell
. (Méthode ReadCell dans l'exemple d'implémentation ci-dessus)
Voici un exemple de mise en œuvre simple.
//Lire les cellules fusionnées
String getStringRangeValue(Cell cell) {
//Obtenez l'index de la cellule à lire
int rowIndex = cell.getRowIndex();
int columnIndex = cell.getColumnIndex();
//Recherchez attentivement pour voir s'il est inclus dans la zone combinée.
int size = sheet.getNumMergedRegions();
for (int i = 0; i < size; i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
//S'il y a une zone incluse
if (range.isInRange(rowIndex, columnIndex)) {
//Obtenez la cellule supérieure gauche
Cell firstCell = sheet.getRow(range.getFirstRow()).getCell(range.getFirstColumn());
//Cell->Jetez à la méthode String.
return readCell(firstCell);
}
}
return null;
}
Workbook
, Sheet
, Row
, Cell
Lors de la création d'un nouveau classeur au format xlsx, créez une instance de ʻorg.apache.poi.xssf.usermodel.XSSFWorkbooket recevez-la comme variable de type
Workbook`.
Si vous voulez créer un objet Sheet
, il est préférable de le convertir en un nom qui peut être utilisé pour une feuille avec` WorkbookUtil.createSafeSheetName () ʻet ensuite le créer.
En ce qui concerne l'objet Row
et l'objet Cell
, dans l'objet Sheet
à l'état initial, toutes les lignes et cellules sont nulles
, donc créez chaque objet une fois avant d'écrire dans la cellule. est nécessaire.
Si vous souhaitez spécifier la ligne / colonne au format A1, utilisez CellReference
comme vous l'avez fait dans la lecture ci-dessus.
//Création d'un objet Workbook
Workbook workbook = new XSSFWorkbook();
//Générer un objet Feuille
String safeName = WorkbookUtil.createSafeSheetName(name);
Sheet sheet = workbook.createSheet(safeName);
//Conversion du format A1 en index
CellReference reference = new CellReference(a1Position);
int rowIndex = reference.getRow();
int columIndex = reference.getCol();
//Générer un objet Row
Row row = sheet.createRow(rowIndex);
//Créer un objet Cell
Cell cell = row.createCell(columIndex);
Après avoir apporté les différentes modifications ci-dessous à l'objet Workbook
, utilisez FileOutputStream
pour exporter finalement le fichier xlsx.
(Bien que omis par souci de concision, veuillez écrire try-catch de manière appropriée dans le code réel.)
FileOutputStream fileOut = new FileOutputStream(filePath);
workbook.write(fileOut);
fileOut.close();
Ecrire une chaîne est très simple, il suffit d'appeler Cell.setvalue ()
.
Cependant, lors de la création d'une méthode qui écrit des cellules en spécifiant l'index, il est préférable de vérifier la valeur nulle de l'objet Row
ou de l'objet Cell
à cette position.
Voici un exemple de mise en œuvre simple.
void writeCellAt(int rowIndex, int columIndex, String value) {
//Row,Vérification nulle de cellule
Row row = sheet.getRow(rowIndex);
if(row == null) {
row = sheet.createRow(rowIndex);
}
Cell cell = row.getCell(columIndex);
if(cell == null) {
cell = row.createCell(columIndex);
}
//Ecrire une chaîne
cell.setCellValue(value);
}
En gros, tant que vous pouvez écrire une chaîne de caractères, je pense qu'un traitement compliqué peut être implémenté à l'aide de fonctions et de bibliothèques Java.
S'il s'agit d'un simple format tabulaire, c'est possible avec un fichier csv, mais je pense qu'il y a des décorations de cellules comme raison d'utiliser xlsx.
Je pense qu'il y a beaucoup de gens dans l'environnement où xlsx est utilisé comme premier document plutôt que PDF et dox, donc la méthode de décoration de base est indiquée ci-dessous.
Il est toujours préférable de vérifier la valeur nulle de Row
et Cell
pour les décorations ci-dessous.
Cette fois, utilisez Sheet.addMergedRegion ()
pour vous enregistrer avec l'objet Sheet
, comme il a été obtenu à partir de l'objet Sheet
lors de la lecture des cellules fusionnées.
//topRow: Index de ligne de la cellule supérieure gauche
//topColum: Index de colonne de la cellule supérieure gauche
//bottomRow: Index de ligne de la cellule inférieure droite
//bottomColum: Index de colonne de la cellule inférieure droite
CellRangeAddress cellRangeAddress = new CellRangeAddress(topRow, bottomRow, topColum, bottomColum);
sheet.addMergedRegion(cellRangeAddress);
Vous pouvez modifier la hauteur de ligne avec Row.setHeightInPoints ()
. S'il est difficile de spécifier une hauteur spécifique, vous pouvez la spécifier en multiples de la valeur par défaut.
//plusieurs
float mult = 2.0f;
//Définir deux fois la valeur par défaut
row.setHeightInPoints(mult*sheet.getDefaultRowHeightInPoints());
Pour envelopper et afficher le tout, utilisez CellStyle
pour l'objet Cell
cible comme suit:
CellStyle style = workbook.createCellStyle();
style.setWrapText(true);
cell.setCellStyle(style);
Si cela ne vous donne pas un bon ajustement dynamique, veuillez vous référer ici. https://stackoverflow.com/questions/19145628/auto-size-height-for-rows-in-apache-poi
De plus, si le réglage de la hauteur ne fonctionne pas, il semble y avoir un moyen de compter les sauts de ligne et de le définir comme un multiple. https://stackoverflow.com/questions/45387206/how-to-increase-the-height-of-the-excel-row-using-apache-poi-having-merged-cell/45388037
Pour dessiner une bordure, utilisez CellStyle
pour spécifier l'objet Cell
cible individuellement, en haut, en bas, à gauche et à droite, comme indiqué ci-dessous.
L'épaisseur est spécifiée par BorderStyle
. C'est un nom déroutant, mais «BorderStyle.THIN» représente généralement une bordure épaisse et «BorderStyle.MEDIUM» représente une bordure épaisse.
CellStyle style = workbook.createCellStyle();
style.setBorderTop(BorderStyle.THIN);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
cell.setCellStyle(style);
La couleur de la police peut également être modifiée avec CellStyle
pour l'objetCell
cible.
Pour les couleurs, une palette de couleurs standard est préparée à l'avance en tant que variable. Veuillez vous référer ici pour des échantillons de couleurs. https://lincolnminto.wordpress.com/2014/04/07/apache-poi-referencia-para-estilos-de-celulas-apache-poi-cellstyles-reference/
CellStyle style = workbook.createCellStyle();
Font font = workbook.createFont();
font.setColor(IndexedColors.WHITE.getIndex());
style.setFont(font);
cell.setCellStyle(style);
Le remplissage de la cellule peut également être modifié avec CellStyle
pour l'objet Cell
.
Encore une fois, de manière déroutante, utilisez «CellStyle.setFillForegroundColor ()» au lieu de «CellStyle.setFillBackgroundColor ()».
CellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(IndexedColors.CORAL.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cell.setCellStyle(style);
Je n'ai pas confirmé que cela fonctionne correctement, mais il semble y avoir un moyen de spécifier RVB pour la couleur de police et la couleur de remplissage de cellule comme suit.
IndexedColorMap colorMap = workbook.getStylesSource().getIndexedColors();
XSSFColor grey = new XSSFColor(new java.awt.Color(192,192,192), colorMap);
cellStyle.setFillForegroundColor(grey);
Référence: https://stackoverflow.com/questions/10912578/apache-poi-xssfcolor-from-hex-code
Collez l'image sur l'objet Workbook
.
Après la conversion en une chaîne d'octets avec ʻIOUtils.toByteArray () , en l'enregistrant dans le livre avec
Workbook.addPicture () `, l'index de l'image est acquis comme valeur de retour. Certains des formats de fichier qui peuvent être spécifiés à ce moment sont indiqués ci-dessous.
constant | format |
---|---|
PICTURE_TYPE_DIB | bmp |
PICTURE_TYPE_JPEG | jpeg |
PICTURE_TYPE_PNG | png |
La position et la taille de l'image sont spécifiées à l'aide de ClientAnchor
.
Spécifiez la cellule supérieure gauche et la cellule inférieure droite pour ajuster la position et la taille. Cependant, «ClientAnchor.setCol2 ()» et «ClientAnchor.setRow2 ()» qui spécifient la cellule inférieure droite sont en fait étirés car ils sont étirés jusqu'à la position d'index-1 spécifiée (une cellule supérieure gauche). Spécifiez la valeur de l'indice + 1 dans la cellule inférieure droite de la plage souhaitée.
Le type d'ancrage est ce qu'Excel appelle le champ de mise en forme de propriété d'une forme, et vous pouvez spécifier s'il faut apporter des modifications à l'image lorsque les cellules se déplacent ou se redimensionnent. Voici une liste de constantes et de paramètres.
constant | La description |
---|---|
DONT_MOVE_AND_RESIZE | Même si la ligne / colonne est redimensionnée, l'image n'est pas déplacée / redimensionnée. |
DONT_MOVE_DO_RESIZE | L'image n'est pas déplacée, mais elle est redimensionnée pour s'adapter à la cellule d'ancrage. |
MOVE_AND_RESIZE | Déplacer et redimensionner. |
MOVE_DONT_RESIZE | Il se déplace selon la cellule de l'ancre |
Enfin, utilisez l'objet Drawing
pour coller l'image avec l'index spécifié à la position d'ancrage spécifiée.
Voici un exemple de mise en œuvre simple. (Bien que omis par souci de concision, veuillez écrire try-catch de manière appropriée dans le code réel.)
//Convertir en chaîne d'octets
InputStream in = new FileInputStream(filePath);
byte[] bytes = IOUtils.toByteArray(in);
in.close();
//Enregistrement d'image, acquisition d'index
int pictureIndex = workbook.addPicture(byteWorkbook.PICTURE_TYPE_PNG);
//Spécifiez la position et la taille avec l'ancre
ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();
anchor.setCol1(topColum);
anchor.setRow1(topRow);
anchor.setCol2(bottomColum+1);
anchor.setRow2(bottomRow+1);
anchor.setAnchorType(AnchorType.MOVE_AND_RESIZE);
//Coller l'image de l'index spécifié à la position de l'ancre spécifiée
Drawing patriarch = sheet.createDrawingPatriarch();
patriarch.createPicture(anchor, pictureIndex);
Référence: https://poi.apache.org/components/spreadsheet/eval-devguide.html
ABS | ACOS | ACOSH | ADDRESS | AND |
ASIN | ASINH | ATAN | ATAN2 | ATANH |
AVEDEV | AVERAGE | BIN2DEC | CEILING | CHAR |
CHOOSE | CLEAN | CODE | COLUMN | COLUMNS |
COMBIN | COMPLEX | CONCATENATE | COS | COSH |
COUNT | COUNTA | COUNTBLANK | COUNTIF | COUNTIFS |
DATE | DAY | DAYS360 | DEC2BIN | DEC2HEX |
DEGREES | DELTA | DEVSQ | DGET | DMIN |
DOLLAR | EDATE | EOMONTH | ERROR.TYPE | EVEN |
EXACT | EXP | FACT | FACTDOUBLE | FALSE |
FIND | FIXED | FLOOR | FV | HEX2DEC |
HLOOKUP | HOUR | HYPERLINK | IF | IFERROR |
IMAGINARY | IMREAL | INDEX | INDIRECT | INT |
INTERCEPT | IPMT | IRR | ISBLANK | ISERR |
ISERROR | ISEVEN | ISLOGICAL | ISNA | ISNONTEXT |
ISNUMBER | ISODD | ISREF | ISTEXT | LARGE |
LEFT | LEN | LN | LOG | LOG10 |
LOOKUP | LOWER | MATCH | MAX | MAXA |
MDETERM | MEDIAN | MID | MIN | MINA |
MINUTE | MINVERSE | MIRR | MMULT | MOD |
MODE | MONTH | MROUND | NA | NETWORKDAYS |
NOT | NOW | NPER | NPV | OCT2DEC |
ODD | OFFSET | OR | PERCENTILE | PI |
PMT | POISSON | POWER | PPMT | PRODUCT |
PROPER | PV | QUOTIENT | RADIANS | RAND |
RANDBETWEEN | RANK | RATE | REPLACE | REPT |
RIGHT | ROMAN | ROUND | ROUNDDOWN | ROUNDUP |
ROW | ROWS | SEARCH | SECOND | SIGN |
SIN | SINH | SLOPE | SMALL | SQRT |
STDEV | SUBSTITUTE | SUBTOTAL | SUM | SUMIF |
SUMIFS | SUMPRODUCT | SUMSQ | SUMX2MY2 | SUMX2PY2 |
SUMXMY2 | T | TAN | TANH | TEXT |
TIME | TODAY | TRANSPOSE | TRIM | TRUE |
TRUNC | UPPER | VALUE | VAR | VARP |
VLOOKUP | WEEKDAY | WEEKNUM | WORKDAY | YEAR |
YEARFRAC |
Page d'accueil de Hishidama Apache POI http://www.ne.jp/asahi/hishidama/home/tech/apache/poi/
La programmation exploite Excel avec Apache POI https://www.javadrive.jp/poi/
L'histoire de Sukero Insérer une image dans EXCEL avec POI https://www.sukerou.com/2019/03/poiexcel.html
--Qiita Apache POI mémorandum Excel lecture https://qiita.com/panage/items/4476ff91d1fcec67f525
stackoverflow Auto size height for rows in Apache POI https://stackoverflow.com/questions/19145628/auto-size-height-for-rows-in-apache-poi
stackoverflow How to increase the height of the excel row using Apache-POI having merged cell value greater than the cell width? https://stackoverflow.com/questions/45387206/how-to-increase-the-height-of-the-excel-row-using-apache-poi-having-merged-cell/45388037
stackoverflow Apache POI background color style seems not working https://stackoverflow.com/questions/43212386/apache-poi-background-color-style-seems-not-working/43213843
stackoverflow Apache POI XSSFColor from hex code https://stackoverflow.com/questions/10912578/apache-poi-xssfcolor-from-hex-code
Recommended Posts