[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-public-sNDKpWVJ":3,"public-project-articles-sNDKpWVJ":17},{"id":4,"uuid":5,"project_id":6,"title":7,"content":8,"type":9,"status":10,"public_enabled":10,"views":11,"sort":12,"created_at":13,"updated_at":14,"project_title":15,"project_slug":16},775,"sNDKpWVJ",49,"07. Springboot3+Vue3实现excel批量导入导出","## Hutool 工具类\n\n[https:\u002F\u002Fdoc.hutool.cn\u002Fpages\u002Findex\u002F](https:\u002F\u002Fdoc.hutool.cn\u002Fpages\u002Findex\u002F)\n\n## Excel 导出\n\n通过输出流的方式导出数据\n\n### 导出数据流程\n\n1. 拿到所有数据\n2. 构建 ExcelWriter\n3. 设置中文表头\n4. 写出数据到writer\n5. 设置输出的文件的名称以及输出流的头信息\n6. 写出到输出流 并关闭 writer\n\n> 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之\n>\n> writer.setOnlyAlias(true);\n\n```java\n\u002F**\n * 数据导出\n *\u002F\n@GetMapping(\"\u002Fexport\")\npublic void exportData(HttpServletResponse response) throws Exception {\n    \u002F\u002F 1. 拿到所有数据\n    List\u003CAdmin> list = adminService.selectAll();\n    \u002F\u002F 2. 构建Writer对象\n    ExcelWriter writer = ExcelUtil.getWriter(true);\n    \u002F\u002F 3. 设置中文表头\n    writer.addHeaderAlias(\"username\", \"账号\");\n    writer.addHeaderAlias(\"name\", \"名称\");\n    writer.addHeaderAlias(\"phone\", \"电话\");\n    writer.addHeaderAlias(\"email\", \"邮箱\");\n    \u002F\u002F 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之\n    writer.setOnlyAlias(true);\n    \u002F\u002F 4. 写出数据到writer\n    writer.write(list);\n    \u002F\u002F 5. 设置输出的文件的名称以及输出流的头信息\n    response.setContentType(\"application\u002Fvnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8\");\n    String fileName = URLEncoder.encode(\"管理员信息\", StandardCharsets.UTF_8);\n    response.setHeader(\"Content-Disposition\", \"attachment;filename=\" + fileName + \".xlsx\");\n    \u002F\u002F 6. 写出到输出流 并关闭 writer\n    ServletOutputStream os = response.getOutputStream();\n    writer.flush(os);\n    writer.close();\n    os.close();\n}\n```\n\n### 异常处理 缺少依赖\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1740275351129-312d035d-50ce-4e7f-83d8-ef27fa871e74.png)\n\n加上  poi-ooxml 这个依赖\n\n```xml\n\u003C!-- 处理office文件的依赖 -->\n\u003Cdependency>\n    \u003CgroupId>org.apache.poi\u003C\u002FgroupId>\n    \u003CartifactId>poi-ooxml\u003C\u002FartifactId>\n    \u003Cversion>5.2.3\u003C\u002Fversion>\n\u003C\u002Fdependency>\n```\n\n### 前端调用\n\n```vue\nconst exportData = () => {\n  window.open('http:\u002F\u002Flocalhost:9999\u002Fadmin\u002Fexport')\n}\n```\n\n### 条件导出\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1740276052930-ee35b422-32d8-4a7e-8041-f88e508effb8.png)\n\nnull 传到后端是一个字符串  “null”\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1740276179342-548ea2fc-404c-451f-b061-70c4f5f890b0.png)\n\n在查询语句里面加上 空字符串的判断\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1740276253402-8d93e2f1-97c9-4b34-bded-52225d842f45.png)\n\n\n\n### 根据选择项导出\n\n解析参数\n\n```java\nString ids = admin.getIds();\nif (StrUtil.isNotBlank(ids)) {\n    String[] idsArr = ids.split(\",\");\n    admin.setIdsArr(idsArr);\n}\n```\n\n查询的 sql\n\n```xml\n\u003Cselect id=\"selectAll\" resultType=\"com.example.entity.Admin\">\n    select * from `admin`\n    \u003Cwhere>\n        \u003Cif test=\"username != null and username != ''\">username like concat('%', #{username}, '%')\u003C\u002Fif>\n        \u003Cif test=\"name != null and name != ''\">and name like concat('%', #{name}, '%')\u003C\u002Fif>  \u003C!-- 相当于 name like '%1%' -->\n        \u003Cif test=\"ids != null and ids != ''\">\n            and id in\n            \u003Cforeach collection=\"idsArr\" open=\"(\" close=\")\" separator=\",\" item=\"id\">\n                #{id}\n            \u003C\u002Fforeach>\n        \u003C\u002Fif>\n    \u003C\u002Fwhere>\n    order by id desc\n\u003C\u002Fselect>\n```\n\n参数的格式\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2025\u002Fpng\u002F751015\u002F1740277301730-94e9ddca-e160-48f6-9270-87acce1e922a.png)\n\n\n\n前端的导出的方法\n\n```vue\nconst exportData = () => {\n  let idsStr = data.ids.join(\",\")  \u002F\u002F 把数组转换成  字符串  [1,2,3]  ->  \"1,2,3\"\n  let url = `http:\u002F\u002Flocalhost:9999\u002Fadmin\u002Fexport?username=${data.username === null ? '' : data.username}`\n    + `&name=${data.name === null ? '' : data.name}`\n    + `&ids=${idsStr}`\n  window.open(url)\n}\n```\n\n## Excel 导入\n\n### 导入数据流程\n\n1. 获取输入流，构建 Reader 对象\n2. 通过Reader 读取 excel 里面的数据\n3. 将数据写到数据库\n\n```java\n\u002F**\n * 批量导入\n *\u002F\n@PostMapping(\"\u002Fimport\")\npublic Result importData(MultipartFile file) throws Exception {\n    \u002F\u002F  1. 拿到输入流 构建 reader\n    InputStream inputStream = file.getInputStream();\n    ExcelReader reader = ExcelUtil.getReader(inputStream);\n    \u002F\u002F  2. 通过Reader 读取 excel 里面的数据\n    reader.addHeaderAlias(\"账号\", \"username\");\n    reader.addHeaderAlias(\"名称\", \"name\");\n    reader.addHeaderAlias(\"电话\", \"phone\");\n    reader.addHeaderAlias(\"邮箱\", \"email\");\n    List\u003CAdmin> list = reader.readAll(Admin.class);\n    \u002F\u002F 3. 将数据写到数据库\n    for (Admin admin : list) {\n        adminService.add(admin);\n    }\n    return Result.success();\n}\n```\n\n前端页面\n\n```vue\n\u003Cel-upload\n    style=\"display: inline-block; margin-left: 10px\"\n    action=\"http:\u002F\u002Flocalhost:9999\u002Fadmin\u002Fimport\"\n    :show-file-list=\"false\"\n    :on-success=\"handleImportSuccess\"\n>\n  \u003Cel-button type=\"success\">批量导入\u003C\u002Fel-button>\n\u003C\u002Fel-upload>\n\n              \nconst handleImportSuccess = (res) => {\n  if (res.code === '200') {\n    ElMessage.success('批量导入数据成功')\n    load()\n  } else {\n    ElMessage.error(res.msg)\n  }\n}\n```\n\n","coding",1,6552,1521,"2025-02-23 10:49:24","2026-05-03 22:49:02","带小白做毕设2025系列课程","graduation-project-2025",{"project":18,"items":19},{"id":6,"title":15,"slug":16},[20,28,35,42,49,56,63,70,71,78,85,92,99,106,113,120,127,134,141,148,155],{"id":21,"uuid":22,"project_id":6,"title":23,"type":9,"status":10,"public_enabled":10,"views":24,"sort":25,"created_at":26,"updated_at":27,"project_title":15,"project_slug":16},766,"XmlcAcY0","00. 带小白做毕设2025课程介绍",19012,1512,"2025-02-22 15:29:01","2026-05-07 15:33:28.189425+00",{"id":29,"uuid":30,"project_id":6,"title":31,"type":9,"status":10,"public_enabled":10,"views":32,"sort":33,"created_at":34,"updated_at":14,"project_title":15,"project_slug":16},767,"nmjXCdVH","01. 前端Vue3 框架的快速搭建以及项目工程的讲解",15797,1513,"2025-02-13 17:13:40",{"id":36,"uuid":37,"project_id":6,"title":38,"type":9,"status":10,"public_enabled":10,"views":39,"sort":40,"created_at":41,"updated_at":14,"project_title":15,"project_slug":16},768,"pMdPrVeH","02. 使用Vue3集成Element-Plus快速搭建一个管理系统的页面框架",15959,1514,"2025-02-14 11:25:07",{"id":43,"uuid":44,"project_id":6,"title":45,"type":9,"status":10,"public_enabled":10,"views":46,"sort":47,"created_at":48,"updated_at":14,"project_title":15,"project_slug":16},771,"8PikYMQU","03. Springboot3框架的快速搭建以及项目工程的讲解",12768,1517,"2025-02-21 17:21:51",{"id":50,"uuid":51,"project_id":6,"title":52,"type":9,"status":10,"public_enabled":10,"views":53,"sort":54,"created_at":55,"updated_at":14,"project_title":15,"project_slug":16},772,"Q1TCG9Jj","04. Springboot3整合MyBatis实现数据库操作",11144,1518,"2025-03-07 15:50:30",{"id":57,"uuid":58,"project_id":6,"title":59,"type":9,"status":10,"public_enabled":10,"views":60,"sort":61,"created_at":62,"updated_at":14,"project_title":15,"project_slug":16},773,"De7YPnEc","05. Springboot3+vue3实现增删改查、分页查询、批量删除（上）",10827,1519,"2025-02-22 15:09:19",{"id":64,"uuid":65,"project_id":6,"title":66,"type":9,"status":10,"public_enabled":10,"views":67,"sort":68,"created_at":69,"updated_at":14,"project_title":15,"project_slug":16},774,"YKEHfsPd","06. Springboot3+vue3实现增删改查、分页查询、批量删除（下）",7760,1520,"2025-02-22 22:00:02",{"id":4,"uuid":5,"project_id":6,"title":7,"type":9,"status":10,"public_enabled":10,"views":11,"sort":12,"created_at":13,"updated_at":14,"project_title":15,"project_slug":16},{"id":72,"uuid":73,"project_id":6,"title":74,"type":9,"status":10,"public_enabled":10,"views":75,"sort":76,"created_at":77,"updated_at":14,"project_title":15,"project_slug":16},776,"1uMP9O6C","08. Springboot3+vue3实现登录注册功能",7964,1522,"2025-02-23 18:14:13",{"id":79,"uuid":80,"project_id":6,"title":81,"type":9,"status":10,"public_enabled":10,"views":82,"sort":83,"created_at":84,"updated_at":14,"project_title":15,"project_slug":16},777,"WahvQp1v","09. Springboot3+vue3实现JWT登录鉴权",7151,1523,"2025-02-23 21:58:00",{"id":86,"uuid":87,"project_id":6,"title":88,"type":9,"status":10,"public_enabled":10,"views":89,"sort":90,"created_at":91,"updated_at":14,"project_title":15,"project_slug":16},778,"QFFAqZh1","10. Springboot3+vue3实现文件上传和下载",6171,1524,"2025-02-24 14:16:27",{"id":93,"uuid":94,"project_id":6,"title":95,"type":9,"status":10,"public_enabled":10,"views":96,"sort":97,"created_at":98,"updated_at":14,"project_title":15,"project_slug":16},1278,"S2eL2g5L","11. Springboot3+vue3实现个人中心、修改密码",5945,1525,"2025-02-24 18:10:59",{"id":100,"uuid":101,"project_id":6,"title":102,"type":9,"status":10,"public_enabled":10,"views":103,"sort":104,"created_at":105,"updated_at":14,"project_title":15,"project_slug":16},1279,"LkN8Mmsn","12. Springboot3+Vue3实现系统公告功能",4967,1526,"2025-02-25 11:50:13",{"id":107,"uuid":108,"project_id":6,"title":109,"type":9,"status":10,"public_enabled":10,"views":110,"sort":111,"created_at":112,"updated_at":14,"project_title":15,"project_slug":16},1280,"i7wziuEN","13. Springboot3+Vue3实现角色权限控制",4446,1527,"2025-02-25 11:51:38",{"id":114,"uuid":115,"project_id":6,"title":116,"type":9,"status":10,"public_enabled":10,"views":117,"sort":118,"created_at":119,"updated_at":14,"project_title":15,"project_slug":16},1281,"pGwiTCRn","14. Springboot3+Vue3实现富文本编辑器功能",4578,1528,"2025-02-26 16:04:58",{"id":121,"uuid":122,"project_id":6,"title":123,"type":9,"status":10,"public_enabled":10,"views":124,"sort":125,"created_at":126,"updated_at":14,"project_title":15,"project_slug":16},1282,"tZ8iDql5","15. Springboot3+Vue3实现模块之间的关联",4454,1529,"2025-02-26 18:28:55",{"id":128,"uuid":129,"project_id":6,"title":130,"type":9,"status":10,"public_enabled":10,"views":131,"sort":132,"created_at":133,"updated_at":14,"project_title":15,"project_slug":16},1283,"gb01JPC2","16. Springboot3+Vue3实现echarts数据统计",4307,1530,"2025-03-03 16:58:21",{"id":135,"uuid":136,"project_id":6,"title":137,"type":9,"status":10,"public_enabled":10,"views":138,"sort":139,"created_at":140,"updated_at":14,"project_title":15,"project_slug":16},1284,"59bDkSFf","17. Springboot3+Vue3实现提交审核业务功能",3793,1531,"2025-03-04 11:58:16",{"id":142,"uuid":143,"project_id":6,"title":144,"type":9,"status":10,"public_enabled":10,"views":145,"sort":146,"created_at":147,"updated_at":14,"project_title":15,"project_slug":16},1285,"gApyb58X","18. Springboot3+Vue3实现预约审核业务功能",3332,1532,"2025-03-05 20:07:24",{"id":149,"uuid":150,"project_id":6,"title":151,"type":9,"status":10,"public_enabled":10,"views":152,"sort":153,"created_at":154,"updated_at":14,"project_title":15,"project_slug":16},1286,"XfpY5re0","19. Springboot3+Vue3实现前台首页的设计",3508,1533,"2025-03-05 20:08:12",{"id":156,"uuid":157,"project_id":6,"title":158,"type":9,"status":10,"public_enabled":10,"views":159,"sort":160,"created_at":161,"updated_at":14,"project_title":15,"project_slug":16},1287,"BnSPRBOc","20. Springboot3+Vue3实现前台轮播图和详情页的设计",4062,1534,"2025-03-17 17:13:36"]