使用POI完成Excel数据处理

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

咚!咚!咚!

昨天晚上接了个活。

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

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

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

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

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

嘿嘿....开动

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

说干就干。

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

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

package com;

import java.io.File;

public class FileDemo {

private static String filepath="D:\\test\\2023-05-10";

    public static void getfileName(String filepath) {

        //获取目录下所有文件的名字(不包括文件夹)
        File f3 = new File(filepath);
        File[] files = f3.listFiles();
        for (File fi : files){
            if (fi.isFile()){
                System.out.println(fi.getName());
            }
        }

    }
}

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

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

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

感谢出处不详,经久不息

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

public class FileDemo {

    private static String filepath="D:\\test\\2023-05-10";
    private static String xlsxdirName;
    private static String xlsxpath;
    ....
    public static void getfileName(String filepath) throws IOException {
        //获取目录下所有文件的名字(不包括文件夹)
        File f3 = new File(filepath);
        File[] files = f3.listFiles();
        for (File fi : files){
            if (fi.isFile()){
                System.out.println(fi.getName());
                //fi.renameTo(new File(xlsxdirName+".xlsx"));
                FileUtils.copyFile(fi,new File(xlsxdirName + ".xlsx"));
                //FileUtils.delete(fi);
            }
        }
    }
}

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

行吧...

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

    public static void readfile_(String filepath) throws FileNotFoundException, IOException {
        File file = new File(filepath);
        String[] list=file.list();
        for(int i=0;i<list.length;i++){
            if(file.isDirectory()){
                System.out.println(list[i]);
                xlsxdirName=list[i];
                xlsxpath=filepath + "\\" + xlsxdirName;
                getfileName(xlsxpath);
            }
        }
    }

很轻松。写个main函数。

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

package com.cecz;


import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * 目的:输入目录,将目录中所有的文件复制到另外一个目录并将其重命名为目录名
 * filepath:目录路径
 * xlsxdirName:目录里所有目录名称
 * xlsxpath:表格路径
 * */

public class FileDemo {

    private static String filepath="D:\\test\\2023-05-10";
    private static String xlsxdirName;
    private static String xlsxpath;

    public static void main(String[] args) throws IOException {
        readfile_(filepath);
    }
    public static void readfile_(String filepath) throws FileNotFoundException, IOException {
        File file = new File(filepath);
        String[] list=file.list();
        for(int i=0;i<list.length;i++){
            if(file.isDirectory()){
                System.out.println(list[i]);
                xlsxdirName=list[i];
                xlsxpath=filepath + "\\" + xlsxdirName;
                getfileName(xlsxpath);
            }
        }
    }
    //get目录下的name并将其重命名→输出文件夹:D:\dev-project\IdeaProjects\cecz-excel
    public static void getfileName(String filepath) throws IOException {
        //获取目录下所有文件的名字(不包括文件夹)
        File f3 = new File(filepath);
        File[] files = f3.listFiles();
        for (File fi : files){
            if (fi.isFile()){
                System.out.println(fi.getName());
                //fi.renameTo(new File(xlsxdirName+".xlsx"));
                FileUtils.copyFile(fi,new File(xlsxdirName + ".xlsx"));
                //FileUtils.delete(fi);
            }
        }
    }
}

下面开始搞POI

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

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

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

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

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

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

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

ArrayList搞得定啊!

找了一篇博客

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

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

package com.cpp;


import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.jupiter.api.Test;

import java.io.*;
import java.util.ArrayList;

public class ExcelReadTest {

    public static int count=0;

    public static ArrayList<String> list=new ArrayList<>();

    public static String path="D:\\dev-project\\IdeaProjects\\cecz-excel";


    public ExcelReadTest() throws FileNotFoundException {
    }

    //
    public static void main(String[] args) throws IOException {
        //将Java程序的输出结果写到txt文件
        PrintStream ps = new PrintStream("D:\\log.txt");
        System.setOut(ps);//sout出的都进log.txt中
        //遍历所有文件执行testRead07
        File allFiles = new File(path);
        String[] list=allFiles.list();
        for(int i=0;i<list.length;i++){
            if(allFiles.isDirectory()){
                if(list[i].endsWith(".xlsx")){
                    System.out.println("================"+list[i]+"=====================");
                    testRead07(list[i]);
                }
            }
        }
    }
    public static void testRead07(String fileName) throws IOException {
        //读取excel文件
        FileInputStream fileInputStream = new FileInputStream(path+"\\"+fileName);
        Workbook workbook = new XSSFWorkbook(fileInputStream);
        Sheet sheet = workbook.getSheetAt(0);
//        Row row = sheet.getRow(1);
//        Cell cell = row.getCell(1);
        //获取行数
        int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
        //输出行数到*********控制台
        System.out.println("行数="+physicalNumberOfRows);
        //遍历行,做对比
        for(int i=1;i<physicalNumberOfRows;i++){
            Row row = sheet.getRow(i);
            Cell cell = row.getCell(1);
//            System.out.println(cell.getStringCellValue());
            compare(cell.getStringCellValue());
        }
        //完成之后返回行数和list中的数据
        System.out.println("行数:"+list.size());
        for (String str:list) {
            //输出比对好的list数据到*******控制台
            System.out.println(str);
        }
        //清除list并count归零
        list.clear();
        count=0;
    }
    /**
     * 对比num和数组中的数据,
     * 如果数组里没有num,则放入,count+1。
     * 如果有,则不防暑
     * */
    public static void compare(String num){
        if(!list.contains(num)){
            list.add(num);
            count++;
        }
    }
}

接着遍历目录里所有的文件,并把数据打印在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根本没执行这段语句啊!

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

    private static void output(String caselsh) throws IOException {
        System.out.println(caselsh);
        boolean flag=false;
        FileInputStream fileInputStream = new FileInputStream(outputPath);
        FileOutputStream fileOutputStream = null;
        XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream);
        //设置自动换行样式
        XSSFCellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setWrapText(true);
        //处理list
        String content = String.join("\n", list);
        XSSFSheet sheet = workbook.getSheetAt(0);
        int rows = sheet.getPhysicalNumberOfRows();//获取当前文件行数
        for(int i=2;i<rows;i++){
            XSSFRow row = sheet.getRow(i);
            XSSFCell cell = row.getCell(1);
            if(cell.getStringCellValue().equals(caselsh)){
                System.out.println("找到了,在第"+i+"行!");
                //XSSFCell cell1 = sheet.getRow(i).createCell(7);
                XSSFCell cell1 = row.getCell(6);
                if(cell1==null){
                    cell1=row.createCell(6);
                    cell1.setCellValue(content);
                    cell1.setCellStyle(cellStyle);
                }else{
                    cell1=row.getCell(6);
                    cell1.setCellValue(content);
                    cell1.setCellStyle(cellStyle);
                }
                //cell1.setCellValue(1);
                //cell1.setCellStyle(cellStyle);
                flag=true;
                return;//结束本循环
            }
        }
        if(flag==false){
            //当循环结束,flag为false,表示本excel里没有此提单号(这他妈不正常),在底部新增一个一行一会再处理
            System.out.println("没有!");
        }

        fileOutputStream=new FileOutputStream(outputPath);
        try{
            System.out.println("save~~~~~");
            fileOutputStream.flush();
            workbook.write(fileOutputStream);
            fileOutputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

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

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

写break只跳出循环。

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值