当前位置:   article > 正文

使用POI完成Excel数据处理_poi 读取 excel

poi 读取 excel

感谢写代码的时候遇到的所有大恩人!磕头了磕头了!

咚!咚!咚!

昨天晚上接了个活。

每个月的月初需要把上个月的物流提单大包数和对应的ID上传到特定的表格中...

做法是先在在线表格取得提单号,根据提单号从邮件里找到对应提单的预报邮件,下载一个压缩包,压缩包里有一个Excel表格,表格里有几万个大包号,需要手动把大包号去重,把大包数量和大包ID提取出来塞到在线表格里。

这是其中一个表格,一共150个

 一个不熟练的人估计需要做一上午。

想了下,之前弄过POI,可以用POI把表格数据提出来,去重,最后输出出来,再往在线表格里塞,这样能节省几个小时。

嘿嘿....开动

首先:从邮件里搜索到下载这一步只能手工搞,我可以把压缩包重命名成提单号,解压缩出来带有提单号的目录,目录里只有一个Excel文件,用Java把Excel文件名改成提单号。遍历每个Excel文件,用POI把数据去重输出,输出数据数量和数据内容。

说干就干。

首先获取整个文件夹的文件名称并赋给文件夹内的文件,我参考了虫卅blog中的一部分代码

【java】如何获取整个文件夹的文件名称_java获取文件名称_虫卅的博客-CSDN博客

  1. package com;
  2. import java.io.File;
  3. public class FileDemo {
  4. private static String filepath="D:\\test\\2023-05-10";
  5. public static void getfileName(String filepath) {
  6. //获取目录下所有文件的名字(不包括文件夹)
  7. File f3 = new File(filepath);
  8. File[] files = f3.listFiles();
  9. for (File fi : files){
  10. if (fi.isFile()){
  11. System.out.println(fi.getName());
  12. }
  13. }
  14. }
  15. }

遍历出来xslx文件之后,使用file.renameTo(new File(filename));方法重命名,但是失败了,翻了不少博客又看了不少文章也找不出个所以然,倒是删除文件没问题。后来看了另外一位朋友的博客决定曲线救国,复制文件改名。

巧妙地解决Java文件重命名失败的问题-蒲公英云

大概意思就是引用一个FileUtils类,通过这个类去把文件复制。我找了几个博客看了下

感谢出处不详,经久不息

Java常用类(三):FileUtils类_出处不详,经久不息的博客-CSDN博客

  1. public class FileDemo {
  2. private static String filepath="D:\\test\\2023-05-10";
  3. private static String xlsxdirName;
  4. private static String xlsxpath;
  5. ....
  6. public static void getfileName(String filepath) throws IOException {
  7. //获取目录下所有文件的名字(不包括文件夹)
  8. File f3 = new File(filepath);
  9. File[] files = f3.listFiles();
  10. for (File fi : files){
  11. if (fi.isFile()){
  12. System.out.println(fi.getName());
  13. //fi.renameTo(new File(xlsxdirName+".xlsx"));
  14. FileUtils.copyFile(fi,new File(xlsxdirName + ".xlsx"));
  15. //FileUtils.delete(fi);
  16. }
  17. }
  18. }
  19. }

运行了下,没反应...找了半天才发现,文件复制+重命名成功了,但是复制到了项目目录下...

行吧...

下面搞遍历,遍历所有目录。

  1. public static void readfile_(String filepath) throws FileNotFoundException, IOException {
  2. File file = new File(filepath);
  3. String[] list=file.list();
  4. for(int i=0;i<list.length;i++){
  5. if(file.isDirectory()){
  6. System.out.println(list[i]);
  7. xlsxdirName=list[i];
  8. xlsxpath=filepath + "\\" + xlsxdirName;
  9. getfileName(xlsxpath);
  10. }
  11. }
  12. }

很轻松。写个main函数。

