在利用Tablesaw进行数据分析和处理后,我想要将所有的表格数据存入同一个.xlsx文件的不同sheet当中。但是Tablesaw只支持将表格写入.csv文件,因此我就需要将.csv文件中的数据读取后存入.xlsx的指定sheet当中。
本文基于EasyExcel库实现上述功能,关于EasyExcel的介绍、安装和基本操作参考:
本文在以上两篇文章的基础上稍作修改后实现。
需要注意的是,文章中的方法读取到Excel的数据均为Srting字符串格式,因此数字也被存为String类型,将String类型的数字存入Excel文件后会引发警告,因此需要将String类型的数字转化为Double类型,详情请参考:
public static void CsvToXlsx(String oripath, String despath, String sheet)
{
ExcelWriter excelWriter = null;
File destFile = new File(despath);
File oriFile = new File(oripath);
File transFile = new File(destFile.getParent(),"trans.xlsx");
try {
if (destFile.exists())
{
//创建中转文件
//追加数据,中转文件与目标文件不能是同一个文件名
//withTemplate()指定模板文件,即复制一份; file() 中间文件名; autoCloseStream() 必须为True,自动关闭输入流
excelWriter = EasyExcel.write().withTemplate(destFile)
//.file() 指定目标文件,不能与模板文件是同一个文件
.file(transFile).autoCloseStream(true).build(); //
}
else
{
excelWriter = EasyExcel.write(destFile).build();
}
WriteSheet writeSheet = EasyExcel.writerSheet(sheet).needHead(false).build();
List<Map<Integer,Object>> list = importdata(oriFile); //返回的数据全部都是String类型的
//将列表中值为数字的字符串转化为Double型
Pattern pattern = Pattern.compile("-?[0-9]+.?[0-9]*");
for(int i=0;i<list.size();i++)
{
Map<Integer, Object> map = list.get(i);
for(int j=0;j<map.size();j++)
{
if(map.get(j)==null)continue;
String value = map.get(j).toString();
if(pattern.matcher(value).matches())
{
map.put(j, Double.parseDouble(value));
}
else
{
map.put(j, value);
}
}
list.set(i, map);
}
excelWriter.write(list, writeSheet);
}
finally
{
if (excelWriter != null)
{
excelWriter.finish();
}
}
if (transFile.exists())
{
//删除原文件
destFile.delete();
boolean result = transFile.renameTo(destFile);
if(result)System.out.println("改名成功");
else System.out.println("改名失败");
}
}
//导入数据
public static List<Map<Integer,Object>> importdata(File file)
{
List<Map<Integer,Object>> list = new LinkedList<>();
EasyExcel.read(file)
.excelType(ExcelTypeEnum.CSV) //如果原始为.xlsx文件则改成.XLSX
.sheet()
.registerReadListener(new AnalysisEventListener<Map<Integer,Object>>() {
@Override
public void invoke(Map<Integer, Object> integerStringMap, AnalysisContext analysisContext) {
// TODO Auto-generated method stub
list.add(integerStringMap);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// TODO Auto-generated method stub
System.out.println("数据读取完毕");
}
}).headRowNumber(0).doRead();
return list;
}
调用CsvToXlsx(String oripath, String despath, String sheet)
即可,若原始文件为.xlsx
格式,则需要修改函数importdata(File file)
中的.excelType(ExcelTypeEnum.CSV)
。
CsvToXlsx(String oripath, String despath, String sheet)
函数的输入参数分别表示:
oripath
:原始文件的路径,即分散的表格文件;despath
:想要写入目标文件的路径,如果不存在会自动创建;sheet
:想要写入目标文件中指定sheet的名称。下面我将以一个简单的案例介绍一下函数的使用方法。
假设我有如下两个表格,名称分别为a.csv
和b.csv
:
运行下面这两句程序,会生成一个名为text.xlsx
的文件:
CsvToXlsx("data/a.csv", "data/test.xlsx", "a");
CsvToXlsx("data/b.csv", "data/test.xlsx", "b");
打开文件,可以看到两个表格的内容均写入了文件的不同sheet当中: