實現excel導入導出功能,excel導入數據到頁面中,頁面數據導出生成excel文件
今天接到項目中的一個功能,要實現excel的導入,導出功能。這個看起來思路比較清楚,但是做起了就遇到了不少問題。
不過核心的問題,大家也不會遇到了。每個項目前台頁面,以及數據填充方式都不一樣,不過大多都是以json數據填充的。在導入excel填充json數據到頁面時,真的讓我差點吐血了。在做這個導入導出的時候,那一個禮拜都是黑暗的。
好了,廢話不多說了,我今天就給大家展示這個兩個功能的核心點,excel生成json數據和json數據生成excel文件。
一:從上傳文件到服務器,后台java解析,返回excel的json數據到前台。我自己從新做了一個簡單的測試項目,需要演示項目的(struts2),下面評論出來,謝謝大家支持。
1.excel生成json數據,用於導入excel文件到頁面中。
2.可以使用jxl,或者poi去實現這個,我兩種方式都采用了,下面是jar包(標記的jar是核心excel轉json數據的,包括jxl和poi,其它jar是項目的)
3.還是和上傳文件一樣,使用ajax,formdata對象將文件傳輸到后台,此時生成的是二進制文件,需要在服務器上生成所要的文件。
4.調用方法將上傳的文件轉化為json數據,使用poi要注意了,03版和07版使用的對象不一樣,代碼中有說明。
4.將得到的json數據返回前台。
5.下面是效果圖,最后面就附上源碼。
這是后台java處理代碼。
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
|
package
com.pan.files.action;
import
java.io.BufferedInputStream;
import
java.io.BufferedOutputStream;
import
java.io.File;
import
java.io.FileInputStream;
import
java.io.FileNotFoundException;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.io.InputStream;
import
java.io.OutputStream;
import
java.io.PrintWriter;
import
java.text.SimpleDateFormat;
import
java.util.ArrayList;
import
java.util.Date;
import
java.util.HashMap;
import
java.util.LinkedHashMap;
import
java.util.LinkedList;
import
java.util.List;
import
java.util.Map;
import
javax.servlet.http.HttpServletResponse;
import
com.alibaba.fastjson.JSON;
import
org.apache.commons.io.FileUtils;
import
org.apache.poi.hssf.usermodel.*;
import
org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import
org.apache.poi.poifs.filesystem.POIFSFileSystem;
import
org.apache.poi.ss.usermodel.*;
import
org.apache.poi.xssf.usermodel.XSSFDataFormat;
import
org.apache.poi.xssf.usermodel.XSSFWorkbook;
import
org.apache.struts2.ServletActionContext;
/*import org.springframework.web.multipart.MultipartFile;*/
public
class
ImportExcel {
private
File files;
//上傳的文件路徑
private
String filesFileName;
//文件名
public
File getFiles() {
return
files;
}
public
void
setFiles(File files) {
this
.files = files;
}
public
String getFilesFileName() {
return
filesFileName;
}
public
void
setFilesFileName(String filesFileName) {
this
.filesFileName = filesFileName;
}
/*
這個是jxl方式
dir:文件地址
*/
/*public static String excelToJson(File dir ) throws BiffException, IOException {
jxl.Workbook wb =jxl.Workbook.getWorkbook(dir); // 從文件流中獲取Excel工作區對象(WorkBook)
jxl.Sheet sheet = wb.getSheet(0); // 從工作區中取得頁(Sheet)
jxl.Cell[] header = sheet.getRow(0);
String json1 = "";
String[] arry = new String[sheet.getRows()];
for (int i = 1; i < sheet.getRows(); i++) { // 循環打印Excel表中的內容
Map hashMap = new HashMap();
ArrayList List = new ArrayList();
for (int j = 0; j < sheet.getColumns(); j++) {
jxl.Cell cell = sheet.getCell(j, i);
List.add(cell.getContents());
}
// 這個json字符串就是我們想要的,實際應用中可以直接返回該字符串
// String json = JSONObject.toJSONString(hashMap);
// String json = JSONObject.toJSONString(List);
String json = com.alibaba.fastjson.JSONArray.toJSONString(List);
json1 += json+",";
}
return "["+ json1.substring(0,json1.length()-1)+"]excel";
} */
public
void
targetFile()
throws
Exception {
//根據服務器的文件保存地址和原文件名創建目錄文件全路徑
String dirs= ServletActionContext.getServletContext()
.getRealPath(
"/image"
);
if
(files !=
null
){
File savedir =
new
File(dirs) ;
if
(! savedir.exists()) {
savedir.mkdirs() ;
}
}
//將上傳到服務器上的二進制文件寫成實際文件
File savefile =
new
File(dirs, filesFileName);
FileUtils.copyFile(files, savefile) ;
// String paremt = excelToJson(savefile);
LinkedHashMap<String, String> sjson = excelTojson(savefile);
HttpServletResponse response = ServletActionContext.getResponse();
response.setHeader(
"Content-type"
,
"text/html;charset=UTF-8"
);
//這句話的意思,是告訴servlet用UTF-8轉碼,而不是用默認的ISO8859
response.setCharacterEncoding(
"UTF-8"
);
PrintWriter out = response.getWriter();
// copy(this.files, di);
out.println(sjson);
}
public
static
LinkedHashMap<String,String> excelTojson(File file)
throws
IOException, Exception {
// 返回的map
LinkedHashMap<String,String> excelMap =
new
LinkedHashMap<>();
// Excel列的樣式,主要是為了解決Excel數字科學計數的問題
CellStyle cellStyle;
// 根據Excel構成的對象
Workbook wb;
// 如果是2007及以上版本,則使用想要的Workbook以及CellStyle
if
(file.getName().endsWith(
"xlsx"
)){
//07及07以后版本
wb =
new
XSSFWorkbook(
new
FileInputStream(file));
XSSFDataFormat dataFormat = (XSSFDataFormat) wb.createDataFormat();
cellStyle = wb.createCellStyle();
// 設置Excel列的樣式為文本
cellStyle.setDataFormat(dataFormat.getFormat(
"@"
));
}
else
{
//03版本
POIFSFileSystem fs =
new
POIFSFileSystem(file);
wb =
new
HSSFWorkbook(fs);
HSSFDataFormat dataFormat = (HSSFDataFormat) wb.createDataFormat();
cellStyle = wb.createCellStyle();
// 設置Excel列的樣式為文本
cellStyle.setDataFormat(dataFormat.getFormat(
"@"
));
}
// sheet表個數
int
sheetsCounts = wb.getNumberOfSheets();
// 遍歷每一個sheet
for
(
int
i =
0
; i < sheetsCounts; i++) {
Sheet sheet = wb.getSheetAt(i);
// 一個sheet表對於一個List
List list =
new
LinkedList();
// 將第一行的列值作為正個json的key
String[] cellNames;
// 取第一行列的值作為key
Row fisrtRow = sheet.getRow(
0
);
// 如果第一行就為空,則是空sheet表,該表跳過
if
(
null
== fisrtRow){
continue
;
}
// 得到第一行有多少列
int
curCellNum = fisrtRow.getLastCellNum();
// 根據第一行的列數來生成列頭數組
cellNames =
new
String[curCellNum];
// 單獨處理第一行,取出第一行的每個列值放在數組中,就得到了整張表的JSON的key
for
(
int
m =
0
; m < curCellNum; m++) {
Cell cell = fisrtRow.getCell(m);
// 設置該列的樣式是字符串
cell.setCellStyle(cellStyle);
cell.setCellType(Cell.CELL_TYPE_STRING);
// 取得該列的字符串值
cellNames[m] = cell.getStringCellValue();
}
for
(String s : cellNames) {
}
// 從第二行起遍歷每一行
int
rowNum = sheet.getLastRowNum();
System.out.println(
"總共有 "
+ rowNum +
" 行"
);
for
(
int
j =
1
; j <= rowNum; j++) {
// 一行數據對於一個Map
LinkedHashMap rowMap =
new
LinkedHashMap();
// 取得某一行
Row row = sheet.getRow(j);
int
cellNum = row.getLastCellNum();
// 遍歷每一列
for
(
int
k =
0
; k < cellNum; k++) {
Cell cell = row.getCell(k);
cell.setCellStyle(cellStyle);
cell.setCellType(Cell.CELL_TYPE_STRING);
// 保存該單元格的數據到該行中
rowMap.put(cellNames[k],cell.getStringCellValue());
}
// 保存該行的數據到該表的List中
list.add(rowMap);
}
// 將該sheet表的表名為key,List轉為json后的字符串為Value進行存儲
excelMap.put(sheet.getSheetName(),JSON.toJSONString(list,
false
));
}
wb.close();
return
excelMap;
}
public
static
void
main(String [] args)
throws
FileNotFoundException{
// createJson();
}
}
|
這是前台js文件:
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
|
$(
function
() {
$(
"#confirm"
).on(
"click"
,
function
(){
var
files = $(
"input"
).eq(0).val();
if
(files==
""
){
alert(
"請先上傳文件"
);
}
});
$(
"#cancel"
).on(
"click"
,
function
(){
// webform.close();
});
$(
"#fileUpload"
).change(
function
(){
var
val = $(
this
).val();
var
fileName = val.split(
"\\"
)[val.split(
"\\"
).length-1];
if
(val.indexOf(
"xls"
) != -1 || val.indexOf(
"xlsx"
) != -1) {
$(
"input"
).eq(0).val(fileName);
$(
'#formFile'
).ajaxSubmit({
url:
'excel_targetFile.action'
,
type:
'POST'
,
// data:{scmd:''}, 需要傳什么參數自己配置
success:
function
(data){
$(
"#confirm"
).on(
"click"
,
function
(){
alert(
"導入成功"
);
});
$(
"#cancel"
).on(
"click"
,
function
(){
alert(
"取消導入"
);
});
},
error:
function
(xhr){
alert(
"上傳出錯"
);
}
});
}
else
{
alert(
"請選擇正確的文件格式!"
);
//清空上傳路徑
$(
this
).val(
""
);
return
false
;
}
});
})
|
這是jsp頁面代碼:
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
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!
DOCTYPE
html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<
html
>
<
head
>
<
meta
http-equiv="Content-Type" content="text/html; charset=UTF-8">
<
title
>Insert title here</
title
>
<
script
src="./js/jquery-1.9.1.min.js" type="text/javascript"></
script
>
<
script
src="./js/jquery.form.js" type="text/javascript"></
script
>
<
script
src="./js/excelJs.js" type="text/javascript"></
script
>
<
style
type="text/css">
.file {
position: relative;
display: inline-block;
background: #D0EEFF;
border: 1px solid #99D3F5;
border-radius: 4px;
/* padding: 4px 12px; */
overflow: hidden;
color: #1E88C7;
text-decoration: none;
text-indent: 0;
line-height: 20px;
top:6px;
}
.file input {
position: absolute;
font-size: 100px;
right: 0;
top: 0;
opacity: 0;
}
.file:hover {
background: #AADFFD;
border-color: #78C3F3;
color: #004974;
text-decoration: none;
}
.positionFile{
margin-left: 10px;
margin-top: 30px;
}
.poConfirm{
margin-top: 40px;
margin-left: 65px;
}
</
style
>
</
head
>
<
body
>
<
form
id="formFile">
<
input
id="textId" type="text" value="" class="positionFile" readonly="readonly">
<
a
href="javascript:;" class="file">點擊上傳文件
<
input
type="file" id="fileUpload" name="files" >
</
a
>
<
br
>
<
input
type="button" id="confirm" value="確定" class="co-win-button poConfirm">
<
input
type="button" id="cancel" value="取消" class="co-win-button poConfirm">
</
form
>
</
body
>
</
html
>
|
好啦,到這里你以及看完了整個過程,重點是要理解其中的思路,尤其是轉化方法上面。下面我將介紹導出json數據到excel文件中,其實這個就簡單了就在后台將你的json數據調用轉化方法,然后寫入到excel文件中,返回前台設置響應讓其下載即可。
這個是導出excel核心的方法。
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
|
/*
src:定義下載的文件路徑
*/
public
static
JSONObject createExcel(String src, JSONArray json) {
JSONObject result =
new
JSONObject();
// 用來反饋函數調用結果
try
{
// 新建文件
File file =
new
File(src);
file.createNewFile();
OutputStream outputStream =
new
FileOutputStream(file);
// 創建工作薄
jxl.write.WritableWorkbook writableWorkbook = jxl.Workbook.createWorkbook(outputStream);
jxl.write.WritableSheet sheet = writableWorkbook.createSheet(
"First sheet"
,
0
);
// 創建新的一頁
// JSONArray jsonArray = json.getJSONArray("dt");// 得到data對應的JSONArray
JSONArray jsonArray = json;
// 得到data對應的JSONArray
jxl.write.Label label;
// 單元格對象
int
column =
0
;
// 列數計數
// 將第一行信息加到頁中。如:姓名、年齡、性別
JSONObject first = jsonArray.getJSONObject(
0
);
Iterator<String> iterator = first.keys();
// 得到第一項的key集合
while
(iterator.hasNext()) {
// 遍歷key集合
String key = (String) iterator.next();
// 得到key
label =
new
jxl.write.Label(column++,
0
, key);
// 第一個參數是單元格所在列,第二個參數是單元格所在行,第三個參數是值
sheet.addCell(label);
// 將單元格加到頁
}
// 遍歷jsonArray
for
(
int
i =
0
; i < jsonArray.size(); i++) {
JSONObject item = jsonArray.getJSONObject(i);
// 得到數組的每項
iterator = item.keys();
// 得到key集合
column =
0
;
// 從第0列開始放
while
(iterator.hasNext()) {
String key = iterator.next();
// 得到key
String value = item.getString(key);
// 得到key對應的value
label =
new
jxl.write.Label(column++, (i +
1
), value);
// 第一個參數是單元格所在列,第二個參數是單元格所在行,第三個參數是值
sheet.addCell(label);
// 將單元格加到頁
}
}
writableWorkbook.write();
// 加入到文件中
writableWorkbook.close();
// 關閉文件,釋放資源
}
catch
(Exception e) {
result.put(
"result"
,
"failed"
);
// 將調用該函數的結果返回
result.put(
"reason"
, e.getMessage());
// 將調用該函數失敗的原因返回
return
result;
}
// result.put("result", "successed");
return
result;
}
|