Java 通過Xml匯出Excel檔案,Java Excel 匯出工具類,Java匯出Excel工具類
==============================
©Copyright 蕃薯耀 2017年9月13日
http://www.cnblogs.com/fanshuyao/
直接上程式碼:
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletOutputStream;
import org.apache.commons.lang.StringUtils;
public class ExportUtil {
/**
* 只匯出包含在includeFieldNames中的屬性
* @param sheetName 表格左下角的名稱
* @param firstRowTitle 第一行需要設定的title,為空則不設定
* @param list 需要顯示的資料集合
* @param headers 表格屬性列名陣列
* @param includeFieldNames 包含的實體屬性
* @param widths 列的寬度,不設定(為Null)則預設,設定則根據對應的列寬設定(可以是一個,可以是對應的數量,整形數字,如200)
* @param outputStream 與輸出裝置關聯的流物件,可以將EXCEL文件匯出到本地檔案或者網路中
* @param datetimePattern 時間形式,當為空(Null或空字串)時預設為yyyy-MM-dd HH:mm:ss
* @throws Exception
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> void exportExcel(String sheetName, String firstRowTitle, List<T> list, String[] headers, String[] includeFieldNames, Integer[] widths,
ServletOutputStream outputStream, String datetimePattern) throws Exception {
// 預設輸出格式
if (StringUtils.isBlank(datetimePattern)) {
datetimePattern = "yyyy-MM-dd HH:mm:ss";
}
// 建立一個excel應用檔案
StringBuffer sb = new StringBuffer();
sb.append("<?xml version=\"1.0\"?>");
sb.append("\n");
sb.append("<?mso-application progid=\"Excel.Sheet\"?>");
sb.append("\n");
sb.append("<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"");
sb.append("\n");
sb.append(" xmlns:o=\"urn:schemas-microsoft-com:office:office\"");
sb.append("\n");
sb.append(" xmlns:x=\"urn:schemas-microsoft-com:office:excel\"");
sb.append("\n");
sb.append(" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"");
sb.append("\n");
sb.append(" xmlns:html=\"http://www.w3.org/TR/REC-html40\">");
sb.append("\n");
sb.append("<Styles>\n");
/*設定列頭樣式*/
sb.append("<Style ss:ID=\"header\" ss:Name=\"header\">\n");//ss:ID=“header”對應下面的Row ss:StyleID=“header”
sb.append("<Interior ss:Color=\"#c4d79b\" ss:Pattern=\"Solid\"/>\n");// 設定背景顏色
sb.append("<Font ss:FontName=\"微軟雅黑\" x:CharSet=\"134\" ss:Bold=\"Bolder\" ss:Size=\"12\"/>\n");//設定字型
sb.append("</Style>\n");
/*其它預設樣式設定*/
sb.append("<Style ss:ID=\"Default\" ss:Name=\"Normal\">\n");
//sb.append("<Alignment ss:Vertical=\"Center\"/>\n");
sb.append("<Alignment ss:Horizontal=\"Center\" ss:Vertical=\"Center\" ss:WrapText=\"1\"/>\n");// 左中右設定,一個是水平,一個是垂直
sb.append("<Borders>\n");
sb.append("<Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Color=\"#666\" ss:Weight=\"1\"/>\n");//左邊框設定
sb.append("<Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Color=\"#666\" ss:Weight=\"1\"/>\n");//右邊框設定
sb.append("<Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Color=\"#666\" ss:Weight=\"1\"/>\n");//下邊框設定
sb.append("<Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Color=\"#666\" ss:Weight=\"1\"/>\n");//上邊框設定
sb.append("</Borders>\n");
sb.append("<Font ss:FontName=\"宋體\" x:CharSet=\"134\" ss:Size=\"12\"/>\n");
sb.append("<Interior/>\n");
sb.append("<NumberFormat/>\n");
sb.append("<Protection/>\n");
sb.append("</Style>\n");
sb.append("</Styles>\n");
try {
// 生成表格
int headersLength = headers.length;
sb.append("<Worksheet ss:Name=\"" + sheetName + "\">");
sb.append("\n");
sb.append("<Table ss:ExpandedColumnCount=\"" + headersLength
+ "\" ss:ExpandedRowCount=\"1000000\" x:FullColumns=\"1\" x:FullRows=\"1\">");
sb.append("\n");
if(!StrUtils.isEmptyArray(widths)){
if(widths.length > 1){
for (int i = 0; i < headersLength; i++) {
sb.append("<Column ss:AutoFitWidth=\"0\" ss:Width=\""+widths[i]+"\"/>");
}
}else{
for (int i = 0; i < headersLength; i++) {
sb.append("<Column ss:AutoFitWidth=\"0\" ss:Width=\""+widths[0]+"\"/>");
}
}
}
// 輸出第一行的標題
if(!StrUtils.isBlank(firstRowTitle)){
//ss:StyleID可以加row或者Cell,加在Row,整行(包括空的Cell)都有,加上Cell,只有Cell才有。
sb.append("<Row ss:Height=\"30\">");
sb.append("<Cell ss:StyleID=\"header\" ss:MergeAcross=\""+ (headersLength - 1)+"\"><Data ss:Type=\"String\">" + firstRowTitle + "</Data></Cell>");
sb.append("</Row>");
}
// 輸出列頭
sb.append("<Row>");
for (int i = 0; i < headersLength; i++) {
sb.append("<Cell ss:StyleID=\"header\"><Data ss:Type=\"String\">" + headers[i] + "</Data></Cell>");
}
sb.append("</Row>");
// 構建表體資料
for (int j = 0; j < list.size(); j++) {
sb.append("<Row>");
T t = (T) list.get(j);
for (int i = 0; i < includeFieldNames.length; i++) {
// 獲取屬性名稱
String fieldName = includeFieldNames[i];
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
// 獲取class物件
Class tCls = t.getClass();
// 獲取屬性值
Object value = null;
try {
// 獲取class方法
Method getMethod = tCls.getMethod(getMethodName, new Class[] {});
// 獲取屬性值
value = getMethod.invoke(t, new Object[] {});
} catch (NoSuchMethodException e) {
// 繼續迴圈
continue;
}
// 判斷值的型別後進行強制型別轉換
String textValue = "";
if (value instanceof Integer) {
// int value = ((Integer) value).intValue();
textValue = value.toString();
} else if (value instanceof String) {
// String s = (String) value;
textValue = value.toString();
} else if (value instanceof Double) {
// double d = ((Double) value).doubleValue();
textValue = String.format("%.2f", value);
} else if (value instanceof Float) {
// float f = ((Float) value).floatValue();
textValue = value.toString();
} else if (value instanceof Long) {
// long l = ((Long) value).longValue();
textValue = value.toString();
} else if (value instanceof Boolean) {
// boolean b = ((Boolean) value).booleanValue();
textValue = value.toString();
} else if (value instanceof Date) {
Date date = (Date) value;
SimpleDateFormat sdf = new SimpleDateFormat(datetimePattern);
textValue = sdf.format(date);
} else if ((value instanceof BigDecimal)) {
textValue = value.toString();
} else {
if (value != null) {
continue;
}
}
sb.append("<Cell><Data ss:Type=\"String\">");
// 如果不是圖片資料,就利用正規表示式判斷textValue是否全部由數字組成
if (StringUtils.isNotBlank(textValue)) {
Pattern p = Pattern.compile("^//d+(//.//d+)?$");
Matcher matcher = p.matcher(textValue);
if (matcher.matches()) {
// 是數字當作double處理
sb.append(Double.parseDouble(textValue));
} else {
sb.append(textValue);
}
}
sb.append("</Data></Cell>");
}
sb.append("</Row>");
sb.append("\n");
}
sb.append("</Table>");
sb.append("<WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">");
sb.append("\n");
sb.append("<ProtectObjects>False</ProtectObjects>");
sb.append("\n");
sb.append("<ProtectScenarios>False</ProtectScenarios>");
sb.append("\n");
sb.append("</WorksheetOptions>");
sb.append("\n");
sb.append("</Worksheet>");
sb.append("</Workbook>");
sb.append("\n");
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
try {
outputStream.write(sb.toString().getBytes());
outputStream.flush();
outputStream.close();
sb = null;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用方式:
注意:不能直接通過Ajax請求,需要通過表單提交。
xml方式轉Excel用到的屬性:
補充一個:
ss:MergeAcross 表示跨列合併,如下:
注意是否需要減1,因為表示是跨多少列,那就是合併其它的幾列,不包括自己,所以需要減 1
萬能方法:
如果突然需要增加某些未知的屬性,可以自己先建立一個Excel檔案,做一個模板出來,然後另存為Xml檔案,注意是Xml檔案,儲存後開啟Xml檔案檢視自己建立的模板的某些屬性應該怎麼設定。但開啟的xml檔案比較亂,所以通過搜尋找到自己對應的那個格子。
原始碼下載見:http://fanshuyao.iteye.com/blog/2393131
=============================
©Copyright 蕃薯耀 2017年9月13日
http://www.cnblogs.com/fanshuyao/