package com.duowan.leopard.officeutil.excel;
/**
* @author lizeyang
* @date 2015年5月29日
*/
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import jxl.CellView;
import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.VerticalAlignment;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;
import com.duowan.leopard.officeutil.excel.annotation.ExcelSheet;
import com.duowan.leopard.officeutil.excel.annotation.SheetCol;
import com.duowan.leopard.officeutil.excel.bean.ExportExcelBean;
public class ExportExcelUtil {
public static final int RESULT_SUCC = 0;
public static final int RESULT_FAIL = -1;
public String timePrintFormat = "yyyy-MM-dd HH:mm:ss";
public int fontSize = 10;
// 两种字体样式,一种正常样式,一种是粗体样式
WritableFont NormalFont = new WritableFont(WritableFont.ARIAL, fontSize);
WritableFont BoldFont = new WritableFont(WritableFont.ARIAL, fontSize, WritableFont.BOLD);
// 标题(列头)样式
WritableCellFormat titleFormat = new WritableCellFormat(BoldFont);
// 正文样式1:居中
WritableCellFormat contentCenterFormat = new WritableCellFormat(NormalFont);
// 正文样式:右对齐
WritableCellFormat contentRightFormat = new WritableCellFormat(NormalFont);
// 正文样式:右对齐
WritableCellFormat contentLeftFormat = new WritableCellFormat(NormalFont);
WritableWorkbook workbook;
public ExportExcelUtil() throws WriteException {
titleFormat.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条
titleFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
titleFormat.setAlignment(Alignment.CENTRE); // 文字对齐
titleFormat.setWrap(false); // 文字是否换行
contentCenterFormat.setBorder(Border.ALL, BorderLineStyle.THIN);
contentCenterFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
contentCenterFormat.setAlignment(Alignment.CENTRE);
contentCenterFormat.setWrap(false);
contentRightFormat.setBorder(Border.ALL, BorderLineStyle.THIN);
contentRightFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
contentRightFormat.setAlignment(Alignment.RIGHT);
contentRightFormat.setWrap(false);
}
public String getTimePrintFormat() {
return timePrintFormat;
}
public void setTimePrintFormat(String timePrintFormat) {
this.timePrintFormat = timePrintFormat;
}
public int getFontSize() {
return fontSize;
}
public void setFontSize(int fontSize) {
NormalFont = new WritableFont(WritableFont.ARIAL, fontSize);
BoldFont = new WritableFont(WritableFont.ARIAL, fontSize, WritableFont.BOLD);
this.fontSize = fontSize;
}
public WritableCellFormat getTitleFormat() {
return titleFormat;
}
public void setTitleFormat(WritableCellFormat titleFormat) {
this.titleFormat = titleFormat;
}
public WritableCellFormat getContentCenterFormat() {
return contentCenterFormat;
}
public void setContentCenterFormat(WritableCellFormat contentCenterFormat) {
this.contentCenterFormat = contentCenterFormat;
}
public WritableCellFormat getContentRightFormat() {
return contentRightFormat;
}
public void setContentRightFormat(WritableCellFormat contentRightFormat) {
this.contentRightFormat = contentRightFormat;
}
public WritableCellFormat getContentLeftFormat() {
return contentLeftFormat;
}
public void setContentLeftFormat(WritableCellFormat contentLeftFormat) {
this.contentLeftFormat = contentLeftFormat;
}
/**
* 将数据转成成excel。 特性: 1、将时间类型的值转成yyyy-MM-dd HH:mm:ss 2、将数字类型的值转成带千分符的形式,并右对齐
* 3、除数字类型外,其他类型的值居中显示
*
* @param sheetContentList封装表格内容
* ,其中参数keyMap、contentList含义,如下所示
* @param keyMap
* 定义标题及每一列对应的JavaBean属性。标题的先后顺序,对应keyMap的插入顺序;
* map中的key值为JavaBean属性,value为标题
* @param contentList
* 表格内容,List中的每一个元素,对应到excel的每一行
* @param os
* 结果输出流
* @return
*/
public final int export(List<ExportExcelBean> sheetContentList, OutputStream os) {
int rs = RESULT_SUCC;
try {
workbook = Workbook.createWorkbook(os);
for (int i = 0; i < sheetContentList.size(); i++) {
addSheet(sheetContentList.get(i).getKeyMap(), sheetContentList.get(i).getContentList(),
sheetContentList.get(i).getSheetName(), i);
}
workbook.write();
workbook.close();
} catch (Exception e) {
rs = RESULT_FAIL;
e.printStackTrace();
}
return rs;
}
public final int export(LinkedHashMap<String, String> keyMap, List<Object> contentList, OutputStream os) {
List<ExportExcelBean> list = new ArrayList<ExportExcelBean>();
ExportExcelBean bean = new ExportExcelBean();
bean.setContentList(contentList);
bean.setKeyMap(keyMap);
bean.setSheetName("sheet1");
list.add(bean);
return export(list, os);
}
private boolean isBlank(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
return true;
}
/**
* 将数据转成成excel。 特性: 1、将时间类型的值转成yyyy-MM-dd HH:mm:ss 2、将数字类型的值转成带千分符的形式,并右对齐
* 3、除数字类型外,其他类型的值居中显示
*
* @param os
* ,结果输出流
* @param sheets
* ,数据列表,不定参长,一个参表示一个excel 表,多个参则是多个表,最后这些表会放到一个同个excel文件一起输出
* @return
*/
public final <T> int exportByAnnotation(OutputStream os, List<T>... sheets) {
List<ExportExcelBean> sheetBeanList = new ArrayList<ExportExcelBean>();
if (null != sheets && sheets.length > 0) {
for (int i = 0; i < sheets.length; i++) {
List<T> sheet = sheets[i];
if (null != sheet && sheet.size() != 0) {
ExportExcelBean sheetBean = getSheetBeanByAnnotation(i, sheet);
sheetBeanList.add(sheetBean);
}
}
}
return export(sheetBeanList, os);
}
private <T> ExportExcelBean getSheetBeanByAnnotation(int i, List<T> sheet) {
T row = sheet.get(0);
Class<?> claaz = row.getClass();
String order = "";
ExportExcelBean sheetBean = new ExportExcelBean();
sheetBean.setContentList((List<Object>) sheet);
// 设置表名
if (claaz.isAnnotationPresent(ExcelSheet.class)) {
sheetBean.setSheetName(claaz.getAnnotation(ExcelSheet.class).name());
order = claaz.getAnnotation(ExcelSheet.class).order();
} else {
sheetBean.setSheetName("sheet" + (i + 1));
}
// 设置要展示的列
LinkedHashMap<String, String> keyMap = new LinkedHashMap<String, String>();
Field[] fields = claaz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.isAnnotationPresent(SheetCol.class)) {
// Object fieldValue = field.get(row);
keyMap.put(field.toString().substring(field.toString().lastIndexOf(".") + 1),
field.getAnnotation(SheetCol.class).value());
}
}
// 如果有定义顺序,要按顺序来展示
if (!isBlank(order)) {
List<String> orderList = Arrays.asList(order.split(","));
LinkedHashMap<String, String> newKeyMap = new LinkedHashMap<String, String>();
// 找到定义的顺序
for (String o : orderList) {
for (Entry<String, String> entry : keyMap.entrySet()) {
if (entry.getKey().equals(o)) {
newKeyMap.put(entry.getKey(), entry.getValue());
continue;
}
}
}
// 如果仍存在部分字段未定义顺序,则按原先的顺序
for (Entry<String, String> keyMapEntry : keyMap.entrySet()) {
for (Entry<String, String> newKeyMapEntry : newKeyMap.entrySet()) {
if (newKeyMapEntry.getKey().equals(keyMapEntry.getKey())) {
continue;
}
}
newKeyMap.put(keyMapEntry.getKey(), keyMapEntry.getValue());
}
sheetBean.setKeyMap(newKeyMap);
} else {
sheetBean.setKeyMap(keyMap);
}
return sheetBean;
}
private void addSheet(LinkedHashMap<String, String> keyMap, List<Object> listContent, String sheetName, int sheetNum)
throws WriteException, RowsExceededException, NoSuchFieldException, IllegalAccessException {
// 创建名为sheetName的工作表
WritableSheet sheet = workbook.createSheet(sheetName, sheetNum);
// 设置标题,标题内容为keyMap中的value值,标题居中粗体显示
Iterator titleIter = keyMap.entrySet().iterator();
int titleIndex = 0;
while (titleIter.hasNext()) {
Map.Entry<String, String> entry = (Map.Entry<String, String>) titleIter.next();
sheet.addCell(new Label(titleIndex++, 0, entry.getValue(), titleFormat));
}
// 设置正文内容
for (int row = 0; row < listContent.size(); row++) {
Iterator contentIter = keyMap.entrySet().iterator();
int col = 0;
while (contentIter.hasNext()) {
Map.Entry<String, String> entry = (Map.Entry<String, String>) contentIter.next();
Object key = entry.getKey();
Field field = listContent.get(row).getClass().getDeclaredField(key.toString());
field.setAccessible(true);
Object content = field.get(listContent.get(row));
Label label = getContentLabel(col, row + 1, field, content);
col++;
sheet.addCell(label);
}
}
setAutoSize(sheet, keyMap.size(), listContent.size());
}
/**
* 每个单元格的内容及格式
*
* @param col
* @param row
* @param field
* @param content
* @return
*/
protected Label getContentLabel(int col, int row, Field field, Object content) {
WritableCellFormat cellFormat = contentCenterFormat;
String contentStr = "";
contentStr = null != content ? content.toString() : "";
// 将数字转变成千分位格式
String numberStr = getNumbericValue(contentStr);
// numberStr不为空,说明是数字类型。
if (null != numberStr && !numberStr.trim().equals("")) {
contentStr = numberStr;
// 数字要右对齐
cellFormat = contentRightFormat;
} else {
// 如果是时间类型。要格式化成标准时间格式
String timeStr = getTimeFormatValue(field, content);
// timeStr不为空,说明是时间类型
if (null != timeStr && !timeStr.trim().equals("")) {
contentStr = timeStr;
}
}
Label label = new Label(col, row, contentStr, cellFormat);
return label;
};
/**
* 宽度自适应
*
* @param sheet
* @param colNum
* @param rowNum
* @return
*/
private boolean setAutoSize(WritableSheet sheet, int colNum, int rowNum) {
for (int i = 0; i < colNum; i++) {
int maxLength = 0;
CellView cell = sheet.getColumnView(i);
for (int j = 0; j < rowNum; j++) {
maxLength = Math.max(sheet.getCell(i, j).getContents().getBytes().length, maxLength);
}
cell.setSize(25 * fontSize * maxLength);
sheet.setColumnView(i, cell);
}
return true;
}
/**
* 获取格式化后的时间串
*
* @param field
* @param content
* @return
*/
protected String getTimeFormatValue(Field field, Object content) {
String timeFormatVal = "";
if (field.getType().getName().equals(java.sql.Timestamp.class.getName())) {
Timestamp time = (Timestamp) content;
timeFormatVal = longTimeTypeToStr(time.getTime(), timePrintFormat);
} else if (field.getType().getName().equals(java.util.Date.class.getName())) {
Date time = (Date) content;
timeFormatVal = longTimeTypeToStr(time.getTime(), timePrintFormat);
}
return timeFormatVal;
}
/**
* 获取千分位数字
*
* @param str
* @return
*/
protected String getNumbericValue(String str) {
String numbericVal = "";
try {
Double doubleVal = Double.valueOf(str);
numbericVal = DecimalFormat.getNumberInstance().format(doubleVal);
} catch (NumberFormatException e) {
// if exception, not format
}
return numbericVal;
}
/**
* 格式化时间
*
* @param time
* @param formatType
* @return
*/
protected String longTimeTypeToStr(long time, String formatType) {
String strTime = "";
if (time >= 0) {
SimpleDateFormat sDateFormat = new SimpleDateFormat(formatType);
strTime = sDateFormat.format(new Date(time));
}
return strTime;
}
}