在日常工作中,我们常常会进行文件读写操作,除去我们最常用的纯文本文件读写,更多时候我们需要对Excel中的数据进行读取操作,本文将介绍Excel读写的常用方法,希望对大家学习Java读写Excel会有帮助。
在开始进行Java读写Excel前,我们需要先下一个jxl的jar包,这个jar包中提供了相关读写Excel的方法,在百度里所搜一下jxl.jar下载就会出现很多下载地址了,这里不再累述。随后我们将jxl.jar放到classpath下或者在工程的buildpath中添加jxl.jar后,便可以开始Java读写Excel的神秘之旅了。
1、Java读取Excel数据
首先,创建一个xls文件(如:jxltest.xls),然后在文件中添加一些数据,Excel文件创建完成后,我们便可以开始写代码读取了:
代码如下:
1. package jxl.zhanhj;
2. import java.io.File;
3. import java.io.FileInputStream;
4. import java.io.FileNotFoundException;
5. import java.io.IOException;
6. import java.io.InputStream;
7. import jxl.Sheet;
8. import jxl.Workbook;
9. import jxl.read.biff.BiffException;
10. public class GetExcelInfo {
11. public static void main(String[] args) {
12. new GetExcelInfo();
13. // 此处为我创建Excel路径:E:/zhanhj/studysrc/jxl下
14. new File("E:/zhanhj/studysrc/jxl/getExcleinfo.xls");
15. obj.readExcel(file);
16. }
17. // 去读Excel的方法readExcel,该方法的入口参数为一个File对象
18. public void readExcel(File file) {
19. try {
20. // 创建输入流,读取Excel
21. new FileInputStream(file.getAbsolutePath());
22. // jxl提供的Workbook类
23. Workbook wb = Workbook.getWorkbook(is);
24. // Excel的页签数量
25. int sheet_size = wb.getNumberOfSheets();
26. for (int index = 0; index < sheet_size; index++) {
27. // 每个页签创建一个Sheet对象
28. Sheet sheet = wb.getSheet(index);
29. // sheet.getRows()返回该页的总行数
30. for (int i = 0; i < sheet.getRows(); i++) {
31. // sheet.getColumns()返回该页的总列数
32. for (int j = 0; j < sheet.getColumns(); j++) {
33. String cellinfo = sheet.getCell(j, i).getContents();
34. System.out.println(cellinfo);
35. }
36. }
37. }
38. catch (FileNotFoundException e) {
39. e.printStackTrace();
40. catch (BiffException e) {
41. e.printStackTrace();
42. catch (IOException e) {
43. e.printStackTrace();
44. }
45. }
46. }
上面这个例子是一个很简单读取Excel并将各单元格的数据打印到控制台上,更多Excel操作方法,请参加jxl API。
下面我们再对上面的例子进行一个小小的扩展:
1、读取一个目录下的所有Excel文件
2、读取的每个Excel文件的数据写入到不同的txt中
代码如下:
1. package jxl.zhanhj;
2. import java.io.File;
3. import java.io.FileInputStream;
4. import java.io.FileNotFoundException;
5. import java.io.FileWriter;
6. import java.io.IOException;
7. import java.io.InputStream;
8. import java.io.PrintWriter;
9. import jxl.Sheet;
10. import jxl.Workbook;
11. import jxl.read.biff.BiffException;
12. public class GetExcelInfo {
13. public static void main(String[] args) {
14. new GetExcelInfo();
15. // 此处路径指定到目录而不是单个文件
16. new File("E:/zhanhj/studysrc/jxl");
17. if (file.isDirectory()) {
18. File[] files = file.listFiles();
19. for (File f : files)
20. // 如果还存在子目录则继续读取子目录下的Excel文件
21. if (f.isDirectory()) {
22. File[] subfiles = f.listFiles();
23. for (File fi : subfiles) {
24. // 对文件进行过滤,只读取Excel文件,非Excel文件不读取,否则会出错
25. if (fi.getName().indexOf(".xls") > 0) {
26. obj.readExcelWrite2TXT(fi);
27. }
28. }
29. else {
30. // 对文件进行过滤,只读取Excel文件,非Excel文件不读取,否则会出错
31. if (f.getName().indexOf(".xls") > 0) {
32. obj.readExcelWrite2TXT(f);
33. }
34. }
35. }
36. }
37. // 去读Excel的方法readExcel,该方法的入口参数为一个File对象
38. public void readExcelWrite2TXT(File file) {
39. // 创建文件输出流
40. null;
41. null;
42. try {
43. // 指定生成txt的文件路径
44. ".xls", "");
45. new FileWriter(file.getParent() + "/" + fileName + ".txt");
46. new PrintWriter(fw);
47. // 创建输入流,读取Excel
48. new FileInputStream(file.getAbsolutePath());
49. // jxl提供的Workbook类
50. Workbook wb = Workbook.getWorkbook(is);
51. // Excel的页签数量
52. int sheet_size = wb.getNumberOfSheets();
53. for (int index = 0; index < sheet_size; index++) {
54. // 每个页签创建一个Sheet对象
55. Sheet sheet = wb.getSheet(index);
56. // sheet.getRows()返回该页的总行数
57. for (int i = 0; i < sheet.getRows(); i++) {
58. // sheet.getColumns()返回该页的总列数
59. for (int j = 0; j < sheet.getColumns(); j++) {
60. String cellinfo = sheet.getCell(j, i).getContents();
61. // 将从Excel中读取的数据写入到txt中
62. out.println(cellinfo);
63. }
64. }
65. }
66. catch (FileNotFoundException e) {
67. e.printStackTrace();
68. catch (BiffException e) {
69. e.printStackTrace();
70. catch (IOException e) {
71. e.printStackTrace();
72. finally {
73. try {
74. // 记得关闭流
75. out.close();
76. fw.close();
77. // 由于此处用到了缓冲流,如果数据量过大,不进行flush操作,某些数据将依旧
78. // 存在于内从中而不会写入文件,此问题一定要注意
79. out.flush();
80. catch (IOException e) {
81. e.printStackTrace();
82. }
83. }
84. }
85. }
下面我们来一起对Java读取Excel流程做一个总结:
1、打开工作文件Workbook,在此之前先用java的io流创建或者读取文件
2、打开工作表Sheet
3、读行,然后读列(行和列是从0开始的)
4、进行数据进行操作
接着上一节的内容,本节主要讲述如何通过Java程序向Excel文件中写数据,包括:1、数据类型的控制;2、单元格及数据的格式化。
要快速上手,我们还是通过阅读代码来学习,这样可以帮助大家建立一个更直观的概念和认识。
1、写入Excel及数据类型控制
程序描述:通过Java程序新建一个名为test.xls的文件,并在Excel的第一行第一列写一个字符串,在第一行第二列写一个数字,在第一行第三列写一个日期。
1. package jxl.zhanhj;
2. import java.io.File;
3. import java.util.Date;
4. import jxl.Workbook;
5. import jxl.write.Label;
6. import jxl.write.WritableSheet;
7. import jxl.write.WritableWorkbook;
8. import jxl.write.Number;
9. import jxl.write.DateTime;
10. public class CreateExcel {
11. public static void main(String args[]) {
12. try {
13. // 打开文件
14. new File(
15. "test.xls"));
16. // 生成名为“sheet1”的工作表,参数0表示这是第一页
17. "sheet1", 0);
18. // 在Label对象的构造子中指名单元格位置是第一列第一行(0,0),单元格内容为string
19. new Label(0, 0, "string");
20. // 将定义好的单元格添加到工作表中
21. sheet.addCell(label);
22. // 生成一个保存数字的单元格,单元格位置是第二列,第一行,单元格的内容为1234.5
23. new Number(1, 0, 1234.5);
24. sheet.addCell(number);
25. // 生成一个保存日期的单元格,单元格位置是第三列,第一行,单元格的内容为当前日期
26. new DateTime(2, 0, new Date());
27. sheet.addCell(dtime);
28. // 写入数据并关闭文件
29. book.write();
30. book.close();
31. catch (Exception e) {
32. System.out.println(e);
33. }
34. }
35. }
几个重要对象解析:
1、WritableWorkbook:用于创建打开Excel文件
2、WritableSheet:用于创建Excel中的页签
3、Label:将单元格指定为文本型,并写入字符串
4、Number:将单元格指定为数字型,并可写入数字
5、DateTime:将单元格指定为日期型,并可写入日期
掌握这几个类及其方法后,我们便可以方便的向Excel进行写入操作了,更多对象请参见jxl api。
2、写入时单元格及数据的格式化
程序描述:在数据写入到单元格后,对数据进行格式化,包括字体大小、颜色等
1. package jxl.zhanhj;
2. import java.io.File;
3. import java.util.Date;
4. import jxl.CellType;
5. import jxl.Workbook;
6. import jxl.format.Border;
7. import jxl.format.BorderLineStyle;
8. import jxl.format.Colour;
9. import jxl.format.VerticalAlignment;
10. import jxl.format.Alignment;
11. import jxl.write.DateFormat;
12. import jxl.write.Label;
13. import jxl.write.NumberFormat;
14. import jxl.write.WritableCellFormat;
15. import jxl.write.WritableFont;
16. import jxl.write.WritableSheet;
17. import jxl.write.WritableWorkbook;
18. import jxl.write.Number;
19. import jxl.write.DateTime;
20. import jxl.write.WriteException;
21. public class CreateExcel {
22. public static void main(String args[]) {
23. try {
24. // 打开文件
25. WritableWorkbook book = Workbook
26. new File("test.xls"));
27. // 生成名为“sheet1”的工作表,参数0表示这是第一页
28. "sheet1", 0);
29. // 在Label对象的构造子中指名单元格位置是第一列第一行(0,0),单元格内容为string
30. new Label(0, 0, "string",
31. getDataCellFormat(CellType.LABEL));
32. // 将定义好的单元格添加到工作表中
33. sheet.addCell(label);
34. // 生成一个保存数字的单元格,单元格位置是第二列,第一行,单元格的内容为1234.5
35. new Number(1, 0, 1234.5,
36. getDataCellFormat(CellType.NUMBER));
37. sheet.addCell(number);
38. // 生成一个保存日期的单元格,单元格位置是第三列,第一行,单元格的内容为当前日期
39. new DateTime(2, 0, new Date(),
40. getDataCellFormat(CellType.DATE));
41. sheet.addCell(dtime);
42. // 写入数据并关闭文件
43. book.write();
44. book.close();
45. catch (Exception e) {
46. System.out.println(e);
47. }
48. }
49. public static WritableCellFormat getDataCellFormat(CellType type) {
50. null;
51. try {
52. // 字体样式
53. if (type == CellType.NUMBER || type == CellType.NUMBER_FORMULA) {// 数字
54. new NumberFormat("#.00");
55. new WritableCellFormat(nf);
56. else if (type == CellType.DATE) {// 日期
57. new DateFormat("yyyy-MM-dd hh:mm:ss");
58. new WritableCellFormat(df);
59. else {
60. new WritableFont(WritableFont.TIMES, 10,
61. false);
62. // 字体颜色
63. wf.setColour(Colour.RED);
64. new WritableCellFormat(wf);
65. }
66. // 对齐方式
67. wcf.setAlignment(Alignment.CENTRE);
68. wcf.setVerticalAlignment(VerticalAlignment.CENTRE);
69. // 设置上边框
70. wcf.setBorder(Border.TOP, BorderLineStyle.THIN);
71. // 设置下边框
72. wcf.setBorder(Border.BOTTOM, BorderLineStyle.THIN);
73. // 设置左边框
74. wcf.setBorder(Border.LEFT, BorderLineStyle.THIN);
75. // 设置右边框
76. wcf.setBorder(Border.RIGHT, BorderLineStyle.THIN);
77. // 设置背景色
78. wcf.setBackground(Colour.YELLOW);
79. // 自动换行
80. true);
81. catch (WriteException e) {
82. e.printStackTrace();
83. }
84. return wcf;
85. }
86. }
效果:
几个重要对象解析:
1、WritableCellFormat:用于格式化单元格
2、WritableFont:用于格式化字体
更多请参加jxl api。
到这里本节的讲解就结束了,下面我们可以总结出Excel的写入流程:
1、用WritableWorkbook创建Excel文件
2、用WritableSheet创建页签
3、用Label、Number、DateTime等创建单元格内容
4、在创建单元格内容时,我们可以给写一个格式化方法,对单元格内容进行格式化
5、格式化主要包括2类:单元格格式化(WritableCellFormat)、值的格式化(WritableFont)
继前两节的Java读取、写入Excel后,本期将推出Java修改Excel中数据以及格式的方法和技巧,如果大家学习了前面的读、写Excel,相信学习本节内容将是不费吹灰之力啊,不过要灵活的运用还需多加努力呀。
好了,为了展示Java修改Excel的魅力,我们先来设计一个业务场景,这个场景是根据最近做过的一件事设计出来的:
在一张Excel中,有一批学生信息数据如下图:
图1 Excel中的示例数据
在创建Excel时,将Excel中的所在省,所在市做成了下拉菜单以供选择,设置如下:
图2 所在省一览 图3 所在市一览
从图1我们会发现一个问题,王五的填写所在省为:四川省,而所在市为:石家庄,大家都石家庄是河北的省会,所以王五的这种情况属于Excel中的错误数据,那么下面我们来做一件事:将Excel中所有出现省市关系弄错了的,在Excel中进行标注出来!!
代码如下:
1. package jxl.zhanhj;
2.
3. import java.io.*;
4. import java.util.HashMap;
5.
6. import jxl.*;
7. import jxl.format.Alignment;
8. import jxl.format.Border;
9. import jxl.format.BorderLineStyle;
10. import jxl.format.Colour;
11. import jxl.format.VerticalAlignment;
12. import jxl.write.Label;
13. import jxl.write.WritableCellFormat;
14. import jxl.write.WritableFont;
15. import jxl.write.WritableSheet;
16. import jxl.write.WritableWorkbook;
17. import jxl.write.WriteException;
18.
19. public class UpdateExcel {
20. public static void main(String args[]) {
21. null;
22. new HashMap<String, String>();
23. map = getPCKV();
24. try {
25. // Excel获得文件
26. new File("update_test.xls"));
27. // 打开一个文件的副本,并且指定数据写回到原文件
28. new File("update_test.xls"), wb);
29. 0);
30. 0);
31. int colunms = sheet.getColumns();
32. // 不读表头
33. for (int i = 1; i < sheet.getRows(); i++) {
34. new StringBuffer();
35. // 将省市组合起来与HashMap进行匹配
36. 4, i).getContents().trim();
37. 5, i).getContents().trim();
38. "-").append(city);
39. // 如果不匹配,则在该行的最后加入标注信息
40. if (!map.containsValue(pcin.toString())) {
41. new Label(colunms, i, "省市选择出错",
42. getDataCellFormat());
43. wsheet.addCell(label);
44. }
45. }
46. book.write();
47. catch (Exception e) {
48. System.out.println(e);
49. finally {
50. try {
51. book.close();
52. catch (IOException e) {
53. e.printStackTrace();
54. }
55. }
56. }
57.
58. // 设置标注的格式为黄底红字
59. public static WritableCellFormat getDataCellFormat() {
60. null;
61. try {
62. new WritableFont(WritableFont.TIMES, 10,
63. false);
64. // 字体颜色
65. wf.setColour(Colour.RED);
66. new WritableCellFormat(wf);
67. // 对齐方式
68. wcf.setAlignment(Alignment.CENTRE);
69. wcf.setVerticalAlignment(VerticalAlignment.CENTRE);
70. // 设置上边框
71. wcf.setBorder(Border.TOP, BorderLineStyle.THIN);
72. // 设置下边框
73. wcf.setBorder(Border.BOTTOM, BorderLineStyle.THIN);
74. // 设置左边框
75. wcf.setBorder(Border.LEFT, BorderLineStyle.THIN);
76. // 设置右边框
77. wcf.setBorder(Border.RIGHT, BorderLineStyle.THIN);
78. // 设置背景色
79. wcf.setBackground(Colour.YELLOW);
80. // 自动换行
81. true);
82. catch (WriteException e) {
83. e.printStackTrace();
84. }
85. return wcf;
86. }
87.
88. // 省市对应关系Map
89. public static HashMap<String, String> getPCKV() {
90. new HashMap<String, String>();
91. "01", "河北省-石家庄");
92. "02", "河北省-秦皇岛");
93. "03", "河北省-唐山");
94. "04", "四川省-成都");
95. "05", "四川省-绵阳");
96. "06", "四川省-达州");
97. "07", "广西省-桂林");
98. "08", "广西省-南宁");
99. "09", "广西省-柳州");
100. return map;
101. }
102. }
代码执行结果如图所示:
图4 执行结果
到这里,Java修改Excel单元格的数据及格式便告一段落了,本节给出了一个较为简单的场景进行了讲述,目的在于引导大家学习Java修改Excel的常用流程和方法,若读者能将Java操作Excel学得更深,往往可以发挥更大的作用。比如程序中利用HashMap来存储对应关系,如果要将全国的省市纳入进来,利用HashMap不是很好的做好,我们可以改成通过利用数据库来达到同样的效果,这里的改进留给读者。
读到这里,可能有部分读者会产生疑问,这种操作,直接在Excel中,我们不是也可以操作吗?为什么通过Java来修改,是不是多此一举了?其实不然,如果读者将Java读写文件结合起来,以及在将此程序稍微扩展一下,对每个Excel的所有页签进行遍历,那么Java程序处理的数据里和复杂度,远远不是单纯的Excel能企及的。举个简单的场景(仅仅将上述场景进行扩展):
如果一个学院要统计该学院所有学生的信息【格式和图1一样】,每个级发一个Excel,每个级不同专业的学生放在不同的页签中(sheet),如Excel样式下图所示:
图5 09级学生信息统计表
图6 10级学生信息统计表
最终,学院要根据收集上来的学生信息导入到数据库中,如果你是那个负责导入数据的人,你便通过Java读写Excel功能将所有的数据转化成SQL语句,同时可以判断出哪些同学信息填写错误,是不是这种应用变得更有意义了?