Excel填充数据并下载

该代码示例展示了如何从SQL数据库中检索数据并填充到Excel模板中,然后下载生成的Excel文件。主要涉及SQL查询、Java对Excel的操作,包括复制行、填充单元格和设置下载头等步骤。

Excel填充数据并下载

每篇一句励志:在你往上爬的时候,一定要保持梯子的整洁,否则你下来时可能会滑倒。

话不多说,直接上代码。
public void exportMsgList(String companyCode, String companyName, String planTime, Integer type, HttpServletResponse response) {
        try {
            //这是使用SQLSERVER数据库;拼接sql
            StringBuffer sb = new StringBuffer();
            sb.append("select * from T_COMPANY_MSG where 1=1 ");
            if(StringUtils.isNotBlank(companyCode)){
                sb.append(" and COMPANY_CODE = '"+companyCode+"'");
            }
            if(type != null){
                sb.append(" and PERIOD_TYPE = "+type);
            }
            if(StringUtils.isNotBlank(planTime)){
                sb.append(" and MONTH = '"+planTime+"'");
            }
            sb.append(" order by CREATE_TIME");

            Query nativeQuery = entityManager.createNativeQuery(sb.toString(), TCompanyMsg.class);
            List<TCompanyMsg> resultList = nativeQuery.getResultList();

            //拿到excel,我的是放在resources下的static里
            InputStream stream = FileUtil.class.getClassLoader().getResourceAsStream("static/" + "企业周期上报计划校验记录.xlsx");

            XSSFWorkbook wb = new XSSFWorkbook(stream);
            response.reset();
            //设置下载文档格式
            response.setContentType("application/msexcel;charset=UTF-8");
            if(CollectionUtils.isNotEmpty(resultList)){
                //填充数据
                //拿到excel的sheet
                XSSFSheet sheet = wb.getSheet("sheet1");
                int xuHao = 0;
                //从哪行开始填充数据
                int rowNum = 6;
                //循环数据集
                for (TCompanyMsg tCompanyMsg : resultList) {
                    xuHao++;
                    //复制行。一般有模板行需要复制
                    //方法的参数为:sheet.copyRows(模板行的开始,模板行的结束,填充数据的开始行,用new的就可以,如果有其他需求方法里可放参数);
                    sheet.copyRows(5,5,rowNum,new CellCopyPolicy());
                    //此处如果你的excel里没有已经处理过的行就需要创建行
                    XSSFRow row = sheet.getRow(rowNum);
//                    XSSFRow row = sheet.createRow(rowNum);//创建行。如果你是创建行可能单元格也需要创建
                    row.getCell(0).setCellValue(xuHao);
                    row.getCell(1).setCellValue(tCompanyMsg.getCompanyCode());
                    row.getCell(2).setCellValue(tCompanyMsg.getCompanyName());
                    row.getCell(3).setCellValue(tCompanyMsg.getMonth());
                    row.getCell(4).setCellValue(tCompanyMsg.getSheetName());
                    if(tCompanyMsg.getCreateTime() != null){
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                        row.getCell(5).setCellValue(sdf.format(tCompanyMsg.getCreateTime()));
                    }
                    rowNum++;//行++
                }
                //删除第一行的模板行。
                sheet.shiftRows(rowNum,sheet.getLastRowNum(),-1);
            }
            //拼装导出的名称
            String excelName = companyName + "企业周期上报计划校验记录";
            response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(excelName, "UTF-8") + ".xlsx");
            BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
            //通过流返回前端
            wb.write(outputStream);
            outputStream.flush();
        } catch (Exception e) {
            log.error("导出Excle报错,{}",e);
        }
    }
