org.swiftboot.sheet.exp.ExcelExporter Maven / Gradle / Ivy
package org.swiftboot.sheet.exp;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.swiftboot.sheet.excel.ExcelCellInfo;
import org.swiftboot.sheet.excel.ExcelSheetInfo;
import org.swiftboot.sheet.meta.Picture;
import org.swiftboot.sheet.meta.*;
import org.swiftboot.sheet.util.PoiUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
/**
* Export data into a new or a templated Excel 2003/2007 file.
*
* @author swiftech
*/
public class ExcelExporter extends BaseExporter {
private final Logger log = LoggerFactory.getLogger(ExcelExporter.class);
private final ThreadLocal cellInfo = new ThreadLocal<>();
public ExcelExporter(String fileType) {
super(fileType);
}
@Override
public void export(Object dataObject, OutputStream outputStream) throws IOException {
this.export(null, dataObject, outputStream);
}
@Override
public void export(InputStream templateFileStream, Object dataObject, OutputStream outputStream) throws IOException {
SheetMetaBuilder builder = new SheetMetaBuilder();
SheetMeta meta = builder.fromAnnotatedObject(dataObject).build();
this.export(templateFileStream, meta, outputStream);
}
@Override
public void export(SheetMeta exportMeta, OutputStream outputStream) throws IOException {
this.export(null, exportMeta, outputStream);
}
@Override
public void export(InputStream templateFileStream, SheetMeta exportMeta, OutputStream outputStream) throws IOException {
Workbook wb = PoiUtils.initWorkbook(templateFileStream, super.getFileType());
cellInfo.set(new ExcelCellInfo());
cellInfo.get().setWorkbook(wb);
final AtomicReference sheetRef = new AtomicReference<>();
final AtomicReference maxPositionRef = new AtomicReference<>(); // max position user wants
exportMeta.setAllowFreeSize(true);
exportMeta.accept(sheetId -> {
log.debug("Export to sheet: " + sheetId);
sheetRef.set(PoiUtils.getOrCreateSheet(wb, sheetId));
cellInfo.get().setSheet(sheetRef.get());
maxPositionRef.set(exportMeta.findMaxPosition(sheetId));
extendSheet(sheetRef.get(), maxPositionRef.get());
// callback to user client to handle the sheet.
if (exportMeta.getSheetHandler(sheetId) != null) {
ExcelSheetInfo sheetInfo = new ExcelSheetInfo(wb, sheetRef.get());
Consumer handler = (Consumer) exportMeta.getSheetHandler(sheetId);
handler.accept(sheetInfo);
}
}, (metaItem, startPos, rowCount, columnCount) -> {
Sheet sheet = sheetRef.get();
// merge all cells in the specific area.
if (metaItem.isMerge() && !metaItem.getArea().isDynamic() && (rowCount > 1 || columnCount > 1)) {
Cell firstCell = PoiUtils.getCell(sheet, startPos);
CellRangeAddress merged = new CellRangeAddress(startPos.getRow(), startPos.getRow() + rowCount - 1,
startPos.getColumn(), startPos.getColumn() + columnCount - 1);
log.debug(String.format("Merge cells: %s", merged.formatAsString()));
sheet.addMergedRegion(merged);
CellStyle cellStyle = firstCell.getCellStyle();
cellStyle.setAlignment(HorizontalAlignment.LEFT);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
RegionUtil.setBorderTop(cellStyle.getBorderTop(), merged, sheet);
RegionUtil.setBorderBottom(cellStyle.getBorderBottom(), merged, sheet);
RegionUtil.setBorderLeft(cellStyle.getBorderLeft(), merged, sheet);
RegionUtil.setBorderRight(cellStyle.getBorderRight(), merged, sheet);
}
if (metaItem.getValue() instanceof PictureLoader) {
try {
Picture pictureValue = ((PictureLoader) metaItem.getValue()).get();
PoiUtils.writePicture(sheetRef.get(), startPos, startPos.clone().moveRows(rowCount).moveColumns(columnCount), pictureValue);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
else {
List> matrix = asMatrix(metaItem.getValue(), rowCount, columnCount);
if (matrix.isEmpty()) {
return;
}
int actualRowCount = rowCount == null ? matrix.size() : Math.min(rowCount, matrix.size());
int actualColumnCount = columnCount == null ? matrix.get(0).size() : Math.min(columnCount, matrix.get(0).size());
// shift rows if need insert
if (metaItem.isInsert()) {
int insertRowCount = (rowCount == null || metaItem.isInsertByValue()) ? actualRowCount : rowCount;
log.debug(String.format("Insert %d rows start at row %d", insertRowCount, startPos.getRow()));
sheet.shiftRows(startPos.getRow(), sheet.getLastRowNum(), insertRowCount, true, true);
createCells(sheet, startPos, startPos.clone().moveRows(insertRowCount - 1).moveColumns(maxPositionRef.get().getColumn() - 1), 0, 0);
}
if (metaItem.getCopyArea() != null && !metaItem.getCopyArea().isDynamic()) {
// if row or column is uncertain size, use copied area's row or column size instead.
Area targetArea = Area.newArea(startPos,
rowCount == null ? metaItem.getCopyArea().rowCount() : rowCount,
columnCount == null ? metaItem.getCopyArea().columnCount() : columnCount);
log.debug(String.format("Copy cells from %s to %s", metaItem.getCopyArea(), targetArea));
PoiUtils.copyCells(sheet, metaItem.getCopyArea(), targetArea);
}
if (metaItem.isMerge()) {
// merge values into lines
Optional optMergeValues = matrix.stream().map(objects -> StringUtils.join(objects, ","))
.reduce((s, s2) -> String.format("%s\n%s", s, s2));
if (optMergeValues.isPresent()) {
Cell cell = sheet.getRow(startPos.getRow()).getCell(startPos.getColumn());
PoiUtils.setValueToCell(cell, optMergeValues.get());
}
}
else {
for (int i = 0; i < actualRowCount; i++) {
cellInfo.get().setRowIdx(i);
List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy