POI渲染Excel表格模板替换其中指定表格参数,以及Microsoft联机文档查看器遇到的坑

pom.xml

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-contrib</artifactId>
            <version>3.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.17</version>
        </dependency>

Util工具类

我们日常开发中很少将静态问题放置在本地服务器,更多的是放在各种云,例如小编目前就是存储在百度云的BOS中,由于构建poi对象时,小编的方式是根据已有模板创建HSSFWorkbook/XSSFWorkbook,所以首先需要获取模板文件的输入流,BOS的Util中已经提供了获取指定文件输入流的方法,但是! 这个流有问题,根据他不能完成渲染数据,后来没办法,只能先下载到本地,然后再获取输入流,这样最后才成功了。

	/**
     * 从网络Url中下载文件
     * 由于linux 与 windows的文件分隔符不一致,所以强烈建议使用 File.separator
     * urlStr 文件地址
     * fileName 保存在本地文件的名称
     * savePath 保存文件的地址 (注意,文件地址与文件名之间添加了file路径)
     */
    public static FileInputStream downLoadFromUrl(String urlStr, String fileName, String savePath) {
        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //设置超时间为3秒
            conn.setConnectTimeout(3 * 1000);
            //防止屏蔽程序抓取而返回403错误
//            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            //得到输入流
            InputStream inputStream = conn.getInputStream();
            //获取自己数组
            byte[] getData = readInputStream(inputStream);

            //文件保存位置
            File saveDir = new File(savePath);
            if (!saveDir.exists()) {
                saveDir.mkdir();
            }
            File file = new File(saveDir + File.separator + "file" + File.separator + fileName);
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(getData);
            fos.close();
            inputStream.close();
            return new FileInputStream(saveDir + File.separator + "file" + File.separator + fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 从输入流中获取字节数组
     */
    public static byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while ((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }

划重点excel文件渲染数据核心方法

/**
 *
 * 功能描述:
 *
 * @Auther: 读少
 * @Date: 2019/3/26 17:25
 * fileName 文件名称
 * in 模板文档输入流
 * out 模板文档输出流
 * resultValue (这里边封装了要渲染参数的坐标index,以及值value)
 * startTime,endTime由于小编处理的是数据报表 所以有抄表区间开始时间,截止时间
 *
 */
 public static void applyDataForReport(String fileName, InputStream in, FileOutputStream out,
                                          List<ReportFormValue> resultValue, CmReportFormsModel model, String startTime,
                                          String endTime) {
        String copyTimeCellIndex = model.getCopyTimeCellIndex();
        try {
            if (fileName.endsWith("xls")) {

                HSSFWorkbook workbook = new HSSFWorkbook(in);
                in.close();
                HSSFSheet sheet = workbook.getSheetAt(0);
                resultValue.forEach(o -> {
                    CellAddress cellAddress = new CellAddress(o.getIndex());
                    HSSFRow row = sheet.getRow(cellAddress.getRow());
                    if (row == null) {
                        row = sheet.createRow(cellAddress.getRow());
                    }
                    HSSFCell cell = row.getCell(cellAddress.getColumn());
                    if (cell == null) {
                        cell = row.createCell(cellAddress.getColumn());
                    }
                    cell.setCellValue(Double.valueOf(o.getValue()));
                });
                if (copyTimeCellIndex != null && !"".equals(copyTimeCellIndex)) {
                    String[] index = copyTimeCellIndex.split(",");
                    for (String tempIndex : index) {
                        CellAddress cellAddress = new CellAddress(tempIndex);
                        HSSFRow row = sheet.getRow(cellAddress.getRow());
                        if (row == null) {
                            row = sheet.createRow(cellAddress.getRow());
                        }
                        HSSFCell cell = row.getCell(cellAddress.getColumn());
                        if (cell == null) {
                            cell = row.createCell(cellAddress.getColumn());
                        }
                        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
                        DateTimeFormatter reF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
                        LocalDateTime.parse(startTime, df).format(reF);
                        cell.setCellValue(
                                "抄表区间:" + LocalDateTime.parse(startTime, df).format(reF) + "-" + LocalDateTime
                                        .parse(endTime, df).format(reF));
                    }
                }
                sheet.setForceFormulaRecalculation(true);
                workbook.write(out);
                in.close();
                out.flush();
                out.close();
            } else {
                //xlxs文件

                XSSFWorkbook workbook = new XSSFWorkbook(in);
                in.close();
                XSSFSheet sheet = workbook.getSheetAt(0);
                resultValue.forEach(o -> {
                    CellAddress cellAddress = new CellAddress(o.getIndex());
                    XSSFRow row = sheet.getRow(cellAddress.getRow());
                    if (row == null) {
                        row = sheet.createRow(cellAddress.getRow());
                    }
                    XSSFCell cell = row.getCell(cellAddress.getColumn());
                    if (cell == null) {
                        cell = row.createCell(cellAddress.getColumn());
                    }
                    cell.setCellValue(Double.valueOf(o.getValue()));
                });
                if (copyTimeCellIndex != null && !"".equals(copyTimeCellIndex)) {
                    String[] index = copyTimeCellIndex.split(",");
                    for (String tempIndex : index) {
                        CellAddress cellAddress = new CellAddress(tempIndex);
                        XSSFRow row = sheet.getRow(cellAddress.getRow());
                        if (row == null) {
                            row = sheet.createRow(cellAddress.getRow());
                        }
                        XSSFCell cell = row.getCell(cellAddress.getColumn());
                        if (cell == null) {
                            cell = row.createCell(cellAddress.getColumn());
                        }
                        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
                        DateTimeFormatter reF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
                        LocalDateTime.parse(startTime, df).format(reF);
                        /**
                      	 *根据指定位置添加,模板渲染时间
                         */
                        cell.setCellValue(
                                "抄表区间:" + LocalDateTime.parse(startTime, df).format(reF) + "-" + LocalDateTime
                                        .parse(endTime, df).format(reF));
                    }
                }
                sheet.setForceFormulaRecalculation(true);
                workbook.write(out);
                in.close();
                out.flush();
                out.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("渲染数据异常" + e.getMessage());
        }
    }

POJO

/**
 * @author 读少
 * @date 2019/3/26 17:33
 * 属性可删减
 */
@Data
public class ReportFormValue {
    private String index;
    private String value;
    private Integer pt;
    private Integer ct;
    private Integer valueType;
    private Integer dateType;
    private String orgMeterCode;
    private String paramCode;
}

/**
 *
 * 功能描述: excel模板
 *
 * @Auther: 读少
 * @Date: 2019/3/26 17:25
 */
@Data
public class CmReportFormsModel {
    private Integer id;

    private Integer orgId;

    private String modelName;

    private String modelBosUrl;

    private Integer modelType;

    private String copyTimeTemplate;

    private Integer publishStatus;

    private Integer state;

    private String creator;

    private Date createTime;

    private String updator;

    private Date updateTime;

    private String remark;

    private String copyTimeCellIndex;

}

综上服务器端渲染核心代码已完成,其中out输出流,开发者可自行处理,从responset.getOutputStream(),或者new一个输出流写到本地服务器,均可,无非就是返回给前端的方式不一样罢了。

下边介绍下小编这里对线上office展示采用的方式

网址:https://products.office.com/zh-CN/office-online/view-office-documents-online
实现大致效果如下,还可以实现下载,打印,全屏等功能。
其中黄色格子即为渲染数据位置

坑!

如果表格中存在公式,例如F12 = F11+F10+F9 建议不要采用office编辑文档后上传模板文件,这样这份文件中的公式值在该组件中无法线上显示,需下载后查看,无论xls,xlsx结果都一样。
解决办法,非常骚气,用wps编辑一下表格,触发提示保存,保存之后再重新上传文档就可以在线上查看到公式单元格了。

缺点

由于参数是一个个单元格渲染的,渲染速度还蛮快的,但就是配置是比较繁琐的,只能通过批量导入,或者一个个单月格进行配置要插入的数据项,好在这种功能不需要频繁修改,运维抱着一劳永逸的态度,也就没那么多小脾气了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Java的POI库操作.doc Word模板替换并循环插入表格的步骤如下: 1. 导入POI库的相关依赖,例如Apache POI和Apache POI-OOXML。 2. 创建一个Word文档(.docx),该文档将作为模板使用。 3. 使用Apache POI的XWPFDocument类加载模板文档。 ```java XWPFDocument doc = new XWPFDocument(new FileInputStream("template.docx")); ``` 4. 声明一个XWPFTable对象,用于向文档中插入表格。 ```java XWPFTable table; ``` 5. 使用XWPFDocument类的getTables()方法获取文档中的所有表格,通常一个模板只有一个表格。 ```java List<XWPFTable> tables = doc.getTables(); table = tables.get(0); // 假设我们要操作的表格是第一个表格 ``` 6. 使用XWPFTable对象的removeRow()方法删除表格中的所有行,这样就可以将模板中的行删除,以便后面插入新的行。 ```java for (int i = table.getRows().size() - 1; i > 0; i--) { table.removeRow(i); } ``` 7. 使用XWPFTable对象的createRow()方法创建新的行,并使用XWPFTableRow对象的createCell()方法创建单元格。 ```java for (int i = 0; i < data.size(); i++) { XWPFTableRow newRow = table.createRow(); // 将data中的数据添加到新行的单元格中 for (int j = 0; j < data.get(i).size(); j++) { XWPFTableCell newCell = newRow.getCell(j); newCell.setText(data.get(i).get(j)); } } ``` 8. 将替换表格文档保存为新的文档。 ```java FileOutputStream out = new FileOutputStream("output.docx"); doc.write(out); out.close(); ``` 这样,你就可以使用Java的POI库操作.doc Word模板替换表格并循环插入新的表格了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值