搞出了啥?

通过easyexcel将csv文本文件转换为excel xlsx的jar包小工具。

  • csv是逗号分隔符,该小工具也支持其他分隔符如竖线(|)、井号(#)或其他自定义的字符串
  • csv只是文本文件后缀名,也可以是txt或其他后缀名的文本文件。
  • 编译环境jdk1.8
  • cmd、linux下可运行
  • 自动转换同jar包路径下的所有
  • 自动trim(去除单元格里内容的前后空格)
  • 字符集UTF8。

背景

业务部门天天找运维部门导数据,一般数据库导出csv文件还是可以的。但业务部门说只会用xls、xlsx,其他的不会。导出的文本文件有时候到几十上百M了,这是要多少行数据。

业务部门要看几百万数据量的excel?xlsx文件单个sheet最多也就1048576行,双击打开都要开半天。这是何苦呢。

运维的同事暂时也没啥好的办法,只能是split按行数先拆分文件,然后复制粘贴到excel,最后交付给业务部门。

Linux下也可以用Gnumeric ssconvert。主要是我也不会,还是写个jar给他们用吧。

ssconvert参考:
1、在Linux中CSV转换成XLSX
2、The Gnumeric Manual, version 1.12。见14.8.Converting Files


需求

需要一个将csv转换为xlsx文件的工具。


问题

先写了一个普通的通过POI HSSF将csv转excel的demo出来先,而后考虑以下问题:

  1. 分隔符如果不是逗号而是其他符号呢,比如竖线(|),或者井号(#),或者是字符串(如$$$,用三个连续的美元符号作为分隔符);
  2. 文件后缀名一定得是csv吗,其他的行不行,比如txt、DAT等等;
  3. 文本数据里有没有表头?
  4. 是一个个的写文件名去转换,还是直接转换同jar路径下的所有文件?
  5. 一个文本文件有多少行数据?xlxs最大也就1048576行,对于几百万行的要如何处理?
  6. 测试过程中一个十多万行的文本跑不出来,打断点观察发现跑到8w多9w的时候,有点跑不动的样子,行数count累加的很慢。POI HSSF貌似不能流输出?

代码

通过easyexcel将文本文件转xlsx。
之前一度卡在如何不建实体类来写xlsx文件上,看官网都是如下代码,感觉都要建个实体类?

excelWriter = EasyExcel.write(fileName, DemoData.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
excelWriter.write(data(), writeSheet);

最终发现将一行内的单元格内容构造为List<List>的样式即可,代码为:

List<List<String>> list = new ArrayList<List<String>>();
list.add(Arrays.asList(getTrimStrs(line, Delimiter_in)));
writer.write(list, sheet);

jar包代码:

public class CsvToXlsxUtil {//默认参数static String Delimiter_in = "|";static String fileType = "txt";static long rowmax = 1000000;// 最大行数100w行static boolean isHeader = true;static Pattern r = Pattern.compile("^\\.\\d+$");private static boolean getInput() {Scanner scanner=new Scanner(System.in);//输入分隔符,默认为竖线System.out.print("请输入分隔符,带双引号,如:, | #(默认为竖线|):");String din=scanner.nextLine();if(din!=null && din.length()>0){Delimiter_in=getDelimiter(din);}else{Delimiter_in=getDelimiter(Delimiter_in);}// 输入文件后缀名,默认为txtSystem.out.print("请输入待转换为xlsx的文件后缀名,如:txt csv(默认为txt):");String fin=scanner.nextLine();if(fin!=null && fin.length()>0){fileType = fin.toString();}// 是否有表头,默认有System.out.print("请输入是否有表头y/n(默认有):");String hIn=scanner.nextLine();if (hIn != null && hIn.length() > 0) {if (hIn.equals("n")) {isHeader = false;}}// 输入xlsx文件最大行数,默认为100wdelimiterSystem.out.print("请输入单个xlsx的最大行数(默认为100w行):");String maxin=scanner.nextLine();try {if (maxin != null && maxin.length()>0) {long temp = Long.parseLong(maxin);if (temp <= 1) {System.out.format("输出的单个xlsx文件最大行数为<=%s??取默认值100w行。\n", maxin);}else if(temp>1048576){System.out.format("xlsx文件最大行数为1048576,取默认值100w行。\n");}else{rowmax = temp;}}} catch (NumberFormatException e) {System.out.format("输入的是 %s ,不是长整型,取默认值100w行", maxin);}if (scanner != null) {scanner.close();}return true;}//当前目录下的所有csv文件转为xlsx文件// jdk环境1.8public static void main(String[] args) {File ftep = new File("");System.out.println("当前路径:"+ftep.getAbsolutePath());// 如果输入参数不对,则结束程序if(!getInput()){return;}File file = new File(ftep.getAbsolutePath());File[] filesName = file.listFiles();// 包含路径int count=0;if(filesName !=null && filesName.length>0){for (int i = 0; i < filesName.length; i++) {if (filesName[i].isFile() && filesName[i].getName().endsWith(fileType)) {String todoFile = filesName[i].toString();System.out.println("处理:"+ todoFile);System.out.println("输出:" );csvToXLSX(todoFile);count++;}}}System.out.println("---------结束-----------");System.out.format("转换了%d个%s文件", count, fileType);}/*** 读取CSV文件并写入到XLSX文件中,默认编码* @param csvFileAddress* @return*/public static String csvToXLSX(String csvFileAddress) {return csvToXLSX(csvFileAddress,"UTF-8");}/*** 读取CSV文件并写入到XLSX文件中,指定CSV文件编码* @param csvFileAddress* @param charset* @return*/public static String csvToXLSX(String csvFileAddress, String charset) {LineIterator it = null;int file_num = 0;//转换后的文件数long rownum = 0;String xlsxFileAddress = null;ExcelWriter writer = null;WriteSheet sheet = null;String header = null;try {it = FileUtils.lineIterator(new File(csvFileAddress), Charset.forName(charset).toString());while (it.hasNext()) {String line = it.nextLine();// 获取表头内容if(isHeader && file_num==0 && rownum==0 ){header = line.toString();}if(rownum==0){xlsxFileAddress = getXlsxFileAdd(csvFileAddress,file_num);writer = new ExcelWriterBuilder().file(xlsxFileAddress).build();sheet = new WriteSheet();if(isHeader && file_num>0){writeRow(header, writer, sheet);rownum++;}}writeRow(line, writer, sheet);rownum++;if(rownum>=rowmax){if (writer != null) {writer.finish();printRes(xlsxFileAddress, rownum);}rownum = 0;file_num++;}}if (writer != null) {writer.finish();printRes(xlsxFileAddress, rownum);}} catch (Exception e) {System.out.println("CsvToXlsxUtil exception :" + e);} finally {if (writer != null) {writer.finish();}LineIterator.closeQuietly(it);}return null;}private static void writeRow(String line, ExcelWriter writer, WriteSheet sheet) {List<List<String>> list = new ArrayList<List<String>>();list.add(Arrays.asList(getTrimStrs(line, Delimiter_in)));writer.write(list, sheet);return;}private static void printRes(String path,long rownum) {System.out.format("已转换xlsx文件:%s,行数:%s\n",getFileName(path), String.valueOf(rownum));}/*** 对字符串数组中的string做trim* @param str* @param delimiter* @return*/private static String[] getTrimStrs(String str,String delimiter) {String[] sps = str.split(delimiter);for (int i=0;i<sps.length;i++) {sps[i]=sps[i].trim();//由于netezza导出文本数据时, 小数如 0.14,会导出为 .14 ,这里做一下处理Matcher m = r.matcher(sps[i]);if (m.matches()) {sps[i] = "0".concat(sps[i]);}}return sps;}/*** 将绝对路径的csv文件名替换为xlsx* @return*/private static String getXlsxFileAdd(String csvFileAdd, int num) {String temp = csvFileAdd.substring(0, csvFileAdd.lastIndexOf("."));if (num == 0) {return temp + ".xlsx";} else {return temp + "_" + String.valueOf(num) + ".xlsx";}}/*** 根据资源路径切割获取文件名* @param path* @return*/private static String getFileName(String path){String[] paths = path.contains("\\")?path.split("\\\\"):path.split("/");return paths[paths.length-1];}/*** 常用分隔符数组* @param path 资源路径* @return*/private static String getDelimiter(String delimiter){if(delimiter!=null){HashSet<String> set=new HashSet<String>();set.add("*");set.add("^");set.add(":");set.add("|");set.add(".");set.add("\\");if(set.contains(delimiter)){return "\\" + delimiter;}}return delimiter;}
}

使用效果

构造了个有表头的三行数据的csv文件,在cmd下运行jar包,按4条提示一次输入参数:分隔符、后缀名、是否有表头、单个文件最大行数。之后输出运行结果。

试一下输出单个文件最大行数为3行,运行结果如下:

jar包下载

java环境1.8哦。

通过easyexcel将文本文件转为excel xlsx文件相关推荐

  1. Java 后端将上传的 csv 文件转为 Excel xlsx 文件

    一.概述 本地文件是 csv格式,将其转成 xlsx 或者 xls. 二.实现步骤 2.1 获取 csv 文件数据 由于前端的上传文件的数据类型是 MultipartFile,所以就通过获取输入流的方 ...

  2. Kettle 将文本文件转为excel输出

    关注微信公共号:小程在线 关注CSDN博客:程志伟的博客 一.将文本文件转为excel输出 1.选择打开,新建转换. 2.点击文本文件输入. 3.点击浏览,找到我们需要的文本文件 4.选择好之后点击增 ...

  3. ASP.NET Core 导入导出Excel xlsx 文件

    ASP.NET Core 使用EPPlus.Core导入导出Excel xlsx 文件,EPPlus.Core支持Excel 2007/2010 xlsx文件导入导出,可以运行在Windows, Li ...

  4. python读取xlsx文件找不到_在python中打开并读取excel .xlsx文件

    我正在尝试使用python打开一个excel .xlsx文件,但我无法找到办法,我尝试使用pandas但是它想要使用一个名为NumPy的库我试图安装numpy但它仍然可以找不到. 我也尝试过使用xlr ...

  5. Python读取和操作Excel(.xlsx)文件

    Python读取和操作Excel(.xlsx)文件 使用openpyxl库来控制excel文件(即.xlsx为后缀的文件).这里介绍一下excel数据的结构. 打开excel文件后生成一个workbo ...

  6. 实战:从文件夹中庞大的excel(.xlsx)文件中提取并整合数据

    从文件夹中庞大的excel(.xlsx)文件中提取并整合数据 Input 需要从文件夹树中提取有格式的单个数据格并汇总. 例如: 2017-2020x市蚊虫数据/2018/7月/abcds方法统计.x ...

  7. EasyExcel生成多个excel.xlsx进行压缩导出

    #java专栏# 背景 通过EasyExcel进行多个ExcelTypeEnum.XLSX类型Excel写入ZIP流时会发生Stream closed异常,以下通过使用ByteArrayOutputS ...

  8. golang 读取excel(xlsx文件) 时间格式解析

    问题起源 最近在写一个读取xlsx文件,并解析其中数据的项目,在所有的数据都就绪之后,却遇到了时间格式获取不正确的问题 时间格式 我查询到的结果 我的代码 func main() {f, err := ...

  9. java使用poi操作excel文件_使用 java apache poi 操作 excel xlsx 文件

    工作中临时需要对各种订单量进行简单的统计分析,为了方便简单学习了apache poi 对 xlsx 文件的基本操作,简单记录 1. 引包 org.apache.poi poi-ooxml 4.1.2 ...

  10. java使用poi(XSSFWorkbook)读取excel(.xlsx)文件

    其中最主要的区别在于jxl不支持.xlsx,而poi支持.xlsx 这里介绍的使用poi方式(XSSFWorkbook),实际上poi提供了HSSFWorkbook和XSSFWorkbook两个实现类 ...

最新文章

  1. linux终端字体大小6,[adminitrative][archlinux][setfont] 设置console的字体大小
  2. 使用pinchzoom实现头像剪裁
  3. folders默认配置 shell_分布式存储Ceph RBD-Mirror灾备方案(二)镜像模式配置
  4. boost::combine相关的测试程序
  5. 8086汇编-实验5(微调)-用栈实现数据交换位置
  6. 布谷鸟沙盒分析静态文件_“案例沙盒方法”喜提国际商学院协会(AACSB)2019年启发式创新奖...
  7. 广州站长沙龙 MIP 问题及答案
  8. Oracle基础 游标
  9. Elasticsearch核心知识图谱
  10. SELECT INTO和INSERT INTO SELECT的区别 类似aaa?a=1b=2c=3d=4,如何将问号以后的数据变为键值对 C# 获取一定区间的随即数 0、1两个值除随机数以外...
  11. Android Studio NDK初探
  12. 霍金警告人工智能危险性 称其若失控很难被阻止
  13. 一个Query Builder,征集更好用的Query Builder的设计方案
  14. uds协议之can总线程序升级
  15. matlab傅里叶变换程序
  16. 服务器虚拟化的重要性,服务器虚拟化:虚拟机迁移的重要性
  17. 帆软日期格式转换_FineReport中日期时间函数使用总结
  18. 三维地图之cesium入门使用
  19. npm 包解析 eml 文件
  20. 图解HTTP-HTTP

热门文章

  1. Linux 程序 动态库 静态库依赖关系
  2. 有效利用PLM系统能为企业带来什么?
  3. ECharts 前端数据可视化
  4. QAC静态代码测试工具试用介绍_c/c++
  5. JavaScript最详细基础语法总结(跳坑记录!)
  6. iis php前景,IIS下PHP的ISAPI和FastCGI比较
  7. 解决VirtualBox无法安装增强工具
  8. token是什么意思
  9. 如何利用Python进行数据分析
  10. 中债估值 收益率_收债