ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java Excel 文件导出导入

2022-07-15 19:33:17  阅读:130  来源: 互联网

标签:style Java String Excel value 导入 workbook new textValue


特点:

支持xls、xlsx格式;

导出时支持自定义表格标题和表格数据,支持一个文档里多个Sheet;

 

依赖:

        <!--excel util-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.2</version>
        </dependency>
maven

代码:

/** 工具类,用于将数据导出到excel文件(可以导出到一个文件的多个Sheet) 或 从excel文件读取数据 */
@Slf4j
public class ExcelUtil {

    public static void main(String[] args) throws IOException {
        String fileName = "test.xls";
        exportExcel(
                Arrays.asList(
                        new SheetInfo<StuExpDownloadVO>(
                                "class1", ("用户名, 姓名, 完成情况, 得分, 评语").split(","),
                                Arrays.asList(new StuExpDownloadVO("zhangsna", "张三", "未开始", 22.0, "good"), new StuExpDownloadVO("lisi", "李四", "进行中", 21.0, "bad"))
                        ),
                        new SheetInfo<StuExpDownloadVO>(
                                "class2", ("用户名, 姓名, 完成情况").split(","), Arrays.asList(new StuExpDownloadVO("wangwu", "王五", "已完成", 20.0, "good"), new StuExpDownloadVO("zhaoliu", "赵六", "未开始", 19.0, "bad"))
                        )
                ), Files.newOutputStream(Paths.get("a.xls")));

        exportExcel(
                ("用户名, 姓名, 完成情况, 得分, 评语").split(","),
                Arrays.asList(new StuExpDownloadVO("zhangsna", "张三", "未开始", 22.0, "good"), new StuExpDownloadVO("lisi", "李四", "进行中", 21.0, "bad")),
                Files.newOutputStream(Paths.get("b.xls")));
    }

    private ExcelUtil() {
    }

    private static final String datetimeFormat = "yyyy-MM-dd HH:mm:ss";

    /**
     * @see {@link #exportExcel(String[] headers, Collection dataset, OutputStream out, String datetimeFormat) }
     */
    public static <T> void exportExcel(String[] headers, Collection<T> dataSet, OutputStream out) {
        exportExcel(headers, dataSet, out, datetimeFormat);
    }


    /**
     * 利用JAVA的反射机制,将放置在JAVA集合中并且符合一定条件的数据以EXCEL的形式输出到指定输出流。<br>
     * <br>
     * <b>输出后会关闭输出流</b>
     *
     * @param headers        表格属性列名数组。注意:数组中列名的顺序须与待导出的javabean属性的定义顺序一致
     * @param dataset        需要显示的数据集合,集合中java bean对象的所有非继承属性的值均会被输出。此方法支持的
     *                       javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据)
     * @param out            与输出设备关联的流对象,可以将 EXCEL 文档导出到本地文件或者网络中
     * @param datetimeFormat 如果有时间数据,设定输出格式。
     */
    public static <T> void exportExcel(String[] headers, Collection<T> dataset, OutputStream out, String datetimeFormat) {
        exportExcel(Arrays.asList(new SheetInfo("sheet 0", headers, dataset)), out, datetimeFormat);
    }

    public static <T> void exportExcel(List<SheetInfo<T>> sheetInfos, OutputStream out) {
        exportExcel(sheetInfos, out, datetimeFormat);
    }

