Fork me on GitHub

java对Excel办公软件的操作

java操作excel的组件除了apache的poi,还有jexcelapi(jxl)。

jxl和poi区别

POI为apache公司的一个子项目,主要是提供一组操作windows文档的Java API.
Java Excel俗称jxl是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容、创建新的Excel文件、更新已经存在的Excel文件。使用该API非Windows操作系统也可以通过纯Java应用来处理Excel数据表。因为是使用Java编写的,所以我们在Web应用中可以通过JSP、Servlet来调用API实现对Excel数据表的访问。

就这两者的区别,主要谈下JVM虚拟机内存消耗的情况.
数据量3000条数据,每条60列.JVM虚拟机内存大小64M.
使用POI:运行到2800条左右就报内存溢出.
使用JXL:3000条全部出来,并且内存还有21M的空间.
可想而知,在对内存的消耗方面差距还是挺大的.
也许是由于JXL在对资源回收利用方面做的还挺不错的.
关于两者效率方面,没有研究过,我想这个也是基于大数据量而言的,数据量小的话基本上差别不大,也不难被发觉.但是大的数据量,POI消耗的JVM内存远比JXL消耗的多.但相比提供的功能的话,JXL又相对弱了点.所以如果要实现的功能比较复杂的情况下可以考虑使用POI,但如果只想生成一些大数据量可以考虑使用JXL,或者CSV也是一个不错的选择,不过CSV并不是真正的excel.
其中jExcelAPI功能相对POI比较弱一点,但jExcelAPI对中文支持非常好,而且API是纯Java的,并不依赖Windows系统,即使运行在Linux下,它同样能够正确的处理Excel文件。
另外需要说明的是,jExcelAPI对图形和图表的支持很有限,而且仅仅识别PNG格式。

使用poi组件操作Excel

网页下载案例

Controller层代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* Excel下载
* @param response
* @throws Exception
*/
@RequestMapping("/download")
public void excelDownload(HttpServletResponse response) throws Exception{
ArrayList<Student> stuList = new ArrayList<Student>();
Student stu1 = new Student("张三", "男", 18, new Date());
Student stu2 = new Student("李四", "男", 50, new Date());
Student stu3 = new Student("王五", "男", 19, new Date());
stuList.add(stu1);
stuList.add(stu2);
stuList.add(stu3);
String fileName = new SimpleDateFormat("yyyyMMddhhmmssSSS").format(new Date());
fileName="D:/"+fileName+".xls";
System.out.println("fileName:"+fileName);
OutputStream out = new FileOutputStream(fileName);
//放入一行头文件
String[] headers = {"姓名","性别","年龄","日期"};
String[] params = {"name","sex","age","date"};
String str = "age:18,青年,50,中年;name:张三,张二";
String timestr = "yyyy-MM-dd";
ExcelUtils.exportExcel("测试", headers, params, stuList, Student.class, out, str, timestr);
//上面已经将生成额excel放入到out中了;这个方法中的一个方法response.getOutputStream()可以得到out
ExcelUtils.download(fileName, response);
}