整个目录中所有的表格名都被改成提单号了

  1. package com.cecz;
  2. import org.apache.commons.io.FileUtils;
  3. import java.io.File;
  4. import java.io.FileNotFoundException;
  5. import java.io.IOException;
  6. /**
  7. * 目的:输入目录,将目录中所有的文件复制到另外一个目录并将其重命名为目录名
  8. * filepath:目录路径
  9. * xlsxdirName:目录里所有目录名称
  10. * xlsxpath:表格路径
  11. * */
  12. public class FileDemo {
  13. private static String filepath="D:\\test\\2023-05-10";
  14. private static String xlsxdirName;
  15. private static String xlsxpath;
  16. public static void main(String[] args) throws IOException {
  17. readfile_(filepath);
  18. }
  19. public static void readfile_(String filepath) throws FileNotFoundException, IOException {
  20. File file = new File(filepath);
  21. String[] list=file.list();
  22. for(int i=0;i<list.length;i++){
  23. if(file.isDirectory()){
  24. System.out.println(list[i]);
  25. xlsxdirName=list[i];
  26. xlsxpath=filepath + "\\" + xlsxdirName;
  27. getfileName(xlsxpath);
  28. }
  29. }
  30. }
  31. //get目录下的name并将其重命名→输出文件夹:D:\dev-project\IdeaProjects\cecz-excel
  32. public static void getfileName(String filepath) throws IOException {
  33. //获取目录下所有文件的名字(不包括文件夹)
  34. File f3 = new File(filepath);
  35. File[] files = f3.listFiles();
  36. for (File fi : files){
  37. if (fi.isFile()){
  38. System.out.println(fi.getName());
  39. //fi.renameTo(new File(xlsxdirName+".xlsx"));
  40. FileUtils.copyFile(fi,new File(xlsxdirName + ".xlsx"));
  41. //FileUtils.delete(fi);
  42. }
  43. }
  44. }
  45. }

下面开始搞POI

POI比较轻松,不过长时间不做这个有点记不清了,就去狂神那里看了一i眼。

4、Excel基本读取及注意_哔哩哔哩_bilibili

通过FirstTalent的博客知道了如何获取表格里的总行数

利用poi获取导入的Excel表格一共有多少行数据!!!_poi获取excel行数_FirstTalent的博客-CSDN博客

需要把每行的大包数找出来进行,删除重复的数据

思路是先初始化一个静态数组和一个int类型的count,每遍历一行数据就和数组里的数据进行比对,如果数组里没有的话就直接add进并且count++。遍历完所有行之后遍历数组并取得数组长度

想了一下这有没有什么类库能实现...一拍脑瓜

ArrayList搞得定啊!

找了一篇博客

如何在Java中将String值与String类型的ArrayList进行比较? | 码农家园

list.contains()方法,舒服了!

  1. package com.cpp;
  2. import org.apache.poi.ss.usermodel.Cell;
  3. import org.apache.poi.ss.usermodel.Row;
  4. import org.apache.poi.ss.usermodel.Sheet;
  5. import org.apache.poi.ss.usermodel.Workbook;
  6. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  7. import org.junit.jupiter.api.Test;
  8. import java.io.*;
  9. import java.util.ArrayList;
  10. public class ExcelReadTest {
  11. public static int count=0;
  12. public static ArrayList<String> list=new ArrayList<>();
  13. public static String path="D:\\dev-project\\IdeaProjects\\cecz-excel";
  14. public ExcelReadTest() throws FileNotFoundException {
  15. }
  16. //
  17. public static void main(String[] args) throws IOException {
  18. //将Java程序的输出结果写到txt文件
  19. PrintStream ps = new PrintStream("D:\\log.txt");
  20. System.setOut(ps);//sout出的都进log.txt中
  21. //遍历所有文件执行testRead07
  22. File allFiles = new File(path);
  23. String[] list=allFiles.list();
  24. for(int i=0;i<list.length;i++){
  25. if(allFiles.isDirectory()){
  26. if(list[i].endsWith(".xlsx")){
  27. System.out.println("================"+list[i]+"=====================");
  28. testRead07(list[i]);
  29. }
  30. }
  31. }
  32. }
  33. public static void testRead07(String fileName) throws IOException {
  34. //读取excel文件
  35. FileInputStream fileInputStream = new FileInputStream(path+"\\"+fileName);
  36. Workbook workbook = new XSSFWorkbook(fileInputStream);
  37. Sheet sheet = workbook.getSheetAt(0);
  38. // Row row = sheet.getRow(1);
  39. // Cell cell = row.getCell(1);
  40. //获取行数
  41. int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
  42. //输出行数到*********控制台
  43. System.out.println("行数="+physicalNumberOfRows);
  44. //遍历行,做对比
  45. for(int i=1;i<physicalNumberOfRows;i++){
  46. Row row = sheet.getRow(i);
  47. Cell cell = row.getCell(1);
  48. // System.out.println(cell.getStringCellValue());
  49. compare(cell.getStringCellValue());
  50. }
  51. //完成之后返回行数和list中的数据
  52. System.out.println("行数:"+list.size());
  53. for (String str:list) {
  54. //输出比对好的list数据到*******控制台
  55. System.out.println(str);
  56. }
  57. //清除list并count归零
  58. list.clear();
  59. count=0;
  60. }
  61. /**
  62. * 对比num和数组中的数据,
  63. * 如果数组里没有num,则放入,count+1。
  64. * 如果有,则不防暑
  65. * */
  66. public static void compare(String num){
  67. if(!list.contains(num)){
  68. list.add(num);
  69. count++;
  70. }
  71. }
  72. }