    /**
     * 利用JAVA的反射机制,将放置在JAVA集合中并且符合一定条件的数据以EXCEL的形式输出到指定输出流。<br>
     * <br>
     * <b>输出后会关闭输出流</b>
     *
     * @param sheetInfos         EXCEL 文档中的Sheet信息定义
     * @param out            与输出设备关联的流对象,可以将 EXCEL 文档导出到本地文件或者网络中
     * @param datetimeFormat 如果有时间数据,设定输出格式。
     */
    public static <T> void exportExcel(List<SheetInfo<T>> sheetInfos, OutputStream out, String datetimeFormat) {
        sheetInfos = Optional.ofNullable(sheetInfos).orElse(Collections.emptyList());
        // 生成Excel文档
        Workbook workbook = generateWorkbook();
        // 生成表头样式
        CellStyle tableHeaderStyle = generateTableHeaderStyle(workbook);
        // 生成表体样式
        CellStyle tableBodyStyle = generateTableBodyStyle(workbook);
        // 时间值格式化工具
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern(datetimeFormat);
        // 生成Excel文档中的sheet
        for (int siIndex = 0; siIndex < sheetInfos.size(); siIndex++) {
            SheetInfo sheetInfo = sheetInfos.get(siIndex);
            String[] headers = sheetInfo.getHeaders();
            //创建sheet
            Sheet sheet = workbook.createSheet();
            workbook.setSheetName(siIndex, sheetInfo.getName());
            sheet.setDefaultColumnWidth(18);
            // 声明一个绘制图片的顶级管理器
            Drawing patriarch = sheet.createDrawingPatriarch();
            // 定义注释的大小和位置
            // HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0,
            // 0, 0, 0, (short) 4, 2, (short) 6, 5));
            // 设置注释内容
            // comment.setString(new HSSFRichTextString("可以在POI中添加注释!"));
            // 设置注释作者,当鼠标移动到单元格上是可以在状态栏中看到该内容.
            // comment.setAuthor("sensetime");

            // 填充表格标题行
            int rowIndex = 0;
            Row row = sheet.createRow(rowIndex);
            for (int i = 0; i < headers.length; i++) {
                Cell cell = row.createCell(i);
                cell.setCellStyle(tableHeaderStyle);
                cell.setCellValue(generateRichTextString(headers[i]));
            }
            rowIndex++;

            // 填充表格数据行
            Iterator<T> rowDataIt = sheetInfo.getDataset().iterator();
            Field[] fields = null;
            while (rowDataIt.hasNext()) {
                row = sheet.createRow(rowIndex);
                T t = (T) rowDataIt.next();
                // 利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值
                if (null == fields) {
                    fields = t.getClass().getDeclaredFields();
                }
                for (int i = 0; i < fields.length && i < headers.length; i++) {
                    //HSSFCell cell = row.createCell(i);
                    Cell cell = row.createCell(i);
                    cell.setCellStyle(tableBodyStyle);

                    Field field = fields[i];
                    field.setAccessible(true);
                    try {
                        Object value = field.get(t);
                        // 判断值的类型后进行强制类型转换
                        String textValue = null;
                        // if (value instanceof Integer) {
                        // int intValue = (Integer) value;
                        // cell.setCellValue(intValue);
                        // } else if (value instanceof Float) {
                        // float fValue = (Float) value;
                        // textValue = new HSSFRichTextString(
                        // String.valueOf(fValue));
                        // cell.setCellValue(textValue);
                        // } else if (value instanceof Double) {
                        // double dValue = (Double) value;
                        // textValue = new HSSFRichTextString(
                        // String.valueOf(dValue));
                        // cell.setCellValue(textValue);
                        // } else if (value instanceof Long) {
                        // long longValue = (Long) value;
                        // cell.setCellValue(longValue);
                        // }
                        if (value == null) {
                            textValue = "";
                        } else if (value instanceof Date) {
                            Date date = (Date) value;
                            textValue = sdf.format(date.toInstant());
                        } else if (value instanceof byte[]) {
                            // 有图片时,设置行高为60px;
                            row.setHeightInPoints(60);
                            // 设置图片所在列宽度为80px,注意这里单位的一个换算
                            sheet.setColumnWidth(i, (short) (35.7 * 80));
                            sheet.autoSizeColumn(i);
                            byte[] bsValue = (byte[]) value;
                            HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 255, (short) 6, rowIndex, (short) 6, rowIndex);
                            anchor.setAnchorType(ClientAnchor.AnchorType.byId(2));
                            patriarch.createPicture(anchor, workbook.addPicture(bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));
                        } else {
                            // 其它数据类型都当作字符串简单处理
                            textValue = value.toString();
                        }
                        // 如果不是图片数据,就利用正则表达式判断textValue是否全部由数字组成
                        if (textValue != null) {
                            Pattern p = Pattern.compile("^//d+(//.//d+)?$");
                            Matcher matcher = p.matcher(textValue);
                            if (matcher.matches()) {
                                // 是数字则当作double处理
                                cell.setCellValue(Double.parseDouble(textValue));
                            } else {
                                cell.setCellValue(generateRichTextString(textValue));
                            }
                        }
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                    }
                }
                rowIndex++;
            }
        }


        try {
            workbook.write(out);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {// 清理资源
            if (null != workbook) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

    /**
     * 读取excel文件内容,存入到字节流。每行结尾加了换行符,一行中各字段后跟一逗号来分隔
     */
    public static ByteArrayInputStream importExcel(InputStream in, int sheetIndex) throws InvalidFormatException, IOException, InstantiationException, IllegalAccessException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try (Workbook workbook = generateWorkbookFromInputStream(in)) {
            Sheet sheet = workbook.getSheetAt(sheetIndex);
            for (int ri = sheet.getFirstRowNum(); ri <= sheet.getLastRowNum(); ri++) {
                Row row = sheet.getRow(ri);
                for (int ci = row.getFirstCellNum(); ci < row.getLastCellNum(); ci++) {
                    Cell cell = row.getCell(ci);
                    String value = getValue(cell) + ", ";
                    baos.write(value.getBytes());
                    // System.out.printf("%s ", value);
                }
                baos.write("\n".getBytes());
                // System.out.println("");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        ;


        return new ByteArrayInputStream(baos.toByteArray());
    }

    private static String getValue(Cell cell) {
        if (cell.getCellType() == CellType.BOOLEAN) {
            // 返回布尔类型的值
            return String.valueOf(cell.getBooleanCellValue());
        } else if (cell.getCellType() == CellType.NUMERIC) {
            // 返回数值类型的值
            return String.valueOf(cell.getNumericCellValue());
        } else {
            // 返回字符串类型的值
            return String.valueOf(cell.getStringCellValue());
        }
    }

    /**
     * excepl 文档中的一个Sheet的信息定义
     */
    @Data
    @AllArgsConstructor
    public static class SheetInfo<T> {
        private String name;//表格名称
        private String[] headers;//表格列名
        private Collection<T> dataset;//表格数据,每个元素代表一行
    }


    //以下为为了同时兼容 xls、xlsx 格式的excel文档而定义的方法
    /**
     * 是否生成xlsx文档,为true则生成xlsx格式的文档(Excel2007及以后的版本,扩展名是.xlsx)、否则生成xls格式的文档(Excel2003及以前的版本,扩展名是.xls)。
     */
    private static final boolean USE_XLSX = true;

    private static RichTextString generateRichTextString(String val) {
        RichTextString res = USE_XLSX ? new XSSFRichTextString(val) : new HSSFRichTextString(val);
        //res.applyFont(new xx);
        return res;
    }


    /**
     * 创建一个excel文档
     */
    private static Workbook generateWorkbook() {
        //HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls
        //XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx
        Workbook res = USE_XLSX ? new XSSFWorkbook() : new HSSFWorkbook();
        return res;
    }

    /**
     * 创建一个excel文档
     */
    private static Workbook generateWorkbookFromInputStream(InputStream in) throws IOException {
        //HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls
        //XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx
        Workbook res = USE_XLSX ? new XSSFWorkbook(in) : new HSSFWorkbook(in);
        return res;
    }

    private static CellStyle generateTableHeaderStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);
        style.setAlignment(HorizontalAlignment.CENTER);
        Font font = workbook.createFont();
        font.setColor(IndexedColors.WHITE.getIndex());
        font.setFontHeightInPoints((short) 12);
        //font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        style.setFont(font);

        return style;
    }

    private static CellStyle generateTableBodyStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        Font font = workbook.createFont();
        font.setColor(IndexedColors.GREY_80_PERCENT.index);
        //font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
        style.setFont(font);

        return style;
    }
}
ExcelUtil

 

标签:style,Java,String,Excel,value,导入,workbook,new,textValue
来源: https://www.cnblogs.com/z-sm/p/16482589.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有