POI操作办公文件

简介

将用户信息导出为 excel 表格(导出数据)

将Excel 表中的信息录入到网站数据库(习题上传..)

开发中经常会设计到 excel 的处理,如导出 Excel ,导入 Excel 到数据库中

操作 Excel 目前比较流行的就是 Apoache POI 和 阿里巴巴的 easyExcel


Apache POI 官网 :https://poi.apache.org/

包名称说明

  • HSSF提供读写Microsoft Excel XLS格式档案的功能。
  • XSSF提供读写Microsoft Excel OOXML XLSX格式档案的功能。
  • HWPF提供读写Microsoft Word DOC格式档案的功能。
  • HSLF提供读写Microsoft PowerPoint格式档案的功能。
  • HDGF提供读Microsoft Visio格式档案的功能。
  • HPBF提供读Microsoft Publisher格式档案的功能。
  • HSMF提供读Microsoft Outlook格式档案的功能。

easyExcel

官网地址: https://github.com/alibaba/easyexcel

官方文档: https://www.yuque.com/easyexcel/doc/easyexcel

POI-Excel 写

  1. 建立一个项目,创建模块
  2. 引入 pom 依赖
  1. <!-- xls 03 的依赖-->
  2. <dependency>
  3. <groupId>org.apache.poi</groupId>
  4. <artifactId>poi</artifactId>
  5. <version>3.9</version>
  6. </dependency>
  7. <!--xlsx(07)-->
  8. <dependency>
  9. <groupId>org.apache.poi</groupId>
  10. <artifactId>poi-ooxml</artifactId>
  11. <version>3.9</version>
  12. </dependency>
  13. <!--日期格式化工具-->
  14. <dependency>
  15. <groupId>joda-time</groupId>
  16. <artifactId>joda-time</artifactId>
  17. <version>2.10.1</version>
  18. </dependency>

03 | 07 版本的写,就是对象不同,方法是一样的

需要注意: 2003版本和2007版本存在兼容性的问题! 03 最多只有 65535 行

  1. /**
  2. * excel03 写
  3. */
  4. @Test
  5. public void TestPOIWrite() throws IOException {
  6. String path = "D:\\CloudMusic\\";
  7. // 创建一个新的 Excel 工作簿
  8. Workbook workbook = new HSSFWorkbook();
  9. // 创建一个工作表
  10. Sheet sheet =workbook.createSheet("我是测试1");
  11. // 创建第一行
  12. Row row1 = sheet.createRow(0);
  13. // 创建单元格(1,1)
  14. Cell row1Cell1 = row1.createCell(0);
  15. row1Cell1.setCellValue("机构名称");
  16. // 创建单元格(1,2)
  17. Cell row1Cell2 = row1.createCell(1);
  18. row1Cell2.setCellValue("花花幼儿园");
  19. // 创建第二行
  20. Row row2 = sheet.createRow(1);
  21. // 创建单元格(2-1)
  22. Cell row2Cell1 = row2.createCell(0);
  23. row2Cell1.setCellValue("手机号");
  24. // 创建单元格(2,2)
  25. Cell row2Cell2 = row2.createCell(1);
  26. row2Cell2.setCellValue("13403504277");
  27. // 创建第三行
  28. Row row3 = sheet.createRow(2);
  29. // 创建单元格(3,1)
  30. Cell row3Cell1 = row3.createCell(0);
  31. row3Cell1.setCellValue("创建时间");
  32. // 创建单元格(3,2)
  33. Cell row3Cell2 = row3.createCell(1);
  34. String createDate = new DateTime().toString("yyyy-MM-dd hh:mm:ss");
  35. row3Cell2.setCellValue(createDate);
  36. // 文件输出流
  37. FileOutputStream fs = new FileOutputStream(path+"机构测试表03.xls");
  38. // 将工作表写入到 文件输出流
  39. workbook.write(fs);
  40. fs.flush();
  41. fs.close();
  42. System.out.println("文件生成成功");
  43. }

