package com.bstek.bdf2.export.excel; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.DataFormat; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellUtil; import org.apache.poi.ss.util.RegionUtil; import org.springframework.stereotype.Component; import com.bstek.bdf2.export.excel.style.FormStyleBuilder; import com.bstek.bdf2.export.excel.style.GridStyleBuilder; import com.bstek.bdf2.export.excel.style.GridStyleType; import com.bstek.bdf2.export.excel.style.TitleStyleBuilder; import com.bstek.bdf2.export.model.ReportFormData; import com.bstek.bdf2.export.model.ReportForm; import com.bstek.bdf2.export.model.ReportGridHeader; import com.bstek.bdf2.export.model.ReportGrid; import com.bstek.bdf2.export.model.ReportTitle; import com.bstek.bdf2.export.utils.ExportUtils; /** * @author matt.yao@bstek.com * @since 2.0 */ @Component(ExcelReportBuilder.BEAN_ID) public class ExcelReportBuilder extends AbstractExcelReportBuilder { private short rowHeitht = 2*200; private short titleRowHeitht = 2*300; public static final String BEAN_ID = "bdf2.ExcelReportBuilder"; public int addTitleToSheet(ReportTitle reportTitle, Sheet sheet, int lastCol) { return this.addTitleToSheet(reportTitle, sheet, 0, 0, lastCol); } /** * 二〇二〇年七月八日 调整,如果标题中包含制表人等信息,创建两行数据 * * @param reportTitle * @param sheet * @param row * @param firstCol * @param lastCol * @return */ public int addTitleToSheet(ReportTitle reportTitle, Sheet sheet, int row, int firstCol, int lastCol) { if (!reportTitle.isShowTitle()) { return row; } Row titleRow = sheet.createRow(row); Cell titleCell = titleRow.createCell(firstCol); titleCell.setCellType(Cell.CELL_TYPE_STRING); titleCell.setCellValue(reportTitle.getTitle()); CellStyle titleStyle = new TitleStyleBuilder().builder(reportTitle, sheet.getWorkbook()); titleCell.setCellStyle(titleStyle); CellRangeAddress rangle = new CellRangeAddress(row, row, firstCol, lastCol); sheet.addMergedRegion(rangle); // System.out.println(titleRow.getHeight()); titleRow.setHeight(titleRowHeitht); // 2020年7月8日 取消标题的边框 // this.setCellRangeAddressBorder(rangle, sheet); // 创建第二行信息 if (null != reportTitle.getCreateUser() || null != reportTitle.getTimeDesc()) { row++; Row descRow = sheet.createRow(row); descRow.setHeight(rowHeitht); Cell cell; int col = firstCol; // 第一个位置是时间:timeDesc if (null != reportTitle.getTimeDesc()) { cell = descRow.createCell(col); cell.setCellType(Cell.CELL_TYPE_STRING); if (null == reportTitle.getTimeDescLabel()) { cell.setCellValue("时间:" + reportTitle.getTimeDesc()); } else { cell.setCellValue(reportTitle.getTimeDescLabel() +":"+ reportTitle.getTimeDesc()); } } // 第二个位置是仓库名称/说明 if (null != reportTitle.getDepotName()) { col = col + lastCol / 4; cell = descRow.createCell(col); cell.setCellType(Cell.CELL_TYPE_STRING); if (null == reportTitle.getDepotNameLabel()) { cell.setCellValue("仓库:" + reportTitle.getDepotName()); } else { cell.setCellValue(reportTitle.getDepotNameLabel() +":"+ reportTitle.getDepotName()); } } // 第三个位置是创建人 if (null != reportTitle.getCreateUser()) { col = col + lastCol / 2; cell = descRow.createCell(col); cell.setCellType(Cell.CELL_TYPE_STRING); cell.setCellValue("制表人:" + reportTitle.getCreateUser()); } // 第四个是单位 if (null != reportTitle.getUnit()) { col = lastCol - 1; cell = descRow.createCell(col); cell.setCellType(Cell.CELL_TYPE_STRING); cell.setCellValue("单位:" + reportTitle.getUnit()); } // 第四个是单位 if (null != reportTitle.getCreateTime()) { col = lastCol - 2; cell = descRow.createCell(col); cell.setCellType(Cell.CELL_TYPE_STRING); cell.setCellValue("制表时间:" + reportTitle.getCreateTime()); } } return row + 1; } public int addFormToSheet(ReportForm reportFormModel, Sheet sheet, int rowNo) throws Exception { rowNo = buildFormExcelData(reportFormModel, sheet, rowNo); return rowNo; } public int addGridToSheet(ReportGrid reportGridModel, Sheet sheet, int initRowNo) { Map styles = new GridStyleBuilder() .builderGridStyles(sheet.getWorkbook(), reportGridModel); int nextRow = this.buildGridExcelHeader(reportGridModel, sheet, initRowNo, styles); nextRow = this.buildGridExcelData(reportGridModel, sheet, nextRow, styles); return nextRow; } private int buildGridExcelHeader(ReportGrid gridModel, Sheet sheet, int starHeaderRow, Map styles) { Map rowMap = new HashMap(); this.calculateMaxHeaderLevel(gridModel, gridModel.getGridHeaderModelList()); int maxHeaderLevel = gridModel.getMaxHeaderLevel(); for (int i = 0; i < maxHeaderLevel; i++) { Row row = sheet.createRow((short) i + starHeaderRow); rowMap.put(i + starHeaderRow, row); } List topHeaders = new ArrayList(); calculateGridHeadersByLevel(gridModel.getGridHeaderModelList(), 1, topHeaders); this.buildGridExcelHeader(sheet, rowMap, maxHeaderLevel, 1, starHeaderRow, 0, topHeaders, styles); return starHeaderRow + maxHeaderLevel; } private void buildGridExcelHeader(Sheet sheet, Map rowMap, int maxHeaderLevel, int currentLevel, int startHeaderRow, int startHeaderCol, List topHeaders, Map styles) { CellStyle headerStyle = styles.get(GridStyleType.headerStyle.name()); int currentRow = startHeaderRow + currentLevel - 1; Cell cell; Row row = (Row) rowMap.get(currentRow); row.setHeight(rowHeitht); int currentCol = startHeaderCol; CellRangeAddress cellRangeAddress; for (ReportGridHeader headerModel : topHeaders) { cell = row.createCell((short) currentCol); cell.setCellValue(headerModel.getLabel()); int firstRow = currentRow; int lastRow = currentRow; int firstCol = currentCol; int lastCol = currentCol; int colspan = calculateGridHeaderColspan(headerModel); cell.setCellStyle(headerStyle); if (headerModel.getHeaders().size() == 0) { int rowspan = maxHeaderLevel - headerModel.getLevel(); cellRangeAddress = new CellRangeAddress(firstRow, lastRow + rowspan, firstCol, lastCol + colspan - 1); sheet.addMergedRegion(cellRangeAddress); this.setCellRangeAddressBorder(cellRangeAddress, sheet); } else { cellRangeAddress = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol + colspan - 1); sheet.addMergedRegion(cellRangeAddress); this.setCellRangeAddressBorder(cellRangeAddress, sheet); this.buildGridExcelHeader(sheet, rowMap, maxHeaderLevel, headerModel.getLevel() + 1, startHeaderRow, firstCol, headerModel.getHeaders(), styles); } currentCol = currentCol + colspan; } } private int buildFormExcelData(ReportForm reportFormModel, Sheet sheet, int initDataRow) throws Exception { SimpleDateFormat sdf = ExportUtils.getSimpleDateFormat(); List formExcelDataList = reportFormModel .getListReportFormDataModel(); FormStyleBuilder formStyleBuilder = new FormStyleBuilder(); CellStyle labelCellStyle = formStyleBuilder.builderLabelCellStyle( reportFormModel, sheet.getWorkbook()); CellStyle dataCellStyle = formStyleBuilder.builderValueCellStyle( reportFormModel, sheet.getWorkbook()); Map> group = new HashMap>(); List currentReportFormDataModels = new ArrayList(); int rowIndx = 0; int colCount = reportFormModel.getColumnCount() * 2; int currentRowColumnSize = 0; int i = 1; for (ReportFormData reportFormDataModel : formExcelDataList) { int colSpan = reportFormDataModel.getColSpan(); int formDataColumnSize = colSpan * 2 - 1 + 1; if (currentRowColumnSize + formDataColumnSize <= colCount) { currentRowColumnSize = currentRowColumnSize + formDataColumnSize; } else { group.put(rowIndx, currentReportFormDataModels); currentRowColumnSize = formDataColumnSize; currentReportFormDataModels = new ArrayList(); rowIndx++; } currentReportFormDataModels.add(reportFormDataModel); if (i == formExcelDataList.size()) { group.put(rowIndx, currentReportFormDataModels); } i++; } CellRangeAddress cellRangeAddress; Row row; Cell cellLabel; Cell cellData; for (Map.Entry> entry : group.entrySet()) { int key = entry.getKey(); int currentRow = initDataRow + key; row = sheet.createRow(currentRow); List value = entry.getValue(); int firstCol = 0; for (ReportFormData reportFormDataModel : value) { String label = reportFormDataModel.getLabel(); Object data = reportFormDataModel.getData(); int colSpan = reportFormDataModel.getColSpan(); cellLabel = row.createCell(firstCol); cellLabel.setCellValue(label); cellLabel.setCellStyle(labelCellStyle); sheet.setColumnWidth(cellLabel.getColumnIndex(), 30 * 256); firstCol = firstCol + 1; cellData = row.createCell(firstCol); cellData.setCellStyle(dataCellStyle); this.fillCellValue(cellData, data, sdf); sheet.setColumnWidth(cellData.getColumnIndex(), 30 * 256); cellRangeAddress = new CellRangeAddress(currentRow, currentRow, firstCol, firstCol + colSpan * 2 - 2); sheet.addMergedRegion(cellRangeAddress); this.setFormRegionStyle(sheet, cellRangeAddress, dataCellStyle); firstCol = firstCol + colSpan * 2 - 1; } } return group.keySet().size() + initDataRow; } private int buildGridExcelData(ReportGrid gridModel, Sheet sheet, int starDataRow, Map styles) { CellStyle dataAlignLeftStyle = styles .get(GridStyleType.dataAlignLeftStyle.name()); CellStyle dataAlignCenterStyle = styles .get(GridStyleType.dataAlignCenterStyle.name()); CellStyle dataAlignRightStyle = styles .get(GridStyleType.dataAlignRightStyle.name()); SimpleDateFormat sdf = ExportUtils.getSimpleDateFormat(); List bottomGridExcelHeader = new ArrayList(); this.calculateBottomColumnHeader(gridModel.getGridHeaderModelList(), bottomGridExcelHeader); List> excelDatas = gridModel.getGridDataModel() .getDatas(); String treeColumn = gridModel.getGridDataModel().getTreeColumn(); int excelDataIndex = 0; int rowSize = excelDatas.size(); Cell cell; Row row; for (int rowNum = starDataRow; rowNum <= starDataRow + rowSize - 1; rowNum++) { row = sheet.createRow(rowNum); //2022年9月28日 23:50:18 手动设置行高 row.setHeight(rowHeitht); Map map = excelDatas.get(excelDataIndex); int j = 0; for (ReportGridHeader header : bottomGridExcelHeader) { Object value = map.get(header.getColumnName()); int dataAlign = header.getDataAlign(); cell = row.createCell(j); if (dataAlign == 1) { cell.setCellStyle(dataAlignCenterStyle); } else if (dataAlign == 2) { cell.setCellStyle(dataAlignRightStyle); } else { cell.setCellStyle(dataAlignLeftStyle); } if (value != null) { if (header.getColumnName().equalsIgnoreCase(treeColumn)) { int level = this.calculateIndentationCount(value .toString()); cell.setCellStyle(new GridStyleBuilder() .createIndentationCellStyle( sheet.getWorkbook(), level == 0 ? 0 : level * 2)); cell.setCellValue(value.toString()); } else { if (value instanceof BigDecimal || value instanceof Float || value instanceof Double) { CellStyle style = cell.getCellStyle(); DataFormat format = sheet.getWorkbook() .createDataFormat(); String displayFormat = header.getDisplayFormat(); if (StringUtils.isEmpty(displayFormat)) style.setDataFormat(format.getFormat("#")); else style.setDataFormat(format .getFormat(displayFormat)); cell.setCellStyle(style); } this.fillCellValue(cell, value, sdf); } } else { cell.setCellValue(""); } // 2020年7月8日 17:11:03 注释掉原来的宽度计算 int columnWidth = sheet.getColumnWidth(cell.getColumnIndex()) / 256; int length; try { length = cell.toString().getBytes("GBK").length; if (columnWidth < length + 1) { columnWidth = length + 1; } } catch (UnsupportedEncodingException e) { System.out.println("Excel计算宽度异常:" + e.getMessage()); } sheet.setColumnWidth(cell.getColumnIndex(), columnWidth * 256); // sheet.setColumnWidth( // cell.getColumnIndex(), // header.getWidth() / 6 > 255 ? 254 * 256 : header // .getWidth() / 6 * 256); j++; } excelDataIndex++; } return starDataRow + rowSize; } private void setCellRangeAddressBorder(CellRangeAddress rangle, Sheet sheet) { int border = 1; Workbook wb = sheet.getWorkbook(); RegionUtil.setBorderBottom(border, rangle, sheet, wb); RegionUtil.setBorderLeft(border, rangle, sheet, wb); RegionUtil.setBorderRight(border, rangle, sheet, wb); RegionUtil.setBorderTop(border, rangle, sheet, wb); } private void setFormRegionStyle(Sheet sheet, CellRangeAddress ca, CellStyle cs) { for (int i = ca.getFirstRow(); i <= ca.getLastRow(); i++) { Row row = CellUtil.getRow(i, sheet); for (int j = ca.getFirstColumn(); j <= ca.getLastColumn(); j++) { Cell cell = CellUtil.getCell(row, j); cell.setCellStyle(cs); } } } private int calculateIndentationCount(String s) { int count = 0; for (int i = 0; i < s.length(); i++) { char temp = s.charAt(i); if (temp == '\u0009') { count++; } } return count; } }