hutool导出excel支持下拉框数据超255字符

hutool导出excel支持下拉框数据超255字符

java 复制代码
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import com.ibmp.common.annotation.Excel;
import com.ibmp.common.constant.ExcelConsts;
import com.ibmp.common.exception.CustomException;
import com.ibmp.common.utils.file.FileTypeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
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.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Mr丶s
 * @date 2021/7/26 2:18 下午
 * @description
 */
@Slf4j
public class ExcelUtils {

    /**
     * 导出
     *
     * @param mergeColumn 合并多少列
     * @param mergeText   合并单元格内文字
     * @param list        需要导出的list
     * @param excelName   导出的文件名称
     * @param clazz       实体类 对应list
     * @param response
     */
    public static void export(int mergeColumn, String mergeText, List<Map<Object, Object>> maps, List<?> list, String excelName, Class clazz, HttpServletResponse response) {
        try {
            if (!list.isEmpty()) {
                if (!list.get(0).getClass().equals(clazz)) {
                    log.error("数据类型与传入的集合数据类型不一致!数据类型:{}; 集合数据类型:{}", clazz, list.get(0).getClass());
                    throw new Exception("数据类型与传入的集合数据类型不一致!");
                } else {
                    ExcelWriter writer = ExcelUtil.getBigWriter();
                    // 获取当前类字段
                    Field[] fields = clazz.getDeclaredFields();
                    // 字段名称集合
                    List<String> fieldNames = new ArrayList<>();
                    // 字段中文名称集合(获取实体中@Excel注解name的值)
                    List<String> cnNames = new ArrayList<>();
                    for (Field field : fields) {
                        if (!field.isAccessible()) {
                            // 关闭反射访问安全检查,为了提高速度
                            field.setAccessible(true);
                        }
                        String fieldName = field.getName();
                        // 排除ID和序号
                        if (!"sid".equals(fieldName) && !"serialVersionUID".equals(fieldName) && !"ordernum".equals(fieldName)) {
                            fieldNames.add(fieldName);
                        }
                        // 判断是否有@Excel
                        boolean annotationPresent = field.isAnnotationPresent(Excel.class);
                        if (annotationPresent && !"sid".equals(fieldName)) {
                            String name = field.getAnnotation(Excel.class).name();
                            cnNames.add(name);
                        }
                    }
                    String[] fs = fieldNames.toArray(new String[0]);
                    String[] ns = cnNames.toArray(new String[0]);
                    for (int i = 0; i < ns.length; i++) {
                        // 设置表头及字段名
                        writer.addHeaderAlias(fs[i], ns[i]);
                    }
                    // 自动换行
                    Workbook workbook = writer.getWorkbook();
//                    Map<Object, Object>map1 = new HashMap<>();
//                    map1.put("cellNo",14);
//                    List<String> strings = new ArrayList<>();
//                    strings.add("cc1");
//                    strings.add("cc2");
//                    strings.add("cc3");
//                    strings.add("cc4");
//                    strings.add("cc5");
//                    map1.put("cellList", strings);
//                    maps.set(6, map1);
                    //设置下拉数据
                    if (CollectionUtils.isNotEmpty(maps)) {
                        int index = 0;
                        for (Map<Object, Object> map : maps) {
                            Integer cellNo = (int) map.get("cellNo");
                            List<Object> cellList = (List<Object>) map.get("cellList");
                            index = index + 1;
                            selectListMore("sheet00" + cellNo, index, workbook, cellNo, cellNo, cellList.toArray(new String[cellList.size()]));
                        }

                    }
                    //合并单元格
                    if (mergeColumn != -1) {
                        writer.merge(mergeColumn, mergeText);
                    }

                    CellStyle headCellStyle = writer.getCellStyle();
                    //设置内容字体
                    Font font = writer.createFont();
                    //设置字体
                    font.setFontName("宋体");
                    //加粗
                    // font.setBold(true);
                    //设置标题字体大小
                    font.setFontHeightInPoints((short) 15);
                    headCellStyle.setFont(font);

                    StyleSet styleSet = new StyleSet(workbook);
                    styleSet.setWrapText();
                    writer.setStyleSet(styleSet);

                    writer.write(list, true);
                    writer.autoSizeColumnAll();
                    //冻结行数 2-前两行
                    writer.setFreezePane(2);
                    ServletOutputStream out = response.getOutputStream();
                    try {
                        for (int i = 0; i < fieldNames.size(); i++) {
                            writer.setColumnWidth(i, 23);
                        }
                        //设置头部
                        response.setContentType(ExcelConsts.CONTENT_TYPE);

                        String ecodeFileName = URLEncoder.encode(excelName, "UTF-8");
                        response.setHeader(ExcelConsts.HEADER_S, ExcelConsts.RESPONSE_HEADER + ecodeFileName + ".xlsx");
                        writer.flush(out, true);
                        writer.close();
                        IoUtil.close(out);
                    } catch (IOException e) {
                        log.error(e.getMessage());
                        e.printStackTrace();
                    }
                }
            } else {
                log.error("数据集合为空");
                throw new Exception("数据集合为空");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * excel下拉框
     *
     * @param sheetName
     * @param index     隐藏的sheet编号(例如1,2,3),多个下拉数据不能使用同一个
     * @param workbook
     * @param firstCol  区域中第一个单元格的列号 (下标0开始)
     * @param lastCol   区域中最后一个单元格的列号
     * @param dataArray 下拉内容
     */
    public static void selectListMore(String sheetName, Integer index, Workbook workbook, int firstCol, int lastCol, String[] dataArray) {
        //将下拉框数据放到新的sheet里,然后excle通过新的sheet数据加载下拉框数据
        Sheet hidden = workbook.createSheet(sheetName);
        //创建单元格对象
        Cell cell = null;
        //遍历我们上面的数组,将数据取出来放到新sheet的单元格中
        for (int i = 0, length = dataArray.length; i < length; i++) {
            //取出数组中的每个元素
            String name = dataArray[i];
            //根据i创建相应的行对象(说明我们将会把每个元素单独放一行)
            Row row = hidden.createRow(i);
            //创建每一行中的第一个单元格
            cell = row.createCell(0);
            //然后将数组中的元素赋值给这个单元格
            cell.setCellValue(name);
        }
        // 创建名称,可被其他单元格引用
        Name namedCell = workbook.createName();
        namedCell.setNameName(sheetName);
        // 设置名称引用的公式
        namedCell.setRefersToFormula(sheetName + "!$A$1:$A$" + dataArray.length);
        String range = sheetName + "!$A$1:$A$" + dataArray.length;
        //加载数据,将名称为hidden的sheet中的数据转换为List形式
        // DVConstraint constraint = DVConstraint.createFormulaListConstraint(sheetName);

        // 设置第一列的3-65534行为下拉列表
        // (3, 65534, 2, 2) ====> (起始行,结束行,起始列,结束列)
        CellRangeAddressList regions = new CellRangeAddressList(0, 1000000, firstCol, lastCol);
        DataValidationHelper dataValidationHelper = hidden.getDataValidationHelper();
        // 数据长度低于100正常录入 超过100 改为编写公式引用
        if (dataArray.length < 100 ) {
            // 将设置下拉选的位置和数据的对应关系 绑定到一起
            // DataValidation dataValidation = new HSSFDataValidation(regions, constraint);
            DataValidationConstraint constraint = dataValidationHelper.createExplicitListConstraint(dataArray);
            DataValidation dataValidation = dataValidationHelper.createValidation(constraint, regions);

            //将数据赋给下拉列表
            workbook.getSheetAt(0).addValidationData(dataValidation);
        }else {
            DataValidationConstraint dvConstraint = dataValidationHelper.createFormulaListConstraint(range);
            DataValidation dataValidation = dataValidationHelper.createValidation(dvConstraint, regions);
            workbook.getSheetAt(0).addValidationData(dataValidation);
        }
        //将第二个sheet设置为隐藏
        workbook.setSheetHidden(index, true);
    }


    /**
     * 导入
     *
     * @param file
     * @param sheet
     * @param clazz
     * @return
     */
    public static ExcelReader read(MultipartFile file, Integer sheet, Class clazz) {
        return readCommon(file, sheet, clazz);
    }

    /**
     * 导入
     *
     * @param file
     * @param clazz
     * @return
     */
    public static ExcelReader read(MultipartFile file, Class clazz) {
        return readCommon(file, 0, clazz);
    }

    /**
     * 导入
     *
     * @param file
     * @param clazz
     * @return
     */
    public static ExcelReader readCommon(MultipartFile file, Integer sheet, Class clazz) {
        try {
            InputStream inputStream = file.getInputStream();
            if (!isExcelFile(file)) {
                throw new CustomException("文件名格式不正确, 请使用后缀名为.xlsx的文件");
            }
            ExcelReader reader = ExcelUtil.getReader(inputStream, sheet);

            // 获取当前类字段
            Field[] fields = clazz.getDeclaredFields();
            // 字段名称集合
            List<String> fieldNames = new ArrayList<>();
            // 字段中文名称集合(获取实体中@Excel注解name的值)
            List<String> cnNames = new ArrayList<>();
            for (Field field : fields) {
                if (!field.isAccessible()) {
                    // 关闭反射访问安全检查,为了提高速度
                    field.setAccessible(true);
                }
                String fieldName = field.getName();
                // 排除ID和序号
                if (!"sid".equals(fieldName) && !"serialVersionUID".equals(fieldName) && !"ordernum".equals(fieldName)) {
                    fieldNames.add(fieldName);
                }
                // 判断是否有@Excel
                boolean annotationPresent = field.isAnnotationPresent(Excel.class);
                if (annotationPresent && !"sid".equals(fieldName)) {
                    String name = field.getAnnotation(Excel.class).name();
                    cnNames.add(name);
                }
            }
            String[] fs = fieldNames.toArray(new String[0]);
            String[] ns = cnNames.toArray(new String[0]);
            for (int i = 0; i < fs.length; i++) {
                // 设置表头及字段名
                reader.addHeaderAlias(ns[i], fs[i]);
            }
            return reader;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 读取sheet数
     *
     * @param file
     * @return
     */
    public static Workbook readExcelSheet(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            if (!isExcelFile(file)) {
                throw new CustomException("文件名格式不正确, 请使用后缀名为.xlsx的文件");
            }
            ExcelReader reader = ExcelUtil.getReader(inputStream);
            return reader.getWorkbook();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 是否为Excel文件
     *
     * @param file 表单文件
     * @return 文件格式是否正确
     */
    public static boolean isExcelFile(MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            throw new CustomException("文件不能为空");
        }
        String filename = file.getOriginalFilename();
        String header = FileTypeUtils.getFileHeader(file.getInputStream());
        return (filename.endsWith(ExcelConsts.EXCEL_VERSION_XLSX) || filename.endsWith(ExcelConsts.EXCEL_VERSION_XLS)) &&
                (header.contains(ExcelConsts.XLS_HEADER) || header.contains(ExcelConsts.XLSX_HEADER));
    }


    public static Workbook getXSSFWorkbook(String sheetName, String[] title, String[][] values, Workbook wb) {
        return getXSSFWorkbook(sheetName, title, null, values, wb);
    }

    public static Workbook getXSSFWorkbook(String sheetName, String[] title, int[] width, String[][] values, Workbook wb) {

        // 第一步,创建一个HSSFWorkbook,对应一个Excel文件
        if (wb == null) {
            wb = new XSSFWorkbook();
        }

        // 第二步,在workbook中添加一个sheet,对应Excel文件中的sheet
        Sheet sheet = wb.createSheet(sheetName);
        sheet.createFreezePane(0, 1, 0, 1);
        // 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制
        Row row = sheet.createRow(0);

        // 第四步,创建单元格,并设置值表头 设置表头居中
        CellStyle style = wb.createCellStyle();
        Font font = wb.createFont();
        font.setBold(true);
        style.setFont(font);

        //声明列对象
        Cell cell;

        //创建标题
        for (int i = 0; i < title.length; i++) {
            cell = row.createCell(i);
            cell.setCellValue(title[i]);
            cell.setCellStyle(style);
            if (width != null) {
                sheet.setColumnWidth(i, width[i]);
            }
        }
        String s;
        //创建内容
        for (int i = 0; i < values.length; i++) {
            row = sheet.createRow(i + 1);
            for (int j = 0; j < values[i].length; j++) {
                //将内容按顺序赋给对应的列对象
                s = values[i][j];
                s = StringUtils.isBlank(s) ? "" : (StringUtils.equals("null", s) ? "" : s);
                row.createCell(j).setCellValue(s);
            }
        }
        return wb;
    }

    public static void margeCell(Sheet sheet, int startRow, int colNum) {
        String content = "";
        int index = startRow;
        for (int i = startRow; i <= sheet.getLastRowNum(); i++) {
            String value = sheet.getRow(i).getCell(colNum).getStringCellValue();
            if (!StringUtils.equals(content, value)) {
                if (i - index > 1) {
                    CellRangeAddress region = new CellRangeAddress(index, i - 1, colNum, colNum);
                    sheet.addMergedRegion(region);
                }
                index = i;
                content = value;
            } else {
                if (i == sheet.getLastRowNum() && i - index > 1) {
                    CellRangeAddress region = new CellRangeAddress(index, i, colNum, colNum);
                    sheet.addMergedRegion(region);
                }
            }
        }
    }


    /**
     * 设置 response
     *
     * @param response
     * @param fileName
     * @throws UnsupportedEncodingException
     */
    public static void setResponse(HttpServletResponse response, String fileName) throws UnsupportedEncodingException {
        // 配置文件下载
        response.setHeader("content-type", "application/octet-stream");
        response.setContentType("application/octet-stream");
        // 下载文件能正常显示中文
        String _filaName = new String((fileName + ".xlsx").getBytes("gb2312"), "iso8859-1");
        response.setHeader("Content-disposition", "attachment;filename=" + _filaName);
    }
}
相关推荐
愿你天黑有灯下雨有伞18 小时前
Java使用FastExcel实现Excel文件导入
java·excel
爆爆凯18 小时前
Excel 导入导出工具类文档
java·excel
凌康ACG1 天前
springboot打包二次压缩Excel导致损坏
spring boot·后端·excel
诸葛大钢铁2 天前
Excel转PDF的三种方法
笔记·职场和发展·pdf·excel
小小薛定谔2 天前
java操作Excel两种方式EasyExcel 和POI
java·python·excel
CodeCraft Studio2 天前
DHTMLX Suite 9.2 重磅发布:支持历史记录、类Excel交互、剪贴板、拖放增强等多项升级
javascript·excel·交互·表格·dhtmlx·grid·网格
小阳睡不醒2 天前
小白成长之路-Elasticsearch 7.0 配置
大数据·elasticsearch·excel
奋进的孤狼2 天前
【Excel】使用vlookup函数快速找出两列数据的差异项
excel
不讲废话的小白2 天前
解锁高效Excel技能:摆脱鼠标,快速编辑单元格
计算机外设·excel
CodeCraft Studio2 天前
Excel处理控件Aspose.Cells教程:使用 Python 在 Excel 中创建甘特图
python·excel·项目管理·甘特图·aspose·aspose.cells