07 写入 xlsx

  1. /**
  2. * excel 07 版本写
  3. */
  4. @Test
  5. public void TestPOIWrit07() throws IOException {
  6. // 创建新的 Excel 工作薄,对象和 03 不一样
  7. Workbook workbook = new XSSFWorkbook();
  8. // 新建一个工作表 sheet
  9. Sheet sheet = workbook.createSheet();
  10. // 创建第一行
  11. Row row1 = sheet.createRow(0);
  12. // 创建单元格(1,1)
  13. Cell row1Cell1 = row1.createCell(0);
  14. row1Cell1.setCellValue("机构名称");
  15. // 创建单元格(1,2)
  16. Cell row1Cell2 = row1.createCell(1);
  17. row1Cell2.setCellValue("花花幼儿园");
  18. // 创建第二行
  19. Row row2 = sheet.createRow(1);
  20. // 创建单元格(2,1)
  21. Cell row2Cell1 = row2.createCell(0);
  22. row2Cell1.setCellValue("手机号");
  23. // 创建单元格(2,2)
  24. Cell row2Cell2 = row2.createCell(1);
  25. row2Cell2.setCellValue("13403504277");
  26. // 创建第三行
  27. Row row3 = sheet.createRow(2);
  28. // 创建单元格(3,1)
  29. Cell row3Cell1 = row3.createCell(0);
  30. row3Cell1.setCellValue("创建时间");
  31. // 创建单元格(3,2)
  32. Cell row3Cell2 = row3.createCell(1);
  33. String createDate = new DateTime().toString("yyyy-MM-dd hh:mm:ss");
  34. row3Cell2.setCellValue(createDate);
  35. // 文件输出流
  36. FileOutputStream out = new FileOutputStream(path+"测试07.xlsx");
  37. // 将文件写入输出流
  38. workbook.write(out);
  39. out.flush();
  40. out.close();
  41. System.out.println("文件生成完毕");
  42. }

大文件写 HSSF 03 版

缺点;:最多只能处理65536行,否则会抛出异常

  1. public void TestPOIBigWrite03() throws IOException {
  2. Workbook workbook = new HSSFWorkbook();
  3. Sheet sheet = workbook.createSheet();
  4. for (int i = 0; i < 100000; i++) {
  5. Row row = sheet.createRow(i);
  6. Cell cell = row.createCell(i);
  7. cell.setCellValue("测试"+i);
  8. }
  9. FileOutputStream out = new FileOutputStream(path+ "测试.xls");
  10. workbook.write(out);
  11. out.flush();
  12. out.close();
  13. }
  1. java.lang.IllegalArgumentException: Invalid row number (65536) outside
  2. allowable range (0..65535)
  1. java.lang.IllegalArgumentException: Invalid column index (256). Allowable column range for BIFF8 is (0..255) or ('A'..'IV')

优点:过程中写入缓存,不操作磁盘,最后一次性写入磁盘,速度快

大文件写 XSSF 07版

缺点: 缺点:写数据时速度非常慢,非常耗内存,也会发生内存溢出,如100万条

优点: 可以写较大的数据量,如 20万条

大文件写 SXSSF

优点: 可以写非常大的数据量,如100万条甚至更多条,写数据速度快,占用更少的内存

注意:

  1. 过程中会产生临时文件,需要清理临时文件

默认由100条记录被保存在内存中,如果超过这数量,则最前面的数据被写入临时文件

如果想自定义内存中数据的数量,可以使用 new SXSSFWorkbook (数量)

SXSSFWorkbook 来自官方的解释: 实现了 “BigGridDemo” 策略的流式 XSSFWorkbook版本, 这允许写入非常大的文件而不会耗尽内存,因为任何时候只有可配置的行部门被保存在内存中。

请注意,仍然可能会消耗大量内存,这些内存基于你正在使用的功能,例如合并区域,注释,仍在只存储在内存中,因此如果广泛使用,可能需要大量内存

POI-Excel 读

