合并策略

  1. public class ExcelMergeStrategy extends AbstractMergeStrategy {
  2. /**
  3. * 合并的列编号,从0开始,指定的index或自己按字段顺序数
  4. */
  5. private Set<Integer> mergeCellIndex = new HashSet<>();
  6. /**
  7. * 数据集大小,用于区别结束行位置
  8. */
  9. private Integer maxRow = 0;
  10. /**
  11. * 禁止无参声明
  12. */
  13. private ExcelMergeStrategy() {
  14. }
  15. public ExcelMergeStrategy(Integer maxRow, int... mergeCellIndex) {
  16. Arrays.stream(mergeCellIndex).forEach(item -> {
  17. this.mergeCellIndex.add(item);
  18. });
  19. this.maxRow = maxRow;
  20. }
  21. /**
  22. * 记录上一次合并的信息
  23. */
  24. private Map<Integer, MergeRange> lastRow = new HashedMap();
  25. /**
  26. * 每行每列都会进入,绝对不要在这写循环
  27. *
  28. * @param sheet
  29. * @param cell
  30. * @param head
  31. * @param relativeRowIndex
  32. */
  33. @Override
  34. protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
  35. int currentCellIndex = cell.getColumnIndex();
  36. String prefix = "";
  37. if (mergeCellIndex.contains(currentCellIndex)) {
  38. if(currentCellIndex> 0){
  39. Row row = cell.getRow();
  40. List<String> prefixList = new CopyOnWriteArrayList<>();
  41. for (int cellIndex = currentCellIndex -1; cellIndex >= 0; cellIndex--) {
  42. prefixList.add(row.getCell(cellIndex).getStringCellValue());
  43. }
  44. Collections.reverse(prefixList);
  45. prefix = String.join("", prefixList);
  46. }
  47. // 判断该行是否需要合并
  48. String currentCellValue = prefix + cell.getStringCellValue();
  49. int currentRowIndex = cell.getRowIndex();
  50. if (!lastRow.containsKey(currentCellIndex)) {
  51. // 记录首行起始位置
  52. lastRow.put(currentCellIndex, new MergeRange(currentCellValue, currentRowIndex, currentRowIndex, currentCellIndex, currentCellIndex));
  53. return;
  54. }
  55. //有上行这列的值了,拿来对比.
  56. MergeRange mergeRange = lastRow.get(currentCellIndex);
  57. if (!(mergeRange.lastValue != null && (mergeRange.lastValue).equals(currentCellValue))) {
  58. // 结束的位置触发下合并.
  59. // 同行同列不能合并,会抛异常
  60. if (mergeRange.startRow != mergeRange.endRow || mergeRange.startCell != mergeRange.endCell) {
  61. sheet.addMergedRegionUnsafe(new CellRangeAddress(mergeRange.startRow, mergeRange.endRow, mergeRange.startCell, mergeRange.endCell));
  62. }
  63. // 更新当前列起始位置
  64. lastRow.put(currentCellIndex, new MergeRange(currentCellValue, currentRowIndex, currentRowIndex, currentCellIndex, currentCellIndex));
  65. }
  66. // 合并行 + 1
  67. mergeRange.endRow += 1;
  68. // 结束的位置触发下最后一次没完成的合并
  69. if (relativeRowIndex.equals(maxRow - 1)) {
  70. MergeRange lastMergeRange = lastRow.get(currentCellIndex);
  71. // 同行同列不能合并,会抛异常
  72. if (lastMergeRange.startRow != lastMergeRange.endRow || lastMergeRange.startCell != lastMergeRange.endCell) {
  73. sheet.addMergedRegionUnsafe(new CellRangeAddress(lastMergeRange.startRow, lastMergeRange.endRow, lastMergeRange.startCell, lastMergeRange.endCell));
  74. }
  75. }
  76. }
  77. }
  78. public class MergeRange {
  79. public int startRow;
  80. public int endRow;
  81. public int startCell;
  82. public int endCell;
  83. public String lastValue;
  84. public MergeRange(String lastValue, int startRow, int endRow, int startCell, int endCell) {
  85. this.startRow = startRow;
  86. this.endRow = endRow;
  87. this.startCell = startCell;
  88. this.endCell = endCell;
  89. this.lastValue = lastValue;
  90. }
  91. }
  92. }