ExcelUtils代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
package yh.utils;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
/**
* Excel的工具类 可分为4种:
* 1.包括:表格名,标题行内容,各标题对应的参数名,数据(用了泛型,保证通用性),实体对象的类型,用于反射,输出流(exportExcel)
* 2.包括:表格名,标题行内容,各标题对应的参数名,数据(用了泛型,保证通用性),实体对象的类型,用于反射,输出流,需要改变的内容(
* exportExcelChangeValue)
* 3.包括:表格名,标题行内容,各标题对应的参数名,数据(用了泛型,保证通用性),实体对象的类型,用于反射,输出流
* ,改变日期格式(exportExcelChangeDateFormat)
* 4.包括:表格名,标题行内容,各标题对应的参数名,数据(用了泛型,保证通用性),实体对象的类型
* ,用于反射,输出流,需要改变的内容,日期格式(exportExcel)
*
* @author YH
*
*/
public class ExcelUtils {
/**
*
* @param title
* 表格名
* @param headers
* 标题行内容
* @param params
* 各标题对应的参数名
* @param stuList
* 数据(用了泛型,保证通用性)
* @param clazz
* 实体对象的类型,用于反射
* @param out
* 输出流
* @throws Exception
*/
public static <T> void exportExcel(String title, String[] headers,
String[] params, ArrayList<T> stuList, Class<T> clazz,
OutputStream out) throws Exception {
exportExcel(title, headers, params, stuList, clazz, out, null, null);
}
/**
*
* @param title
* 表格名
* @param headers
* 标题行内容
* @param params
* 各标题对应的参数名
* @param stuList
* 数据(用了泛型,保证通用性)
* @param clazz
* 实体对象的类型,用于反射
* @param out
* 输出流
* @param str
* 需要改变的内容;比如:String str =
* "age:18,青年,50,中年;name:张三,张二";如果age属性的值为18
* ,改为青年;为50,改为中年。name属性值为张三,改为张二。
* @throws Exception
*/
public static <T> void exportExcelChangeValue(String title,
String[] headers, String[] params, ArrayList<T> stuList,
Class<T> clazz, OutputStream out, String str) throws Exception {
exportExcel(title, headers, params, stuList, clazz, out, str, null);
}
/**
*
* @param title
* 表格名
* @param headers
* 标题行内容
* @param params
* 各标题对应的参数名
* @param stuList
* 数据(用了泛型,保证通用性)
* @param clazz
* 实体对象的类型,用于反射
* @param out
* 输出流
* @param str
* 日期格式
* @throws Exception
*/
public static <T> void exportExcelChangeDateFormat(String title,
String[] headers, String[] params, ArrayList<T> stuList,
Class<T> clazz, OutputStream out, String str) throws Exception {
exportExcel(title, headers, params, stuList, clazz, out, null, str);
}
/**
*
* @author YH
* @param title
* 表格名
* @param headers
* 标题行内容
* @param params
* 各标题对应的参数名
* @param stuList
* 数据(用了泛型,保证通用性)
* @param clazz
* 实体对象的类型,用于反射
* @param out
* 输出流
* @param str
* 需要改变的内容;比如:String str = "age:18,青年,50,中年;name:张三,张二";
* 如果age属性的值为18,改为青年;为50,改为中年。
* @param timestr
* 日期格式
* @throws Exception
*/
public static <T> void exportExcel(String title, String[] headers,
String[] params, ArrayList<T> stuList, Class<T> clazz,
OutputStream out, String str, String timestr) throws Exception {
// 声明一个工作薄
HSSFWorkbook workbook = new HSSFWorkbook();
// 生成一个表格
HSSFSheet sheet = workbook.createSheet(title);
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth((short) 15);
// 生成一个样式
HSSFCellStyle style = workbook.createCellStyle();
// 设置这些样式
// style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 生成一个字体
HSSFFont font = workbook.createFont();
font.setColor(HSSFColor.VIOLET.index);
font.setFontHeightInPoints((short) 12);
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 把字体应用到当前的样式
style.setFont(font);
// 生成并设置另一个样式
HSSFCellStyle style2 = workbook.createCellStyle();
// style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style2.setBorderRight(HSSFCellStyle.BORDER_THIN);
style2.setBorderTop(HSSFCellStyle.BORDER_THIN);
style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);
style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
// 生成另一个字体
HSSFFont font2 = workbook.createFont();
font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
// 把字体应用到当前的样式
style2.setFont(font2);
// 产生表格标题行
HSSFRow row = sheet.createRow(0);
for (short i = 0; i < headers.length; i++) {
HSSFCell cell = row.createCell(i);
cell.setCellStyle(style);
HSSFRichTextString text = new HSSFRichTextString(headers[i]);
cell.setCellValue(text);
}
try {
// 遍历集合数据,产生数据行
int index = 0;
Field field = null;
if (str == null) {
for (T t : stuList) {
index++;
row = sheet.createRow(index);
for (int i = 0; i < params.length; i++) {
HSSFCell cell = row.createCell(i);
cell.setCellStyle(style2);
field = clazz.getDeclaredField(params[i]);
field.setAccessible(true);
String value = "";
if (field.get(t) != null) {
if (field.get(t) instanceof Date && timestr != null) {
SimpleDateFormat sdf = new SimpleDateFormat(
timestr);
value = sdf.format(field.get(t));
} else {
value = field.get(t).toString();
}
}
HSSFRichTextString richString = new HSSFRichTextString(
value);
HSSFFont font3 = workbook.createFont();
font3.setColor(HSSFColor.BLUE.index);
richString.applyFont(font3);
cell.setCellValue(richString);
}
}
} else {
ArrayList<String> changeParamsList = new ArrayList<String>();
Map<String, Map<String, String>> changeParams = new HashMap<String, Map<String, String>>();
String[] strs = str.split(";");
for (int i = 0; i < strs.length; i++) {
String[] strs1 = strs[i].split(":");
String[] strs2 = strs1[1].split(",");
Map<String, String> map = new HashMap<String, String>();
for (int j = 0; j < strs2.length; j += 2) {
map.put(strs2[j], strs2[j + 1]);
}
changeParamsList.add(strs1[0]);
changeParams.put(strs1[0], map);
}
for (T t : stuList) {
index++;
row = sheet.createRow(index);
for (int i = 0; i < params.length; i++) {
HSSFCell cell = row.createCell(i);
cell.setCellStyle(style2);
field = clazz.getDeclaredField(params[i]);
field.setAccessible(true);
String value = "";
if (field.get(t) != null) {
if (field.get(t) instanceof Date && timestr != null) {
SimpleDateFormat sdf = new SimpleDateFormat(
timestr);
value = sdf.format(field.get(t));
} else {
value = field.get(t).toString();
}
}
for (String param : changeParamsList) {
if (param.equals(params[i])) {
Map<String, String> map = changeParams
.get(param);
if (map.get(value) != null) {
value = map.get(value);
}
}
}
HSSFRichTextString richString = new HSSFRichTextString(
value);
HSSFFont font3 = workbook.createFont();
font3.setColor(HSSFColor.BLUE.index);
richString.applyFont(font3);
cell.setCellValue(richString);
}
}
}
workbook.write(out);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 文件的下载
*
* @param path
* @param response
*/
public static void download(String path, HttpServletResponse response) {
try {
// path是指欲下载的文件的路径。
File file = new File(path);
// 取得文件名。
String filename = file.getName();
// 以流的形式下载文件。
InputStream fis = new FileInputStream(path);
byte[] buffer = new byte[(int) file.length()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 设置response的Header
response.addHeader("Content-Disposition", "attachment;filename="
+ new String(filename.getBytes()));
response.addHeader("Content-Length", "" + file.length());
OutputStream toClient = new BufferedOutputStream(
response.getOutputStream());
response.setContentType("application/vnd.ms-excel;charset=gb2312");
toClient.write(buffer);
toClient.flush();
toClient.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

Excel的读取操作(ExcelTest):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package yh.test;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.junit.Test;
/**
* 通过poi实现对Excel文件的读取 对xls的操作只需要poi的jar包
*
* @author UCMED
*
*/
public class ExcelTest {
/**
* 读取xls类型
*/
@Test
public void xlsTest() {
try {
readXls();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void readXls() throws IOException {
InputStream is = new FileInputStream("D:\\20160322025438546.xls");
HSSFWorkbook hssfWorkbook = new HSSFWorkbook(is);
// 循环工作表Sheet
for (int numSheet = 0; numSheet < hssfWorkbook.getNumberOfSheets(); numSheet++) {
HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(numSheet);
if (hssfSheet == null) {
continue;
}
// 循环行Row
for (int rowNum = 0; rowNum <= hssfSheet.getLastRowNum(); rowNum++) {
HSSFRow hssfRow = hssfSheet.getRow(rowNum);
if (hssfRow == null) {
continue;
}
// 循环列Cell
for (int cellNum = 0; cellNum <= hssfRow.getLastCellNum(); cellNum++) {
HSSFCell hssfCell = hssfRow.getCell(cellNum);
if (hssfCell == null) {
continue;
}
System.out.print(" " + getValue(hssfCell));
}
System.out.println();
}
}
}
private String getValue(HSSFCell hssfCell) {
if (hssfCell.getCellType() == hssfCell.CELL_TYPE_BOOLEAN) {
return String.valueOf(hssfCell.getBooleanCellValue());
} else if (hssfCell.getCellType() == hssfCell.CELL_TYPE_NUMERIC) {
return String.valueOf(hssfCell.getNumericCellValue());
} else {
return String.valueOf(hssfCell.getStringCellValue());
}
}
}

需要的jar包支持:
poi-3.14.jar

项目地址

项目地址点这里
参考地址

「真诚赞赏,手留余香」