03 版本

  1. public List<String> file(MultipartFile file) throws IOException {
  2. List<String> list = new ArrayList<>();
  3. // 读取excel 工作簿
  4. Workbook workbook = new HSSFWorkbook(file.getInputStream());
  5. // 获取第一个工作表
  6. Sheet sheet = workbook.getSheetAt(0);
  7. // 工作表有多少行
  8. int lastRowNum = sheet.getLastRowNum();
  9. for (int i = 0; i < lastRowNum; i++) {
  10. // 获得行数
  11. Row row = sheet.getRow(i);
  12. if(row != null){
  13. // 获取最后一行的单元格
  14. int cellcount = row.getPhysicalNumberOfCells();
  15. for (int j = 0; j <cellcount ; j++) {
  16. Cell cell = row.getCell(j);
  17. if(cell != null){
  18. // 获取单元格的类型
  19. int cellType = cell.getCellType();
  20. String stringCellValue = null;
  21. // 判断单元格的数据类型
  22. switch (cellType){
  23. case HSSFCell
  24. .CELL_TYPE_STRING:
  25. System.out.println("String 类型");
  26. stringCellValue = cell.getStringCellValue();
  27. break;
  28. case HSSFCell.CELL_TYPE_BOOLEAN:
  29. System.out.println("布尔类型");
  30. stringCellValue = String.valueOf(cell.getBooleanCellValue());
  31. break;
  32. case HSSFCell.CELL_TYPE_BLANK:
  33. System.out.println("空");
  34. break;
  35. case HSSFCell.CELL_TYPE_NUMERIC:
  36. if(HSSFDateUtil.isCellDateFormatted(cell)){
  37. System.out.println("日期类型");
  38. Date value = cell.getDateCellValue();
  39. stringCellValue = new SimpleDateFormat("yyyy-MM-dd").format(value);
  40. }else {
  41. // 是数字
  42. System.out.println("将数字转换为 字符串");
  43. // 将 cell 类型转换为 字符串
  44. cell.setCellType(HSSFCell.CELL_TYPE_STRING);
  45. stringCellValue = cell.getStringCellValue();
  46. }
  47. break;
  48. case HSSFCell.CELL_TYPE_ERROR:
  49. System.out.println("数据类型错误");
  50. break;
  51. default:
  52. System.out.println("未知的数据类型");
  53. }
  54. System.out.print(stringCellValue+"||");
  55. list.add(stringCellValue);
  56. }
  57. }
  58. System.out.println();
  59. }
  60. }
  61. return list;
  62. }

POI 计算公式 03 xls 版本

  1. @PostMapping("/file1")
  2. public String file1(MultipartFile file) throws IOException {
  3. String result = null;
  4. Workbook workbook = new HSSFWorkbook(file.getInputStream());
  5. Sheet sheet = workbook.getSheetAt(0);
  6. Row row = sheet.getRow(0);
  7. Cell cell = row.getCell(2);
  8. // 公式计算器
  9. FormulaEvaluator evaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
  10. // 得到类型
  11. int cellType = cell.getCellType();
  12. // 判断是否是公式类型
  13. if(HSSFCell.CELL_TYPE_FORMULA == cellType){
  14. // 得到的是公式
  15. String cellFormula = cell.getCellFormula();
  16. // 计算后的单元格
  17. CellValue evaluate = evaluator.evaluate(cell);
  18. // 计算后的结果转化为 string
  19. result = evaluate.formatAsString();
  20. System.out.println(result);
  21. }
  22. return result;
  23. }

导出word 文件

  1. public void export() throws IOException {
  2. // 创建07版的word文档
  3. XWPFDocument word = new XWPFDocument();
  4. // 首页标题
  5. XWPFParagraph title = word.createParagraph();
  6. // 设置段落居中
  7. title.setAlignment(ParagraphAlignment.valueOf(STJc.INT_CENTER));
  8. XWPFRun titleRun = title.createRun();
  9. titleRun.setFontSize(20);
  10. titleRun.setFontFamily("楷体");
  11. titleRun.setBold(Boolean.TRUE);
  12. titleRun.setText("出师表/前出师表");
  13. // 换行
  14. titleRun.addBreak();
  15. // 第二行
  16. XWPFParagraph row1 = word.createParagraph();
  17. // 设置左对齐
  18. row1.setAlignment(ParagraphAlignment.CENTER);
  19. XWPFRun row1Run = row1.createRun();
  20. row1Run.setFontSize(12);
  21. row1Run.setFontFamily("黑体");
  22. row1Run.setText("作者: 诸葛亮");
  23. row1Run.addBreak();
  24. List<String> data = data();
  25. for (int i = 0; i <data.size() ; i++) {
  26. XWPFParagraph row = word.createParagraph();
  27. row.setAlignment(ParagraphAlignment.LEFT);
  28. XWPFRun row2Run = row.createRun();
  29. row2Run.setFontSize(12);
  30. row2Run.setFontFamily("黑体");
  31. row2Run.setText(data.get(i));
  32. row2Run.addBreak();
  33. }
  34. FileOutputStream fos = new FileOutputStream("C:\\Users\\ojd\\Desktop\\出师表.pdf");
  35. word.write(fos);
  36. fos.flush();
  37. fos.close();
  38. }

文档 XWPFDocument

XWPFDocument是对 .docx 文档操作的高级封装 API

创建新文档

XWPFDocument doc = new XWPFDocument();

读取已有文档:段落,表格,图片