<think>我们正在处理一个关于使用Java POI操作Excel模板的问题。用户希望打开一个Excel模板填充数据,然后实现下载功能。 根据用户提供的引用[1],我们可以使用POI读取和操作Excel文件。但是,用户提供的示例代码是用于提取Excel文本内容不适合用于填充数据下载。 我们需要做的是: 1. 打开一个现有的Excel模板文件(例如,一个.xls或.xlsx文件)。 2. 在模板的特定位置填充数据。 3. 将填充后的Excel文件提供给用户下载(例如,通过HTTP响应输出流)。 步骤: 1. 读取模板文件:使用POI的WorkbookFactory打开模板文件,这样可以同时支持.xls和.xlsx格式。 2. 获取工作表(Sheet)定位到需要填充数据的单元格(Cell)。 3. 设置单元格的值。 4. 将修改后的工作簿写入到输出流(例如,Servlet响应输出流),以便用户下载。 另外,用户提到“下载功能”,通常这是在Web应用中实现的,所以我们需要考虑在Servlet或Spring MVC等Web框架中实现。 示例代码结构: 假设我们在一个Servlet中处理请求: ```java protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 读取模板文件 InputStream templateInputStream = new FileInputStream(new File("path/to/template.xlsx")); Workbook workbook = WorkbookFactory.create(templateInputStream); // 2. 获取第一个工作表(根据实际情况调整) Sheet sheet = workbook.getSheetAt(0); // 3. 填充数据(例如,在A1单元格填充) Row row = sheet.getRow(0); // 第一行 if (row == null) { row = sheet.createRow(0); } Cell cell = row.getCell(0, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); cell.setCellValue("填充数据"); // 4. 设置响应头,告诉浏览器这是一个Excel文件触发下载 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename=result.xlsx"); // 5. 将工作簿写入响应输出流 OutputStream out = response.getOutputStream(); workbook.write(out); out.flush(); out.close(); // 6. 关闭工作簿和输入流 workbook.close(); templateInputStream.close(); } ``` 注意: - 异常处理:这里省略了异常处理,实际应用中需要妥善处理异常,比如关闭流等。 - 路径:模板文件的路径需要根据实际情况设置,或者可以配置在配置文件中。 - 数据填充:实际应用中,数据可能来自数据库或其他来源,且需要根据模板的结构填充到多个位置。 另外,如果模板是.xls格式(HSSFWorkbook),则使用WorkbookFactory会自动处理。但是,如果明确知道模板是.xlsx,也可以直接使用XSSFWorkbook。 优化: - 使用try-with-resources确保资源被正确关闭(Java 7及以上)。 - 考虑使用模板引擎(如Apache POI模板引擎)来更灵活地填充数据,但这里我们先使用基本的单元格填充。 示例代码(使用try-with-resources): ```java protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 模板文件路径 String templatePath = "/path/to/template.xlsx"; try (InputStream is = new FileInputStream(templatePath); Workbook workbook = WorkbookFactory.create(is)) { // 操作工作簿... Sheet sheet = workbook.getSheetAt(0); // 填充数据... // 设置响应 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename=result.xlsx"); // 写入响应 try (OutputStream out = response.getOutputStream()) { workbook.write(out); } } catch (Exception e) { // 处理异常 e.printStackTrace(); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "生成Excel失败"); } } ``` 如果数据量较大,或者需要填充多个位置,建议将填充逻辑封装成方法,或者使用循环填充。 另外,引用[2]提到了使用数据填充,比如XML数据源,但这里我们直接使用Java代码填充。如果需要从数据库获取数据,可以在填充之前先查询数据库。 相关问题: 1. 如何动态确定Excel模板中需要填充的位置? 2. 如何填充多个工作表或大量数据? 3. 如何处理Excel模板中的合单元格? 4. 如何设置单元格的样式(字体、颜色、边框等)? 5. 在Web应用中,如何确保下载时的性能? 我们将根据用户的问题,提供上述解决方案。</think>### 使用 Java POI 操作 Excel 模板填充数据+下载) #### 核心步骤 1. **加载模板**:读取预定义的 Excel 模板文件 2. **填充数据**:在指定位置写入动态数据 3. **下载文件**:通过 HTTP 响应流输出 Excel 文件 #### 完整代码示例(Servlet 实现) ```java import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import javax.servlet.http.*; import java.io.*; public class ExcelServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { // 1. 加载模板文件 try (InputStream is = getClass().getResourceAsStream("/templates/report_template.xlsx"); Workbook workbook = WorkbookFactory.create(is)) { // 2. 获取工作表填充数据 Sheet sheet = workbook.getSheetAt(0); // 示例:在B2单元格填充标题 Row titleRow = sheet.getRow(1); Cell titleCell = titleRow.getCell(1); titleCell.setCellValue("2023年度销售报表"); // 示例:动态填充数据行(实际应从数据库获取) int startRow = 4; Object[][] data = { {"A001", "笔记本电脑", 15, 8999.00}, {"A002", "智能手机", 32, 3999.00} }; for (int i = 0; i < data.length; i++) { Row row = sheet.createRow(startRow + i); for (int j = 0; j < data[i].length; j++) { Cell cell = row.createCell(j); if (data[i][j] instanceof Number) { cell.setCellValue(((Number) data[i][j]).doubleValue()); } else { cell.setCellValue(data[i][j].toString()); } } } // 3. 设置下载响应头 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename=generated_report.xlsx"); // 4. 输出Excel到响应流 try (OutputStream out = response.getOutputStream()) { workbook.write(out); } } catch (Exception e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "生成文件失败: " + e.getMessage()); } } } ``` #### 关键技术说明 1. **模板加载**: - 使用 `WorkbookFactory.create()` 自动识别 .xls/.xlsx 格式 - 模板文件建议放在 `resources/templates/` 目录 - 支持保留模板中的公式/格式/样式 2. **数据填充技巧**: ```java // 修改现有单元格 sheet.getRow(0).getCell(0).setCellValue("新值"); // 创建新单元格(保留样式) CellStyle style = workbook.createCellStyle(); style.cloneStyleFrom(existingCell.getCellStyle()); newCell.setCellStyle(style); ``` 3. **性能优化**: - 大数据量时使用 `SXSSFWorkbook`(流式处理) - 批量操作数据后一次性写入 - 及时关闭资源(try-with-resources) #### 前端调用示例(JavaScript) ```javascript // 触发文件下载 fetch('/export-excel') .then(response => response.blob()) .then(blob => { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'report.xlsx'; document.body.appendChild(a); a.click(); document.body.removeChild(a); }); ``` #### 常见问题解决 1. **中文乱码**: ```java response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + URLEncoder.encode("报表.xlsx", "UTF-8")); ``` 2. **样式丢失**: - 在模板中预定义所有样式 - 通过 `CellUtil` 复制样式: ```java CellUtil.copyCellStyle(sourceCell, targetCell); ``` 3. **公式不更新**: ```java workbook.getCreationHelper().createFormulaEvaluator().evaluateAll(); ``` > **提示**:对于复杂模板建议使用 [Apache POI模板引擎](https://poi.apache.org/components/spreadsheet/how-to.html#template_xssf),或结合邮件合技术处理结构化数据[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值