当前位置: 首页 > ops >正文

springboot+vue实现通过poi完成excel

前端

1、按钮

              <el-buttontype="text"size="mini"@click="handleExport">导出</el-button>

2、方法

 //导出async handleExport() {if (!this.activityId) {this.$message.warning('活动ID不存在');return;}try {this.loading = true;const res = await exportSignSheet({activityId: this.activityId});//文件名let fileName = `活动签到表_${this.activity?.activityTitle || '未知活动'}_${Date.now()}.xlsx`;//创建下载链接const blob = new Blob([res.data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});const url = window.URL.createObjectURL(blob);const link = document.createElement('a');link.href = url;link.download = fileName;document.body.appendChild(link);link.click();// 清理setTimeout(() => {document.body.removeChild(link);window.URL.revokeObjectURL(url);}, 100);this.$message.success('签到表下载已开始');} catch (error) {console.error('导出失败:', error);this.$message.error(`导出失败: ${error.message}`);} finally {this.loading = false;}},

3、路由

export function exportSignSheet(data) {return request({url: '/association/detail/signSheet',//后端接口地址method: 'post',data,responseType: 'blob',//一定要指定类型为blob// 确保能获取到headerstransformResponse: (data, headers) => {return {data,headers: headers || {}};}});
}

4、后端

      <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency>
 @PostMapping("/signSheet")public void exportSignSheet(@RequestBody Map<String, Long> request, // 前端参数HttpServletResponse response) throws IOException {// 设置CORS头(如果存在跨域问题)response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");// 1. 验证活动IDLong activityId = request.get("activityId");if (activityId == null) {throw new IllegalArgumentException("活动ID不能为空");}// 2. 获取活动完整信息(复用已有查询方法)ActivityDetailVO activityVO = activityDetailService.getActivityDetail(activityId);if (activityVO == null) {throw new RuntimeException("活动不存在或已删除");}// 3. 处理文件名String activityName = activityVO.getActivityTitle() != null ? activityVO.getActivityTitle() : "未知活动";String fileName = "活动签到表_" + activityName + "_" + System.currentTimeMillis() + ".xlsx";// 4. 处理文件名避免乱码String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replace("+", "%20"); // 替换空格编码// 5. 设置请求头        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setHeader("Content-Disposition","attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);// 6. 创建并填充Exceltry (XSSFWorkbook workbook = new XSSFWorkbook()) {buildExcelContent(workbook, activityVO);//可以将文件存入本地进行调试//workbook.write(Files.newOutputStream(Paths.get("debug.xlsx")));workbook.write(response.getOutputStream());} catch (Exception e) {response.reset();response.setContentType("application/json");response.setCharacterEncoding("UTF-8");response.getWriter().write("{\"error\":\"" + e.getMessage() + "\"}");}}
private void buildExcelContent(XSSFWorkbook workbook, ActivityDetailVO activityVO) {Sheet sheet = workbook.createSheet("活动签到表");sheet.setDefaultColumnWidth(15);// 创建样式(保持不变)CellStyle titleStyle = createTitleStyle(workbook);CellStyle borderStyle = createBorderStyle(workbook);CellStyle headerStyle = createHeaderStyle(workbook);// 标题行(第0行)- 修复合并单元格边框Row titleRow = sheet.createRow(0);Cell titleCell = titleRow.createCell(0);titleCell.setCellValue("活动签到表");CellRangeAddress titleRegion = new CellRangeAddress(0, 0, 0, 5);sheet.addMergedRegion(titleRegion);titleCell.setCellStyle(titleStyle);setRegionBorder(BorderStyle.THIN, titleRegion, sheet, workbook); // 新增:设置合并区域边框// 第二行:活动名称(第1行)- 修复合并单元格边框Row nameRow = sheet.createRow(1);Cell nameCell = nameRow.createCell(0);nameCell.setCellValue(activityVO.getActivityTitle() != null ? activityVO.getActivityTitle() : "未设置");CellRangeAddress nameRegion = new CellRangeAddress(1, 1, 0, 5);sheet.addMergedRegion(nameRegion);nameCell.setCellStyle(borderStyle);setRegionBorder(BorderStyle.THIN, nameRegion, sheet, workbook); // 新增:设置合并区域边框// 第三行:活动地点和活动时间(第2行)- 修复合并单元格边框Row locationTimeRow = sheet.createRow(2);// 活动地点标签Cell locationLabelCell = locationTimeRow.createCell(0);locationLabelCell.setCellValue("活动地点");locationLabelCell.setCellStyle(borderStyle);// 活动地点内容(合并1-2列)Cell locationCell = locationTimeRow.createCell(1);locationCell.setCellValue(getFirstActivityLocation(activityVO));CellRangeAddress locationRegion = new CellRangeAddress(2, 2, 1, 2);sheet.addMergedRegion(locationRegion);locationCell.setCellStyle(borderStyle);setRegionBorder(BorderStyle.THIN, locationRegion, sheet, workbook); // 新增:设置合并区域边框// 活动时间标签Cell timeLabelCell = locationTimeRow.createCell(3);timeLabelCell.setCellValue("活动时间");timeLabelCell.setCellStyle(borderStyle);// 活动时间内容(合并4-5列)Cell timeCell = locationTimeRow.createCell(4);timeCell.setCellValue(formatActivityTimeRange(activityVO.getStartTime(), activityVO.getEndTime()));CellRangeAddress timeRegion = new CellRangeAddress(2, 2, 4, 5);sheet.addMergedRegion(timeRegion);timeCell.setCellStyle(borderStyle);setRegionBorder(BorderStyle.THIN, timeRegion, sheet, workbook); // 新增:设置合并区域边框// 第四行:活动召集人和报名人数(第3行)- 修复合并单元格边框Row organizerCountRow = sheet.createRow(3);// 活动召集人标签Cell organizerLabelCell = organizerCountRow.createCell(0);organizerLabelCell.setCellValue("活动召集人");organizerLabelCell.setCellStyle(borderStyle);// 活动召集人内容(合并1-2列)Cell organizerCell = organizerCountRow.createCell(1);organizerCell.setCellValue(activityVO.getEntrepreneurNames() != null ? activityVO.getEntrepreneurNames() : "未设置");CellRangeAddress organizerRegion = new CellRangeAddress(3, 3, 1, 2);sheet.addMergedRegion(organizerRegion);organizerCell.setCellStyle(borderStyle);setRegionBorder(BorderStyle.THIN, organizerRegion, sheet, workbook); // 新增:设置合并区域边框// 报名人数标签Cell countLabelCell = organizerCountRow.createCell(3);countLabelCell.setCellValue("报名人数");countLabelCell.setCellStyle(borderStyle);// 报名人数内容(合并4-5列)Cell countCell = organizerCountRow.createCell(4);countCell.setCellValue(String.valueOf(getParticipantCount(activityVO)));CellRangeAddress countRegion = new CellRangeAddress(3, 3, 4, 5);sheet.addMergedRegion(countRegion);countCell.setCellStyle(borderStyle);setRegionBorder(BorderStyle.THIN, countRegion, sheet, workbook); // 新增:设置合并区域边框// 第五行:签到处(第4行)- 修复合并单元格边框Row signRow = sheet.createRow(4);Cell signCell = signRow.createCell(0);signCell.setCellValue("签到处");CellRangeAddress signRegion = new CellRangeAddress(4, 4, 0, 5);sheet.addMergedRegion(signRegion);signCell.setCellStyle(borderStyle);setRegionBorder(BorderStyle.THIN, signRegion, sheet, workbook); // 新增:设置合并区域边框// 表头行(第5行)- 保持不变Row headerRow = sheet.createRow(5);String[] headers = {"序号", "报名人", "联系电话", "序号", "报名人", "联系电话"};for (int i = 0; i < headers.length; i++) {Cell cell = headerRow.createCell(i);cell.setCellValue(headers[i]);cell.setCellStyle(headerStyle);}}// 带边框的样式private CellStyle createBorderStyle(XSSFWorkbook workbook) {CellStyle style = workbook.createCellStyle();// 设置边框style.setBorderTop(BorderStyle.THIN);style.setBorderBottom(BorderStyle.THIN);style.setBorderLeft(BorderStyle.THIN);style.setBorderRight(BorderStyle.THIN);// 设置边框颜色(黑色)style.setTopBorderColor(IndexedColors.BLACK.getIndex());style.setBottomBorderColor(IndexedColors.BLACK.getIndex());style.setLeftBorderColor(IndexedColors.BLACK.getIndex());style.setRightBorderColor(IndexedColors.BLACK.getIndex());// 居中对齐style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(VerticalAlignment.CENTER);return style;}// 标题样式(继承边框样式并加大字体)private CellStyle createTitleStyle(XSSFWorkbook workbook) {CellStyle style = createBorderStyle(workbook);Font font = workbook.createFont();font.setBold(true);font.setFontHeightInPoints((short) 16);style.setFont(font);return style;}// 表头样式(继承边框样式并加粗)private CellStyle createHeaderStyle(XSSFWorkbook workbook) {CellStyle style = createBorderStyle(workbook);Font font = workbook.createFont();font.setBold(true);style.setFont(font);return style;}

http://www.xdnf.cn/news/17708.html

相关文章:

  • Postman 平替 技术解析:架构优势与实战指南
  • 观察者模式(C++)
  • 【Leetcode hot 100】76.最小覆盖字串
  • 【HarmonyOS】Window11家庭中文版开启鸿蒙模拟器失败提示未开启Hyoer-V
  • SwiftUI 页面弹窗操作
  • 用飞算JavaAI一键生成电商平台项目:从需求到落地的高效实践
  • 使用免费API开发口播数字人
  • [机器学习]07-基于多层感知机的鸢尾花数据集分类
  • c++中的Lambda表达式详解
  • Java基础07——基本运算符(本文为个人学习笔记,内容整理自哔哩哔哩UP主【遇见狂神说】的公开课程。 > 所有知识点归属原作者,仅作非商业用途分享)
  • k8s+isulad 网络问题
  • 如何使用 AI 大语言模型解决生活中的实际小事情?
  • 【P81 10-7】OpenCV Python【实战项目】——车辆识别、车流统计(图像/视频加载、图像运算与处理、形态学、轮廓查找、车辆统计及显示)
  • 网络协议序列化工具Protobuf
  • 4.1vue3的setup()
  • 2019 GPT2原文 Language Models are Unsupervised Multitask Learners - Reading Notes
  • Kotlin Data Classes 快速上手
  • Qt TCP 客户端对象生命周期与连接断开问题解析
  • 解锁Prompt秘籍:框架、技巧与指标全解析
  • Windows 11操作系统 Git命令执行速度慢
  • SpringMVC基本原理和配置
  • 第2节 如何计算神经网络的参数:AI入门核心逻辑详解
  • pytorch学习笔记-加载现有的网络模型(VGG16)、增加/修改其中的网络层(修改为10分类)
  • 云计算-多服务集群部署实战指南:从JumpServer到Kafka、ZooKeeper 集群部署实操流程
  • 70亿参数让机器人“开窍“:英伟达Cosmos Reason如何让AI理解物理世界
  • 分段锁和限流的间接实现
  • 基于51单片机的手机蓝牙控制8位LED灯亮灭设计
  • Day19 C 语言标准 IO 机制
  • 深度学习——03 神经网络(2)-损失函数
  • 2021 年全国硕士研究生招生考试真题笔记