感谢写代码的时候遇到的所有大恩人!磕头了磕头了!
咚!咚!咚!
昨天晚上接了个活。
每个月的月初需要把上个月的物流提单大包数和对应的ID上传到特定的表格中...
做法是先在在线表格取得提单号,根据提单号从邮件里找到对应提单的预报邮件,下载一个压缩包,压缩包里有一个Excel表格,表格里有几万个大包号,需要手动把大包号去重,把大包数量和大包ID提取出来塞到在线表格里。
这是其中一个表格,一共150个
一个不熟练的人估计需要做一上午。
想了下,之前弄过POI,可以用POI把表格数据提出来,去重,最后输出出来,再往在线表格里塞,这样能节省几个小时。
嘿嘿....开动
首先:从邮件里搜索到下载这一步只能手工搞,我可以把压缩包重命名成提单号,解压缩出来带有提单号的目录,目录里只有一个Excel文件,用Java把Excel文件名改成提单号。遍历每个Excel文件,用POI把数据去重输出,输出数据数量和数据内容。
说干就干。
首先获取整个文件夹的文件名称并赋给文件夹内的文件,我参考了虫卅blog中的一部分代码
【java】如何获取整个文件夹的文件名称_java获取文件名称_虫卅的博客-优快云博客
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));方法重命名,但是失败了,翻了不少博客又看了不少文章也找不出个所以然,倒是删除文件没问题。后来看了另外一位朋友的博客决定曲线救国,复制文件改名。
大概意思就是引用一个FileUtils类,通过这个类去把文件复制。我找了几个博客看了下
Java常用类(三):FileUtils类_出处不详,经久不息的博客-优快云博客
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眼。
通过FirstTalent的博客知道了如何获取表格里的总行数
利用poi获取导入的Excel表格一共有多少行数据!!!_poi获取excel行数_FirstTalent的博客-优快云博客
需要把每行的大包数找出来进行,删除重复的数据
思路是先初始化一个静态数组和一个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文件中的方法_太閤秀吉的博客-优快云博客
齐活,一个月干一天的工作俩小时搞定了...
下面开始考虑怎么把list里的数据塞进在线表格里的Cell里....
有点麻烦似乎...
更新于2023年8月8日
其实一点都不麻烦,只要找到了对应方法
我首先看了下如何实现单元格内容换行
这篇文章解决了我的问题
java POI实现Excel单元格内容换行_java实现excel换行_congcongxianshen的博客-优快云博客
试了一下插入失败,报错空指针,网上说是需要先判断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只跳出循环。
这种二笔错误竟然犯了...自己去墙边罚站了