表头颜色策略

  1. public class HeadTwoColorStyleWriteStrategy extends AbstractCellStyleStrategy {
  2. private Workbook workbook;
  3. /**
  4. * 颜色分割点
  5. */
  6. private Integer pointIndex;
  7. private Integer pointIndex2;
  8. /**
  9. * 头的高度
  10. */
  11. private Integer headHeight;
  12. @Override
  13. protected void initCellStyle(Workbook workbook) {
  14. this.workbook=workbook;
  15. }
  16. public HeadTwoColorStyleWriteStrategy(Integer pointIndex, Integer pointIndex2){
  17. //设置投高度默认
  18. this.headHeight = 2;
  19. this.pointIndex = pointIndex;
  20. this.pointIndex2 = pointIndex2;
  21. }
  22. public HeadTwoColorStyleWriteStrategy(Integer headHeight,Integer pointIndex, Integer pointIndex2){
  23. this.headHeight = headHeight;
  24. this.pointIndex = pointIndex;
  25. this.pointIndex2 = pointIndex2;
  26. }
  27. /**
  28. * 设置表格头样式
  29. * @param cell
  30. * @param head
  31. * @param relativeRowIndex
  32. */
  33. @Override
  34. protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
  35. if ( relativeRowIndex < headHeight) {
  36. int columnIndex = cell.getColumnIndex();
  37. WriteCellStyle writeCellStyle=new WriteCellStyle();
  38. WriteFont headWriteFont = new WriteFont();
  39. headWriteFont.setColor(IndexedColors.WHITE.getIndex());
  40. writeCellStyle.setWriteFont(headWriteFont);
  41. // WriteCellStyle转换为CellStyle
  42. CellStyle headCellStyle = StyleUtil.buildHeadCellStyle(workbook, writeCellStyle);
  43. XSSFCellStyle cellStyle = (XSSFCellStyle)headCellStyle;
  44. if(columnIndex < pointIndex){
  45. cellStyle.setFillForegroundColor(getRGBColor(0, 51, 102));
  46. }else if (columnIndex < pointIndex2){
  47. cellStyle.setFillForegroundColor(getRGBColor(0, 112, 192));
  48. }else {
  49. cellStyle.setFillForegroundColor(getRGBColor(146, 208, 80));
  50. }
  51. cell.setCellStyle(cellStyle);
  52. }
  53. }
  54. @Override
  55. protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
  56. }
  57. /**
  58. * 得到RBG自定义颜色
  59. *
  60. * @param redNum 红色数值
  61. * @param greenNum 绿色数值
  62. * @param blueNum 蓝色数值
  63. * @return
  64. */
  65. public static XSSFColor getRGBColor(int redNum, int greenNum, int blueNum) {
  66. XSSFColor color = new XSSFColor(new byte[]{(byte) redNum, (byte) greenNum, (byte) blueNum}, new DefaultIndexedColorMap());
  67. return color;
  68. }
  69. }

链接转跳和文本转跳策略

public class HyperlinkExcelStrategy implements CellWriteHandler {
    /**
     * 行
     */
    private Integer row;
    /**
     * 列
     */
    private Integer col;
    /**
     * type 类型 HyperlinkType 参考该枚举
     */
    private HyperlinkType type;
    /**
     * 要替换成该 链接
     */
    private String link;

    /**
     * 第几列添加链接
     * @param col
     * @param link
     * @param type 类型 HyperlinkType.DOCUMENT
     */
    public HyperlinkExcelStrategy(Integer col,String link,HyperlinkType type){
        this.col = col;
        this.link = link;
        this.type = type;
    }
    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        if (!isHead){
            int columnIndex = cell.getColumnIndex();
            //等于当前列是添加链接 或链接文档
            if (columnIndex== this.col){
                CreationHelper helper=writeSheetHolder.getSheet().getWorkbook().getCreationHelper();
                Hyperlink hyperlink=helper.createHyperlink(type);
                hyperlink.setAddress(this.link);
                cell.setHyperlink(hyperlink);
            }
        }
    }
}

自定义表头宽度策略策略

public class CustomCellWriteHandler extends AbstractColumnWidthStyleStrategy {


    private Map<Integer, Map<Integer, Integer>> CACHE = new HashMap<>(64);

    private Integer dataLength(List<CellData> cellDataList, Cell cell, Boolean isHead) {
        if (Boolean.TRUE.equals(isHead)) {
            return cell.getStringCellValue().getBytes().length;
        } else {
            CellData cellData = cellDataList.get(0);
            CellDataTypeEnum type = cellData.getType();
            if (type == null) {
                return -1;
            } else {
                switch (type) {
                    case STRING:
                        return cellData.getStringValue().getBytes().length;
                    case BOOLEAN:
                        return cellData.getBooleanValue().toString().getBytes().length;
                    case NUMBER:
                        return cellData.getNumberValue().toString().getBytes().length;
                    default:
                        return -1;
                }
            }
        }
    }

    @Override
    protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        if (isHead || !CollectionUtils.isEmpty(cellDataList)) {
            Map<Integer, Integer> maxColumnWidthMap = CACHE.get(writeSheetHolder.getSheetNo());
            if (CollectionUtils.isEmpty(maxColumnWidthMap)) {
                maxColumnWidthMap = new HashMap<>();
                CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
            }

            Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
            if (columnWidth >= 0) {
                if (columnWidth > 255) {
                    columnWidth = 255;
                }
                Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
                if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
                    maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
                    writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256);
                }
            }
        }
    }
}