原创/朱季谦
这款工具是笔者在2018年初开发完成的,时隔两载,偶然想起这款小工具,于是,决定将其开源,若有人需要做类似Java批处理实现整理文档的工具,可参考该工具逻辑思路来实现。
该工具是运行在windos系统上的,基于bat脚本与jar包形式协同运行。当时开发该工具的背景是,需要每天定时处理大批量的对账单txt文本信息,将其统一整合到一张Excel文档上,供会计人员获取。在没有该工具之前,项目组上的会计人员,需要每天手动打开大量txt文本,并从每份txt文档里,复制所需信息,然后将获取到的信息再复制到一份当日的Excel文档里。这个过程根据对账单数量而定,若数量过多,手动整理就需花费大量时间,且过程重复操作。基于这个原因,当时就开发了这款小工具,供会计人员使用,其带来的效果是,节省了大量整理时间:会计人员只需把每天邮件收到的批量对账单txt文件,统一放到指定目录下,点击start启动脚本,就可一键自动批量处理完成。
这个工具在当时的工作环境下,是行之有效的,但若换到另一种领域或者环境,还需二次开发做修改。工具整体实现的逻辑并不复杂,笔者只提供一种解决文档重复整理工作的小思路,仅做参考学习之用,毕竟,解决问题的本质不在于工具,而在于思路。
下面,就围绕着业务与具体实现来结束该自动处理工具。
整体结构如下:
1.对账单:将同类型对账单批量放入到对账单文件夹中,同类,即格式几乎一样,但数据不一样,如下所示:
2.对账单集处理结果:批量处理获取到的数据,会统一写入到一份自动生成的Excel文档里,该文档存放在“对账单集处理结果”目录底下;
3.Auto.jar:由Java语言开发的jar包,通过循环读取各txt文本数据,从读取文本指定字段数据,截取其名字与对应保证金、可用资金,再写入到自动生成的Excel文档里。
4.CopyName.bat:bat脚本,将本目录下的txt文件名批量写入到“对账单批量名字集合.txt”;
CopyName.bat如下:
1 @dir /a-d /b *.txt>对账单批量名字集合.txt
5.Start.bat:bat脚本,主要实现是,将CopyName.bat和“对账单批量名字集合.txt”都复制到“对账单”目录,然后执行CopyName.bat,将该目录底下的所有.txt后缀的文件名,写入到“对账单批量名字集合.txt”,再启动Auto.jar包,该jar会去“对账单批量名字集合.txt”获取所在目录下各txt文档名字,再根据这些名字去读取对应的txt文档。
Start.bat主要代码如下:
1 @echo off
2 copy /y CopyName.bat 对账单
3 copy /y 对账单批量名字集合.txt 对账单
4 cd D:\批量处理对账单\对账单
5 call CopyName.bat
6 java -jar D:\批量处理对账单\Auto.jar
综上,业务人员只需把对账单统一放入到“对账单”目录下:
点击Start.bat启动,就可得到以下指定数据的统一获取:
接下来,就具体分享一下Java部分的逻辑实现:
代码结构
以maven进行jar依赖,主要有Datas、ExportExcelBase、ExportExcleClient、PutExcel四个类。
1.引入依赖
1
2
3 org.apache.poi
4 poi
5 3.10-FINAL
6
7
8 org.projectlombok
9 lombok
10 1.18.2
11
12
2.设置导出基本类,根据需生成的Excel展示数据设置,笔者案例里只需展示“组合名”,“保证金占用金额”,“可用资金额”三个字段,故只需设置name,margin,avaFunds来接受获取到的值;
1 package com.put.data;
2 import lombok.Data;
3
4 /**
5 * 导出数据类
6 * @author zhujiqian
7 * @date 2020/10/27 20:09
8 */
9 @Data
10 public class Datas {
11 //名字
12 private String name;
13 //保证金
14 private String margin;
15 //可用资金
16 private String avaFunds;
17
18 public Datas(String name, String margin, String avaFunds) {
19 this.name = name;
20 this.margin = margin;
21 this.avaFunds = avaFunds;
22 }
23
24 }
3.设置Excel表格生成类
1 package com.put.put;
2
3 import org.apache.poi.hssf.usermodel.*;
4 import org.apache.poi.hssf.util.Region;
5
6 import java.io.File;
7 import java.io.FileNotFoundException;
8 import java.io.FileOutputStream;
9 import java.io.IOException;
10
11 /**
12 * HSSF - 提供读写Microsoft Excel格式档案的功能。
13 *
14 * XSSF - 提供读写Microsoft Excel OOXML格式档案的功能。
15 *
16 * @author zhujiqian
17 * @date 2020/10/27 20:33
18 */
19 public class ExportExcelBase {
20 private HSSFWorkbook hwb=null;
21 private HSSFSheet sheet=null;
22 public ExportExcelBase(HSSFWorkbook hwb,HSSFSheet sheet){
23 this.hwb=hwb;
24 this.sheet=sheet;
25 }
26 public HSSFWorkbook getHwb() {
27 return hwb;
28 }
29 public void setHwb(HSSFWorkbook hwb) {
30 this.hwb = hwb;
31 }
32 public HSSFSheet getSheet() {
33 return sheet;
34 }
35 public void setSheet(HSSFSheet sheet) {
36 this.sheet = sheet;
37 }
38
39 /**
40 * 创建设置表格头
41 */
42 public void createNormalHead(String headString,int colSum){
43 //创建表格标题行,第一行
44 HSSFRow row=this.sheet.createRow(0);
45 //创建指定行的列,第一列
46 HSSFCell cell=row.createCell(0);
47 //设置标题行默认行高
48 row.setHeight((short) 500);
49 //设置表格内容类型:0-数值型;1-字符串;2-公式型;3-空值;4-布尔型;5-错误
50 cell.setCellType(1);
51 //设置表格标题内容
52 cell.setCellValue(new HSSFRichTextString(headString));
53 // 指定合并区域
54 this.sheet.addMergedRegion(new Region(0, (short)0, 0, (short)colSum));
55 // 定义单元格格式,添加单元格表样式,并添加到工作簿
56 HSSFCellStyle cellStyle=this.hwb.createCellStyle();
57 // 设置单元格水平对齐居中类型
58 cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
59 // 指定单元格垂直居中对齐
60 cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
61 // 指定单元格自动换行
62 cellStyle.setWrapText(true);
63 //设置字体
64 HSSFFont font=this.hwb.createFont();
65 font.setBoldweight((short) 700);
66 font.setFontName("宋体");
67 font.setFontHeight((short) 300);
68 cellStyle.setFont(font);
69 cell.setCellStyle(cellStyle);
70 }
71
72 /**
73 *表单第二行
74 * @param params
75 * @param colSum
76 */
77 public void createNormalTwoRow(String[] params,int colSum){
78 HSSFRow row1=this.sheet.createRow(1);
79 row1.setHeight((short) 300);
80 HSSFCell cell2=row1.createCell(0);
81 cell2.setCellType(1);
82 cell2.setCellValue(new HSSFRichTextString("统计时间"+params[0]+"至"+params[1]));
83 this.sheet.addMergedRegion(new Region(1, (short) 0,1,(short)colSum));
84 HSSFCellStyle cellStyle=this.hwb.createCellStyle();
85 cellStyle.setAlignment((short) 2);
86 cellStyle.setVerticalAlignment((short) 1);
87 cellStyle.setWrapText(true);
88 HSSFFont font=this.hwb.createFont();
89 font.setBoldweight((short) 700);
90 font.setFontName("宋体");
91 font.setFontHeight((short) 250);
92 cellStyle.setFont(font);
93 cell2.setCellStyle(cellStyle);
94 }
95
96
97 /**
98 * 表单内容
99 * @param wb
100 * @param row
101 * @param col
102 * @param align
103 * @param val
104 */
105 public void cteateCell(HSSFWorkbook wb, HSSFRow row, int col, short align, String val) {
106 HSSFCell cell = row.createCell(col);
107 cell.setCellType(1);
108 cell.setCellValue(new HSSFRichTextString(val));
109 HSSFCellStyle cellstyle = wb.createCellStyle();
110 cellstyle.setAlignment(align);
111 cell.setCellStyle(cellstyle);
112 }
113
114
115 /**
116 * 文档输出流
117 * @param fileName
118 */
119 public void outputExcle(String fileName) {
120 FileOutputStream fos = null;
121 try {
122 fos = new FileOutputStream(new File(fileName));
123 this.hwb.write(fos);
124 fos.close();
125 } catch (FileNotFoundException var4) {
126 var4.printStackTrace();
127 } catch (IOException var5) {
128 var5.printStackTrace();
129 }
130 }
131 }
4.设置Excel根据数据导出类
1 package com.put.put;
2
3
4 import com.put.data.Datas;
5 import org.apache.poi.hssf.usermodel.*;
6
7 import java.text.SimpleDateFormat;
8 import java.util.Date;
9 import java.util.List;
10
11 /**
12 * TODO
13 *
14 * @author zhujiqian
15 * @date 2020/10/27 20:24
16 */
17 public class ExportExcleClient {
18 private HSSFWorkbook hwb=null;
19 private HSSFSheet sheet=null;
20
21 ExportExcelBase exportExcel = null;
22 SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
23
24 public ExportExcleClient() {
25 this.hwb = new HSSFWorkbook();
26 this.exportExcel = new ExportExcelBase(this.hwb, this.sheet);
27 }
28
29 /**
30 * 导出Excel
31 * @return
32 */
33 public String exportExcel() {
34 String a = this.df.format(new Date()) + "对账单集合.xls";
35 String b = "D:\\批量处理对账单\\对账单集处理结果\\" + a;
36 this.exportExcel.outputExcle(b);
37 return b;
38 }
39
40 /**
41 * 设置导出格式
42 * @param data
43 * @return
44 */
45 public String alldata(List data) {
46 if (data.size() != 0) {
47 this.sheet = this.exportExcel.getHwb().createSheet("对账单集合");
48 this.exportExcel.setSheet(this.sheet);
49 int number = 2;
50
51 for(int i = 0; i < number; ++i) {
52 this.sheet.setColumnWidth(i, 8000);
53 }
54
55 HSSFCellStyle cellStyle = this.hwb.createCellStyle();
56 cellStyle.setAlignment((short)2);
57 cellStyle.setVerticalAlignment((short)1);
58 cellStyle.setWrapText(true);
59 HSSFFont font = this.hwb.createFont();
60 font.setBoldweight((short)700);
61 font.setFontName("宋体");
62 font.setFontHeight((short)200);
63 cellStyle.setFont(font);
64 this.exportExcel.createNormalHead("对账单整合表", number);
65 String[] params = new String[]{this.df.format(new Date()), this.df.format(new Date())};
66 this.exportExcel.createNormalTwoRow(params, number);
67 HSSFRow row2 = this.sheet.createRow(2);
68 HSSFCell cell0 = row2.createCell(0);
69 cell0.setCellStyle(cellStyle);
70 cell0.setCellValue(new HSSFRichTextString("组合名"));
71 HSSFCell cell1 = row2.createCell(1);
72 cell1.setCellStyle(cellStyle);
73 cell1.setCellValue(new HSSFRichTextString("保证金占用金额"));
74 HSSFCell cell2 = row2.createCell(2);
75 cell2.setCellStyle(cellStyle);
76 cell2.setCellValue(new HSSFRichTextString("可用资金额"));
77
78 for(int i = 0; i < data.size(); ++i) {
79 System.out.println("==============" + ((Datas)data.get(i)).getName() + " " + ((Datas)data.get(i)).getMargin() + " " + ((Datas)data.get(i)).getAvaFunds());
80 HSSFRow row = this.sheet.createRow((short)i + 3);
81 this.exportExcel.cteateCell(this.hwb, row, 0, (short)6, ((Datas)data.get(i)).getName());
82 this.exportExcel.cteateCell(this.hwb, row, 1, (short)6, ((Datas)data.get(i)).getMargin());
83 this.exportExcel.cteateCell(this.hwb, row, 2, (short)6, ((Datas)data.get(i)).getAvaFunds());
84 }
85 }
86
87 return "";
88 }
89 }
5.批量读取txt文本截取指定数据类
1 package com.put;
2
3 import com.put.data.Datas;
4 import com.put.put.ExportExcleClient;
5 import java.io.*;
6 import java.util.ArrayList;
7 import java.util.List;
8
9 /**
10 * TODO
11 *
12 * @author zhujiqian
13 * @date 2020/10/27 20:08
14 */
15 public class PutExcel {
16 public PutExcel() {
17 }
18 public static List readTxtFile1(String TxtName, String filePath) {
19 ArrayList list = new ArrayList();
20 try {
21 System.out.println("该组合:" + TxtName);
22 File file = new File(filePath);
23 if (file.isFile() && file.exists()) {
24 InputStreamReader read = new InputStreamReader(new FileInputStream(file), "GBK");
25 BufferedReader bufferedReader = new BufferedReader(read);
26 String lineTxt = null;
27
28 while(true) {
29 do {
30 if ((lineTxt = bufferedReader.readLine()) == null) {
31 read.close();
32 return list;
33 }
34 } while(!lineTxt.contains("持仓保证金:") && !lineTxt.contains("保证金占用:") && !lineTxt.contains("保证金占用 Margin Occupied:") && !lineTxt.contains("保证金占用 Margin Occupied:"));
35 String ZiJin;
36 int a;
37 String b;
38 int c;
39 String d;
40 int e;
41 int f;
42 String E;
43 if (lineTxt.contains("持仓保证金:")) {
44 ZiJin = lineTxt.replace(" ", "");
45 a = ZiJin.indexOf("持");
46 b = ZiJin.substring(a);
47 c = b.indexOf(".");
48 d = b.substring(0, c + 3);
49 e = d.indexOf(":");
50 f = d.length();
51 E = d.substring(e + 1, f);
52 list.add(E);
53 } else if (lineTxt.contains("保证金占用:")) {
54 ZiJin = lineTxt.replace(" ", "");
55 a = ZiJin.indexOf("保");
56 b = ZiJin.substring(a);
57 c = b.indexOf(".");
58 d = b.substring(0, c + 3);
59 e = d.indexOf(":");
60 f = d.length();
61 E = d.substring(e + 1, f);
62 list.add(E);
63 } else if (lineTxt.contains("保证金占用 Margin Occupied:")) {
64 ZiJin = lineTxt.replace(" ", "");
65 a = ZiJin.indexOf("保");
66 b = ZiJin.substring(a);
67 c = b.indexOf(".");
68 d = b.substring(0, c + 3);
69 e = d.indexOf(":");
70 f = d.length();
71 E = d.substring(e + 1, f);
72 list.add(E);
73 } else if (lineTxt.contains("保证金占用 Margin Occupied:")) {
74 ZiJin = lineTxt.replace(" ", "");
75 a = ZiJin.indexOf("保");
76 b = ZiJin.substring(a);
77 c = b.indexOf(".");
78 d = b.substring(0, c + 3);
79 e = d.indexOf(":");
80 f = d.length();
81 E = d.substring(e + 1, f);
82 list.add(E);
83 }
84 }
85 } else {
86 System.out.println("找不到指定的文件");
87 }
88 } catch (Exception var16) {
89 System.out.println("读取文件内容出错");
90 var16.printStackTrace();
91 }
92 return list;
93 }
94 public static List readTxtFile2(String TxtName, String filePath) {
95 ArrayList list = new ArrayList();
96
97 try {
98
99 System.out.println("该组合:" + TxtName);
100 File file = new File(filePath);
101 if (file.isFile() && file.exists()) {
102 InputStreamReader read = new InputStreamReader(new FileInputStream(file), "GBK");
103 BufferedReader bufferedReader = new BufferedReader(read);
104 String lineTxt = null;
105
106 while(true) {
107 do {
108 if ((lineTxt = bufferedReader.readLine()) == null) {
109 read.close();
110 return list;
111 }
112 } while(!lineTxt.contains("可用资金:") && !lineTxt.contains("可用资金 Fund Avail.:") && !lineTxt.contains("可用资金 Fund Avail.:"));
113 String ZiJin;
114 int a;
115 String b;
116 int c;
117 String d;
118 int e;
119 int f;
120 String E;
121 if (lineTxt.contains("可用资金:")) {
122 ZiJin = lineTxt.replace(" ", "");
123 ZiJin = lineTxt.replace(" ", "");
124 a = ZiJin.indexOf("可");
125 b = ZiJin.substring(a);
126 c = b.indexOf(".");
127 d = b.substring(0, c + 3);
128 e = d.indexOf(":");
129 f = d.length();
130 E = d.substring(e + 1, f);
131 list.add(E);
132 } else if (lineTxt.contains("可用资金 Fund Avail.:")) {
133 ZiJin = lineTxt.replace(" ", "");
134 ZiJin = lineTxt.replace(" ", "");
135 a = ZiJin.indexOf("可");
136 b = ZiJin.substring(a);
137 c = b.lastIndexOf(".");
138 d = b.substring(0, c + 3);
139 e = d.indexOf(":");
140 f = d.length();
141 E = d.substring(e + 1, f);
142 list.add(E);
143 } else if (lineTxt.contains("可用资金 Fund Avail.:")) {
144 lineTxt.replace(" ", "");
145 ZiJin = lineTxt.replace(" ", "");
146 a = ZiJin.indexOf("可");
147 b = ZiJin.substring(a);
148 c = b.lastIndexOf(".");
149 d = b.substring(0, c + 3);
150 e = d.indexOf(":");
151 f = d.length();
152 E = d.substring(e + 1, f);
153 list.add(E);
154 }
155 }
156 } else {
157 System.out.println("找不到指定的文件");
158 }
159 } catch (Exception var16) {
160 System.out.println("读取文件内容出错");
161 var16.printStackTrace();
162 }
163
164 return list;
165 }
166
167 public static void main(String[] argv) {
168 String path = "D:\\批量处理对账单\\对账单\\对账单批量名字集合.txt";
169 List nums = writeToDat(path);
170 List listData = new ArrayList();
171 for(int i = 0; i < nums.size(); ++i) {
172 if (!(nums.get(i)).equals("对账单批量名字集合.txt")) {
173 listData.add(ZuHe(nums.get(i)));
174 System.out.println("--------==========" + ZuHe(nums.get(i)));
175 }
176 }
177
178 System.out.println("-----------" + listData);
179 ExportExcleClient client = new ExportExcleClient();
180 client.alldata(listData);
181 String url = client.exportExcel();
182 System.out.println(url);
183 }
184
185 public static Datas ZuHe(String TxtName) {
186 String address = "D:\\批量处理对账单\\对账单\\" + TxtName;
187 List r1 = readTxtFile1(TxtName, address);
188 List r2 = readTxtFile2(TxtName, address);
189 int c = TxtName.indexOf(".");
190 String txt = TxtName.substring(0, c);
191 System.out.println(txt);
192 System.out.println(r1);
193 Datas d = null;
194 if (r1.isEmpty() && r2.isEmpty()) {
195 if (r1.isEmpty() && r2.isEmpty()) {
196 System.out.println(txt + "--" + r1 + "---" + r2);
197 d = new Datas(txt, "无", "无");
198 }
199 } else {
200 d = new Datas(txt, r1.get(0), r2.get(0));
201 }
202 return d;
203 }
204 public static List writeToDat(String path) {
205 File file = new File(path);
206 ArrayList list = new ArrayList();
207 try {
208 String encoding = "GBK";
209 InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
210 BufferedReader bw = new BufferedReader(read);
211 String line = null;
212
213 while((line = bw.readLine()) != null) {
214 list.add(line);
215 }
216 bw.close();
217 } catch (IOException var7) {
218 var7.printStackTrace();
219 }
220 return list;
221 }
222 }
以上的代码,大部分都是在2018年左右写成,现再阅读,代码风格甚为稚嫩。我没有做大的修改,原因是,想要留住这些代码最初的样子,就像留住刚毕业那会的记忆一般。整体实现逻辑并不算复杂,但再简单的东西,能解决问题,都是值得分享的东西。在此基础上,还可继续完善与扩展,给需要用到的业务人员带来方便。
这是我开源的第一个小工具,以此为励,在以后的日子里,要更加深入地学习,并将所学与所得,多多分享。在我看来,输入的东西,不一定是自己的,但输出的,一定是自己的。
这,就是我喜欢输出的原因之一。
最后,附上第一个github源码链接:https://github.com/z924931408/auto-put-tool