接着遍历目录里所有的文件,并把数据打印在txt文档里。

感谢太閤秀吉的文章

java输出结果到txt_将Java程序的输出结果写到txt文件中的方法_太閤秀吉的博客-CSDN博客

齐活,一个月干一天的工作俩小时搞定了...

下面开始考虑怎么把list里的数据塞进在线表格里的Cell里....

有点麻烦似乎...

更新于2023年8月8日

其实一点都不麻烦,只要找到了对应方法

我首先看了下如何实现单元格内容换行

这篇文章解决了我的问题

java POI实现Excel单元格内容换行_java实现excel换行_congcongxianshen的博客-CSDN博客

试了一下插入失败,报错空指针,网上说是需要先判断Cell是否为空,再使用对应方法..

应用错误收集

写上了,试了以下,仍然写入失败,程序直接退出,插入失败。

不过查找算是查找到了,去网上查了一下,哦原来是我没写输出流关闭流...

POI向Excel中写入数据及追加数据 - Ethon - 博客园 (cnblogs.com)

三个月没碰咋代码差点忘了

加了输出流之后运行直接报错Package should contain a content type part [M1.13],还是插入失败

打开Excel的时候发现文件坏了

网上查了一篇文章,原因是我输出流初始化的语句卸载了输入流初始化下边,这容易报错。原因不知道,算了,写在最下边。

POI操作EXCEL,追加或覆盖数据,输入输出流注意事项,jar包的选择 - allMayMight - 博客园 (cnblogs.com)

代码写完了,执行,还是报错,我在输出流附近打了个桩,NM根本没执行这段语句啊!

我把该犯的错误都犯了,能解决的都解决了!问题出在哪里了呢?

  1. private static void output(String caselsh) throws IOException {
  2. System.out.println(caselsh);
  3. boolean flag=false;
  4. FileInputStream fileInputStream = new FileInputStream(outputPath);
  5. FileOutputStream fileOutputStream = null;
  6. XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream);
  7. //设置自动换行样式
  8. XSSFCellStyle cellStyle = workbook.createCellStyle();
  9. cellStyle.setWrapText(true);
  10. //处理list
  11. String content = String.join("\n", list);
  12. XSSFSheet sheet = workbook.getSheetAt(0);
  13. int rows = sheet.getPhysicalNumberOfRows();//获取当前文件行数
  14. for(int i=2;i<rows;i++){
  15. XSSFRow row = sheet.getRow(i);
  16. XSSFCell cell = row.getCell(1);
  17. if(cell.getStringCellValue().equals(caselsh)){
  18. System.out.println("找到了,在第"+i+"行!");
  19. //XSSFCell cell1 = sheet.getRow(i).createCell(7);
  20. XSSFCell cell1 = row.getCell(6);
  21. if(cell1==null){
  22. cell1=row.createCell(6);
  23. cell1.setCellValue(content);
  24. cell1.setCellStyle(cellStyle);
  25. }else{
  26. cell1=row.getCell(6);
  27. cell1.setCellValue(content);
  28. cell1.setCellStyle(cellStyle);
  29. }
  30. //cell1.setCellValue(1);
  31. //cell1.setCellStyle(cellStyle);
  32. flag=true;
  33. return;//结束本循环
  34. }
  35. }
  36. if(flag==false){
  37. //当循环结束,flag为false,表示本excel里没有此提单号(这他妈不正常),在底部新增一个一行一会再处理
  38. System.out.println("没有!");
  39. }
  40. fileOutputStream=new FileOutputStream(outputPath);
  41. try{
  42. System.out.println("save~~~~~");
  43. fileOutputStream.flush();
  44. workbook.write(fileOutputStream);
  45. fileOutputStream.close();
  46. }catch (Exception e){
  47. e.printStackTrace();
  48. }
  49. }

找了一个小时,终于找到了,循环跳出写了个return,应该写break。

写runtrn不仅跳出循环,还跳出当前方法,直接下边不执行了,当然没法保存了!

写break只跳出循环。

这种二笔错误竟然犯了...自己去墙边罚站了

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/88852
推荐阅读
相关标签
  

闽ICP备14008679号