All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.thomas.alib.excel.exporter.ExcelExportSheetItem Maven / Gradle / Ivy

package com.thomas.alib.excel.exporter;

import com.thomas.alib.excel.annotation.ExcelSheet;
import com.thomas.alib.excel.enums.SortType;
import com.thomas.alib.excel.utils.CollectionUtils;
import com.thomas.alib.excel.utils.ReflectUtil;
import com.thomas.alib.excel.utils.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * Excel导出对应每个工作表(Sheet)的解析工具
 *
 * @param  数据源对象类型泛型
 */
public class ExcelExportSheetItem> implements AutoCloseable {
    private static final Logger logger = LoggerFactory.getLogger(ExcelExportSheetItem.class);
    /**
     * excel导出构建对象
     */
    private EE excelExporter;
    /**
     * 数据源列表
     */
    private List sourceList;
    /**
     * sheet数据类型对象
     */
    private Class sheetDataClazz;
    /**
     * sheet名称
     */
    private String sheetName;
    /**
     * 本sheet是否显示序号
     */
    private boolean showIndex;
    /**
     * 列排序方式
     */
    private SortType columnSortType;

    /**
     * 表头行高度,默认-1不设置
     */
    private short headRowHeight;

    /**
     * 数据行高度,默认-1不设置
     */
    private short dataRowHeight;
    /**
     * sheet页中通用表头行样式
     */
    private XSSFCellStyle sheetHeadStyle;
    /**
     * sheet页中通用数据行样式
     */
    private XSSFCellStyle sheetDataStyle;
    /**
     * 全部的成员列表
     */
    private List totalFieldList;
    /**
     * 全部的成员对应的excel列信息列表
     */
    private List excelColumnList;
    /**
     * 本sheet页对象
     */
    Sheet mySheet;

    /**
     * 构造方法
     *
     * @param excel_exporter   excel导出构建对象
     * @param source_list      数据源列表
     * @param sheet_data_clazz 数据源泛型class
     * @param show_index       是否显示序号
     * @param sheet_name       外部设置的sheet名称,如果有值,则此值优先级比注解内的高
     */
    ExcelExportSheetItem(EE excel_exporter, List source_list, Class sheet_data_clazz, Boolean show_index, String sheet_name) {
        excelExporter = excel_exporter;
        sourceList = source_list;
        //获取数据类型
        sheetDataClazz = sheet_data_clazz;
        if (sheetDataClazz == null) throw new RuntimeException("获取导出数据类型失败");
        //取得表格sheet相关注解
        ExcelSheet excel_sheet = sheetDataClazz.getAnnotation(ExcelSheet.class);
        //判断是否传入了sheet_name,传入的参数值优先级更高,单独判断处理
        if (StringUtils.isEmpty(sheet_name)) {
            if (excel_sheet == null) {//未设置,设置默认值
                sheetName = sheetDataClazz.getSimpleName();
            } else {//已设置,取出设置的值
                sheetName = excel_sheet.sheetName();
            }
        } else {
            sheetName = sheet_name;
        }
        //判断是否传入了show_index,传入的参数值优先级更高,单独判断处理
        if (show_index == null) {//如果需要显示序号,则添加序号
            if (excel_sheet == null) {//未设置,设置默认值
                showIndex = true;
            } else {//已设置,取出设置的值
                showIndex = excel_sheet.showIndex();
            }
        } else {
            showIndex = show_index;
        }
        //表头样式处理
        ExcelExportStyleProcessor head_style_processor;
        //数据样式处理
        ExcelExportStyleProcessor data_style_processor;
        //表格sheet注解判空区分处理
        if (excel_sheet == null) {
            //未设置sheet注解,设置默认值
            columnSortType = SortType.S2B;//列排序方式,默认由小到大排序
            headRowHeight = -1;//表头行高度,默认-1不设置
            dataRowHeight = -1;//数据行高度,默认-1不设置
            head_style_processor = null;
            data_style_processor = null;
        } else {
            //已设置sheet注解,取出设置的值
            columnSortType = excel_sheet.columnSortType();//列排序方式
            headRowHeight = excel_sheet.headRowHeight();//表头行高度
            dataRowHeight = excel_sheet.dataRowHeight();//数据行高度
            //读取表头行样式
            head_style_processor = ExcelExportStyleProcessor.read(excel_sheet.baseStyle()).coverBySourceExceptNotSet(excel_sheet.headStyle());
            sheetHeadStyle = head_style_processor.createXSSFCellStyle(excelExporter.sxssfWorkbook);
            //读取数据行样式
            data_style_processor = ExcelExportStyleProcessor.read(excel_sheet.baseStyle()).coverBySourceExceptNotSet(excel_sheet.dataStyle());
            sheetDataStyle = data_style_processor.createXSSFCellStyle(excelExporter.sxssfWorkbook);
        }
        //根据解析信息创建excel数据
        mySheet = excelExporter.sxssfWorkbook.createSheet(sheetName());//创建sheet对象
        //解析全部成员属性
        totalFieldList = ReflectUtil.getAccessibleFieldIncludeSuper(sheetDataClazz);//全部的成员列表
        excelColumnList = new ArrayList<>();//解析成员为excel列信息列表
        for (Field item_field : totalFieldList) {//遍历寻找所有有效column成员
            ExcelExportColumnItem column = new ExcelExportColumnItem(item_field, excelExporter.sxssfWorkbook, head_style_processor, data_style_processor);
            if (column.isValid()) //有效
                excelColumnList.add(column);
        }
        //给列排序
        columnSortType.sort(excelColumnList);
    }

