Ответ на ваш вопрос "Как мы можем преобразовать HSSFCellStyle
объект в XSSFCellStyle
?" является: Мы не можем сделать это, используя apache poi 4.1.2
. Это просто не поддерживается, как четко указано в CellStyle.cloneStyleFrom : «Однако оба типа CellStyles должны быть одного типа (HSSFCellStyle или XSSFCellStyle).»
Другой вопрос это: Если мы вообще конвертируем один стиль ячейки в другой? Или какие варианты использования вообще существуют для CellStyle.cloneStyleFrom
? На мой взгляд их нет. Существуют Excel
ограничения на количество уникальных форматов ячеек / стилей ячеек. См. Спецификации и ограничения Excel . Поэтому мы не должны создавать единый стиль ячейки для каждой отдельной ячейки, потому что тогда эти ограничения будут достигнуты очень быстро. Таким образом, вместо клонирования стилей ячеек мы должны получить свойства стиля из исходного стиля style1
и затем использовать CellUtil.setCellStyleProperties , чтобы установить эти свойства стиля для другой рассматриваемой ячейки. Этот метод пытается найти существующий CellStyle
, который соответствует текущему стилю плюс свойства стиля в properties
. Новый стиль создается только в том случае, если книга не содержит соответствующего стиля.
Поскольку ваш вопрос называется «Копировать ячейки между книгами Excel с Apache POI», я создал рабочий черновик того, как я сделайте это.
Следующий код сначала получает существующий Workbook.xls
как HSSFWorkbook
wb1
и создает новый XSSFWorkbook
wb2
. Затем он перебирает все ячейки первого листа wb1
и пытается скопировать эти ячейки на первый лист wb2
. Для этого есть метод copyCells(Cell cell1, Cell cell2)
, который использует copyStyles(Cell cell1, Cell cell2)
. Последний получает свойства стиля из исходного стиля style1
, полученного из cell1
, а затем использует CellUtil.setCellStyleProperties
, чтобы установить для этих свойств стиля значение cell2
. Для копирования используются шрифты copyFont(Font font1, Workbook wb2)
. Это попытается создать новые шрифты в wb2
, только если такого шрифта еще нет в этой книге. Это необходимо, поскольку в каждой рабочей книге есть ограничение на количество уникальных типов шрифтов в Excel
.
Рабочий пример:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.util.CellUtil;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.*;
class ExcelCopyCells {
static Font copyFont(Font font1, Workbook wb2) {
boolean isBold = font1.getBold();
short color = font1.getColor();
short fontHeight = font1.getFontHeight();
String fontName = font1.getFontName();
boolean isItalic = font1.getItalic();
boolean isStrikeout = font1.getStrikeout();
short typeOffset = font1.getTypeOffset();
byte underline = font1.getUnderline();
Font font2 = wb2.findFont(isBold, color, fontHeight, fontName, isItalic, isStrikeout, typeOffset, underline);
if (font2 == null) {
font2 = wb2.createFont();
font2.setBold(isBold);
font2.setColor(color);
font2.setFontHeight(fontHeight);
font2.setFontName(fontName);
font2.setItalic(isItalic);
font2.setStrikeout(isStrikeout);
font2.setTypeOffset(typeOffset);
font2.setUnderline(underline);
}
return font2;
}
static void copyStyles(Cell cell1, Cell cell2) {
CellStyle style1 = cell1.getCellStyle();
Map<String, Object> properties = new HashMap<String, Object>();
//CellUtil.DATA_FORMAT
short dataFormat1 = style1.getDataFormat();
if (BuiltinFormats.getBuiltinFormat(dataFormat1) == null) {
String formatString1 = style1.getDataFormatString();
DataFormat format2 = cell2.getSheet().getWorkbook().createDataFormat();
dataFormat1 = format2.getFormat(formatString1);
}
properties.put(CellUtil.DATA_FORMAT, dataFormat1);
//CellUtil.FILL_PATTERN
//CellUtil.FILL_FOREGROUND_COLOR
FillPatternType fillPattern = style1.getFillPattern();
short fillForegroundColor = style1.getFillForegroundColor(); //gets only indexed colors, no custom HSSF or XSSF colors
properties.put(CellUtil.FILL_PATTERN, fillPattern);
properties.put(CellUtil.FILL_FOREGROUND_COLOR, fillForegroundColor);
//CellUtil.FONT
Font font1 = cell1.getSheet().getWorkbook().getFontAt(style1.getFontIndexAsInt());
Font font2 = copyFont(font1, cell2.getSheet().getWorkbook());
properties.put(CellUtil.FONT, font2.getIndexAsInt());
//BORDERS
BorderStyle borderStyle = null;
short borderColor = -1;
//CellUtil.BORDER_LEFT
//CellUtil.LEFT_BORDER_COLOR
borderStyle = style1.getBorderLeft();
properties.put(CellUtil.BORDER_LEFT, borderStyle);
borderColor = style1.getLeftBorderColor();
properties.put(CellUtil.LEFT_BORDER_COLOR, borderColor);
//CellUtil.BORDER_RIGHT
//CellUtil.RIGHT_BORDER_COLOR
borderStyle = style1.getBorderRight();
properties.put(CellUtil.BORDER_RIGHT, borderStyle);
borderColor = style1.getRightBorderColor();
properties.put(CellUtil.RIGHT_BORDER_COLOR, borderColor);
//CellUtil.BORDER_TOP
//CellUtil.TOP_BORDER_COLOR
borderStyle = style1.getBorderTop();
properties.put(CellUtil.BORDER_TOP, borderStyle);
borderColor = style1.getTopBorderColor();
properties.put(CellUtil.TOP_BORDER_COLOR, borderColor);
//CellUtil.BORDER_BOTTOM
//CellUtil.BOTTOM_BORDER_COLOR
borderStyle = style1.getBorderBottom();
properties.put(CellUtil.BORDER_BOTTOM, borderStyle);
borderColor = style1.getBottomBorderColor();
properties.put(CellUtil.BOTTOM_BORDER_COLOR, borderColor);
CellUtil.setCellStyleProperties(cell2, properties);
}
static void copyCells(Cell cell1, Cell cell2) {
switch (cell1.getCellType()) {
case STRING:
/*
//TODO: copy HSSFRichTextString to XSSFRichTextString
RichTextString rtString1 = cell1.getRichStringCellValue();
cell2.setCellValue(rtString1); // this fails if cell2 is XSSF and rtString1 is HSSF
*/
String string1 = cell1.getStringCellValue();
cell2.setCellValue(string1);
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell1)) {
Date date1 = cell1.getDateCellValue();
cell2.setCellValue(date1);
} else {
double cellValue1 = cell1.getNumericCellValue();
cell2.setCellValue(cellValue1);
}
break;
case FORMULA:
String formula1 = cell1.getCellFormula();
cell2.setCellFormula(formula1);
break;
//case : //TODO: further cell types
}
copyStyles(cell1, cell2);
}
public static void main(String[] args) throws Exception {
Workbook wb1 = WorkbookFactory.create(new FileInputStream("Workbook.xls"));
Workbook wb2 = new XSSFWorkbook();
Sheet sheet1 = wb1.getSheetAt(0);
Sheet sheet2 = wb2.createSheet();
Set<Integer> columns = new HashSet<Integer>();
Row row2 = null;
Cell cell2 = null;
for (Row row1 : sheet1) {
row2 = sheet2.createRow(row1.getRowNum());
for (Cell cell1 : row1) {
columns.add(cell1.getColumnIndex());
cell2 = row2.createCell(cell1.getColumnIndex());
copyCells(cell1, cell2);
}
}
wb1.close();
for (Integer column : columns) {
sheet2.autoSizeColumn(column);
}
FileOutputStream out = new FileOutputStream("Workbook.xlsx");
wb2.write(out);
out.close();
wb2.close();
}
}
Если Workbook.xls
выглядит следующим образом:
, тогда результирующее Workbook.xlsx
выглядит так:
Примечание: Это рабочий проект и должен быть завершен. См. TODO
комментарии в коде. RichTextString
значения ячеек необходимо учитывать. Другие типы клеток должны быть рассмотрены.
Метод copyStyles
обеспечивает только копирование формата данных, заливки рисунка и заливки основного цвета (только для индексированных цветов), шрифта и границ. Дополнительные свойства стиля ячейки должны быть рассмотрены.