XWDFDocument doc = new XWDFDocument(new FileInputStream(“。、deepoove.docx”));

我们就可以读取文档内容,包括段落,表格,图片等

  1. // 段落
  2. List<XWPFParagraph> paragraphs = doc.getParagraphs();
  3. // 表格
  4. List<XWPFTable> tables = doc.getTables();
  5. // 图片
  6. List<XWPFPictureData> allPictures = doc.getAllPictures();
  7. // 页眉
  8. List<XWPFHeader> headerList = doc.getHeaderList();
  9. // 页脚
  10. List<XWPFFooter> footerList = doc.getFooterList();

生成 文档

  1. try (FileOutputStream out = new FileOutputStream("simple.docx")) {
  2. doc.write(out);
  3. }

段落 XWPFParagraph 段落

段落是组合 Word文档的一个基本单元

创建新段落
  1. XWPFParagraph p1 = doc.createParagraph();

设置格式格式
  1. // 对齐方式
  2. p1.setAlignment(ParagraphAlignment.CENTER);
  3. // 边框
  4. p1.setBorderBottom(Borders.DOUBLE);
  5. p1.setBorderTop(Borders.DOUBLE);
  6. p1.setBorderRight(Borders.DOUBLE);
  7. p1.setBorderLeft(Borders.DOUBLE);
  8. p1.setBorderBetween(Borders.SINGLE);

基本元素 XWPFRun

XWPFRun是段落的基本单元,它可以是一个文本,可以是一张图片。

阅读文本
  1. // 获取文字
  2. String text = paragraph.getText();
  3. // 获取段落内所有XWPFRun
  4. List<XWPFRun> runs = paragraph.getRuns();

创建文本
  1. // 段落末尾创建XWPFRun
  2. XWPFRun run = paragraph.createRun();
  3. run.setText("为这个段落追加文本");

插入文本
  1. // 段落起始插入XWPFRun
  2. XWPFRun insertNewRun = paragraph.insertNewRun(0);
  3. insertNewRun.setText("在段落起始位置插入这段文本");

修改 XWPF 运行文本
  1. List<XWPFRun> runs = paragraph.getRuns();
  2. // setText默认为追加文本,参数0表示设置第0个位置的文本,覆盖上一次设置
  3. runs.get(0).setText("追加文本", 0);
  4. runs.get(0).setText("修改文本", 0);

样式:颜色、字体
  1. // 颜色
  2. run.setColor("00ff00");
  3. // 斜体
  4. run.setItalic(true);
  5. // 粗体
  6. run.setBold(true);
  7. // 字体
  8. run.setFontFamily("Courier");
  9. // 下划线
  10. run.setUnderline(UnderlinePatterns.DOT_DOT_DASH);

文本换行
  1. run.addCarriageReturn();

段落图片 XWPFPicture

抽取图片
  1. List<XWPFPictureData> allPictures = doc.getAllPictures();
  2. XWPFPicture pciture = allPictures.get(0);
  3. byte[] data = pciture.getPictureData().getData();

创建图片
  1. InputStream stream = new FileInputStream("./sayi.png");
  2. XWPFRun run = paragraph.createRun();
  3. run.addPicture(stream, XWPFDocument.PICTURE_TYPE_PNG, "Generated", Units.toEMU(256), Units.toEMU(256));

表格XWPFTTable

表格是构成 Word 文档的另一个重要基本元素。

创建新表格

创建一个三行三列的表格:

  1. XWPFTable table = doc.createTable(3, 3);

设置单元格文本

表格是由表格行XWPF行组成,单元每行是由格XWPFCell组成,每个格内部又是许多XWPFaragraph段落组成。

  1. table.getRow(1).getCell(1).setText("EXAMPLE OF TABLE");

等价于

  1. XWPFParagraph p1 = table.getRow(0).getCell(0).addParagraph();
  2. XWPFRun r1 = p1.createRun();
  3. r1.setText("EXAMPLE OF TABLE");

单位格图片

图片操作其实就是一段一段,然后一段操作中的图片。

  1. XWPFParagraph p1 = table.getRow(0).getCell(0).addParagraph();
  2. XWPFRun r1 = p1.createRun()

设置格样式:背景色、单元方式
  1. // 背景色
  2. cell.setColor(cellStyle.getBackgroundColor());
  3. // 获取单元格段落后设置对齐方式
  4. XWPFParagraph addParagraph = cell.addParagraph();
  5. addParagraph.setAlignment(ParagraphAlignment.CENTER);