    /**
     * 写入表头行
     */
    private void writeHeadRow() {
        //外部给每行操作的列计数,因为是否自动显示序号会影响起始位置
        int row_column_index = 0;
        //创建并填充表头信息
        Row headRow = mySheet.createRow(0);//创建表头
        //设置表头行高
        if (headRowHeight > 0) headRow.setHeight(headRowHeight);
        if (showIndex) {//如果需要默认显示序号
            Cell cell = headRow.createCell(row_column_index);
            cell.setCellValue("序号");
            if (sheetHeadStyle != null) cell.setCellStyle(sheetHeadStyle);
            mySheet.setColumnWidth(row_column_index, 3000);
            row_column_index++;
        }
        for (ExcelExportColumnItem column : excelColumnList) {
            Cell cell = headRow.createCell(row_column_index);
            cell.setCellValue(column.getHeadName());
            if (column.getColumnHeadStyle() != null) {
                cell.setCellStyle(column.getColumnHeadStyle());
            } else if (sheetHeadStyle != null) {
                cell.setCellStyle(sheetHeadStyle);
            }
            mySheet.setColumnWidth(row_column_index, column.getColumnWidth());
            row_column_index++;
        }
        logger.debug("表头行处理完成");
    }

    /**
     * 写入数据行
     */
    private void writeDataRow() {
        if (!CollectionUtils.isEmpty(sourceList)) {
            //外部给每行操作的列计数,因为是否自动显示序号会影响起始位置
            int row_column_index;
            //创建并填充每行数据信息
            for (int i = 0; i < sourceList.size(); i++) {//创建每一行数据
                int row_index = i + 1;//行序号
                T item_source = sourceList.get(i);//逐个取出数据源
                Row dataRow = mySheet.createRow(row_index);//创建数据行
                //设置数据行高
                if (dataRowHeight > 0) dataRow.setHeight(dataRowHeight);
                row_column_index = 0;//每新开始一行,重置row计数
                if (showIndex) {//如果需要默认显示序号
                    Cell cell = dataRow.createCell(row_column_index);
                    cell.setCellValue(row_index);
                    if (sheetDataStyle != null) cell.setCellStyle(sheetDataStyle);
                    row_column_index++;
                }
                for (ExcelExportColumnItem column : excelColumnList) {
                    Cell cell = dataRow.createCell(row_column_index);
                    if (column.isPicture()) {
                        try {
                            byte[] pictureBytes = column.getColumnPictureBytesFromSource(item_source, row_index);
                            if (pictureBytes == null) {
                                cell.setCellValue("图片: " + column.getColumnValueFromSource(item_source, row_index) + "  加载失败");
                            } else {
                                Drawing drawing = mySheet.getDrawingPatriarch();
                                if (drawing == null) drawing = mySheet.createDrawingPatriarch();
                                ClientAnchor clientAnchor = drawing.createAnchor(0, 0, 0, 0, row_column_index, row_index, row_column_index + 1, i + 2);
                                int addPicture = excelExporter.sxssfWorkbook.addPicture(pictureBytes, SXSSFWorkbook.PICTURE_TYPE_JPEG);
                                Picture picture = drawing.createPicture(clientAnchor, addPicture);
                                picture.getPictureData();
                            }
                        } catch (Throwable e) {
                            logger.error("表格\"" + column.getHeadName() + "\"列-第" + row_index + "行-绘制图片时发生错误:", e);
                            cell.setCellValue("图片: " + column.getColumnValueFromSource(item_source, row_index) + "  绘制失败");
                        }
                    } else {
                        cell.setCellValue(column.getColumnValueFromSource(item_source, row_index));
                    }
                    if (column.getColumnDataStyle() != null) {
                        cell.setCellStyle(column.getColumnDataStyle());
                    } else if (sheetDataStyle != null) {
                        cell.setCellStyle(sheetDataStyle);
                    }
                    row_column_index++;
                }
                logger.debug("表格第" + row_index + "行处理完成");
            }
        }
        logger.debug("数据行处理完成");
    }

    /**
     * 初始化sheet并设置数据到sheet中
     */
    void writeData() {
        logger.debug(sheetName() + "sheet页签准备处理数据");
        writeHeadRow();
        writeDataRow();
        logger.debug(sheetName() + "sheet页签数据处理完成");
    }

    /**
     * 获取sheet名
     *
     * @return sheet名
     */
    String sheetName() {
        if (StringUtils.isEmpty(sheetName)) {
            return String.valueOf(System.currentTimeMillis());
        } else {
            return sheetName;
        }
    }

    /**
     * 结束当前创建的sheet页签对象的方法调用,返回导出者,继续后续导出操作
     * (目前暂无实际业务场景,为未来扩展预留的方法)
     *
     * @return 导出者
     */
    public EE over() {
        return excelExporter;
    }

    /**
     * 关闭,目前用于清空所有对象引用,防止内存泄漏
     */
    @Override
    public void close() {
        excelExporter = null;
        sourceList = null;
        sheetDataClazz = null;
        sheetName = null;
        showIndex = false;
        columnSortType = null;
        headRowHeight = -1;
        dataRowHeight = -1;
        sheetHeadStyle = null;
        sheetDataStyle = null;
        if (totalFieldList != null) {
            totalFieldList.clear();
        }
        totalFieldList = null;
        if (excelColumnList != null) {
            excelColumnList.forEach(ExcelExportColumnItem::close);
            excelColumnList.clear();
        }
        excelColumnList = null;
        mySheet = null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy