最近公司項目需要把數據通過Excel形式展示給用戶,由於第一次接觸java 生成Excel,在網上找了很多資料,但是很多都不是很理想,自己設計了一個通過自定義註解把列名配置到實體類上,然後通過代碼讀取自定義註解作爲列名,具體實現可以看一下代碼(代碼是實習時候寫的,有點low,大家湊合着看吧,該功能已經上生產了,代碼應該問題沒什麼問題了,就是不夠優雅)
實體類
package com.ifp.business.common.utils;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
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.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import com.ifp.common.common.utils.ColumnName;
@SuppressWarnings("all")
public class CreateExcelTool {
private static HSSFWorkbook workbook = null;
private List listAll = new ArrayList();
private List<Map> listMap = null;
private Map mapTitle = new HashMap();
private static String type[] = {"long","int","double","float","short","byte","boolean","char"};
/**
* 判斷文件是否存在.
* @param fileDir 文件路徑
* @return
*/
public static boolean fileExist(String fileDir){
boolean flag = false;
File file = new File(fileDir);
flag = file.exists();
return flag;
}
/**
* 判斷文件的sheet是否存在.
* @param fileDir 文件路徑
* @param sheetName 表格索引名
* @return
*/
public static boolean sheetExist(String fileDir,String sheetName) throws Exception{
boolean flag = false;
File file = new File(fileDir);
if(file.exists()){ //文件存在
//創建workbook
try {
workbook = new HSSFWorkbook(new FileInputStream(file));
//添加Worksheet(不添加sheet時生成的xls文件打開時會報錯)
HSSFSheet sheet = workbook.getSheet(sheetName);
if(sheet!=null)
flag = true;
} catch (Exception e) {
throw e;
}
}else{ //文件不存在
flag = false;
}
return flag;
}
/**
* 創建新excel.
* @param fileDir excel的路徑
* @param sheetName 要創建的表格索引
* @param list excel的第一行即列名
*/
public static void CreateExcelTitle(String fileDir,String sheetName,List list,String name) throws Exception{
//CreateExcelUtil.deleteExcel(fileDir);
System.out.println("Excel路徑:----------------------------------------"+fileDir);
String path = fileDir.substring(0,fileDir.lastIndexOf("\\")+1);
if (getCurrentOS().equals("linux")) {
path = fileDir.substring(0,fileDir.lastIndexOf("/")+1);
}
File file=new File(path);
if(!file.exists()){
file.mkdirs();
}
HSSFSheet sheet1;
Map<String, String> sheetStyle = new HashMap<String, String>();
//判斷文件是否存在
if(CreateExcelUtil.fileExist(fileDir)){
workbook = new HSSFWorkbook(new FileInputStream(fileDir));
//判斷sheet頁是否存在
if(CreateExcelUtil.sheetExist(fileDir, sheetName)){
sheet1 = workbook.getSheet(sheetName);
}else{
//添加Worksheet(不添加sheet時生成的xls文件打開時會報錯)
sheet1 = workbook.createSheet(sheetName);
}
}else{
workbook = new HSSFWorkbook();
//添加Worksheet(不添加sheet時生成的xls文件打開時會報錯)
sheet1 = workbook.createSheet(sheetName);
}
sheet1.autoSizeColumn(1);
sheet1.autoSizeColumn(1, true);
/**合併單元格
* 參數:起始行號,終止行號, 起始列號,終止列號
* 只有 該文件中不存在sheet頁纔會合併單元格
* */
sheet1.addMergedRegion(new CellRangeAddress(0, 0, 0, list.size() - 1));
sheet1.addMergedRegion(new CellRangeAddress(1, 1, 0, list.size() - 1));
SimpleDateFormat format = new SimpleDateFormat("yyyy年M月");
//新建文件
FileOutputStream out = null;
try {
HSSFFont fontName = workbook.createFont();
HSSFCellStyle cellStyleName = workbook.createCellStyle();
fontName.setFontHeightInPoints((short) 14); //字體高度
fontName.setFontName("宋體"); //字體
fontName.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); //加粗
cellStyleName.setAlignment(HSSFCellStyle.ALIGN_CENTER);
cellStyleName.setFont(fontName);
HSSFRow row1 = workbook.getSheet(sheetName).createRow(0);
row1.setHeight((short)450);
HSSFCell cell1 = row1.createCell(0);
cell1.setCellValue(name);
cell1.setCellStyle(cellStyleName);
//設置單元格爲文本格式
cell1.setCellType(HSSFCell.CELL_TYPE_STRING);
HSSFRow row2 = workbook.getSheet(sheetName).createRow(1);
HSSFCell cell2 = row2.createCell(0);
cell2.setCellValue("製表日期:"+format.format(new Date()));
//添加列名
HSSFRow row = workbook.getSheet(sheetName).createRow(2); //創建第一行
HSSFFont font = workbook.createFont();
HSSFCellStyle cellStyle = workbook.createCellStyle();
font.setFontHeightInPoints((short) 12); //字體高度
cellStyle.setFont(font);
for(short i = 0;i < list.size();i++){
HSSFCell cell = row.createCell(i);
//設置列寬
sheet1.setColumnWidth(i,list.get(i).toString().getBytes().length*256);
cell.setCellValue("" + list.get(i));
cell.setCellStyle(cellStyle);
}
out = new FileOutputStream(fileDir);
workbook.write(out);
} catch (Exception e) {
throw e;
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 刪除文件.
* @param fileDir 文件路徑
*/
public static boolean deleteExcel(String fileDir) {
boolean flag = false;
File file = new File(fileDir);
// 判斷目錄或文件是否存在
if (!file.exists()) { // 不存在返回 false
return flag;
} else {
// 判斷是否爲文件
if (file.isFile()) { // 爲文件時調用刪除文件方法
file.delete();
flag = true;
}
}
return flag;
}
/**
* 往excel中寫入
* @param fileDir 文件路徑
* @param sheetName 表格索引
* @param object
* @throws Exception
*/
public void writeToExcel(String fileDir,String sheetName,List<Map> mapList) throws Exception{
//創建workbook
File file = new File(fileDir);
try {
workbook = new HSSFWorkbook(new FileInputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//流
FileOutputStream out = null;
HSSFSheet sheet = workbook.getSheet(sheetName);
HSSFFont font = workbook.createFont();
HSSFCellStyle cellStyle = workbook.createCellStyle();
font.setFontHeightInPoints((short) 12); //字體高度
cellStyle.setFont(font);
/*sheet.setDefaultColumnWidth(14);//設置默認列寬
sheet.setDefaultRowHeight((short) (6 * 256)); //設置默認行高,表示2個字符的高度*/
// 獲取表格的總行數
// int rowCount = sheet.getLastRowNum() + 1; // 需要加一
// 獲取表頭的列數
int columnCount = sheet.getRow(2).getLastCellNum();
try {
// 獲得表頭行對象
HSSFRow titleRow = sheet.getRow(2);
if(titleRow!=null){
int rowId = 3;
int i = 0;
int rowsIndex = 0;
int row = 3;
boolean flag = false;
while(i<mapList.size()){
Map map = mapList.get(i);
HSSFRow newRow1=sheet.createRow(row);
for (short columnIndex = 0; columnIndex < columnCount; columnIndex++) { //遍歷表頭
String titleName = titleRow.getCell(columnIndex).toString().trim().toString().trim();
String mapKey = (String) mapTitle.get(titleName);
List list = new ArrayList();
if(map.get(mapKey)!=null&&map.get(mapKey).getClass().equals(list.getClass())){
flag = true;
list = (List) map.get(mapKey);
int j = 0;
HSSFRow newRow;
for(int listIndex = 0;listIndex<list.size();listIndex++){
if(sheet.getRow(rowId + j)!=null){
newRow = sheet.getRow(rowId+j);
}else{
newRow=sheet.createRow(rowId+j);
}
newRow.setHeightInPoints(50);
HSSFCell cell = newRow.createCell(columnIndex);
//設置列寬
sheet.setColumnWidth(i,list.get(listIndex).toString().getBytes().length*256);
cell.setCellValue(list.get(listIndex)==null ? null : list.get(listIndex).toString());
setStyle(cell,font);
j++;
rowsIndex = j;
}
}else{
try{
HSSFCell cell = newRow1.createCell(columnIndex);
//判斷字符串長度是否大於列寬,大於列寬,從新設置列寬
if(!"".equals(map.get(mapKey))&&map.get(mapKey)!=null){
//判斷是否是中文
if(isContainChinese(map.get(mapKey).toString())&&sheet.getColumnWidth(columnIndex)<map.get(mapKey).toString().getBytes().length*256){
sheet.setColumnWidth(columnIndex,map.get(mapKey).toString().getBytes().length*256);
}else if(!isContainChinese(map.get(mapKey).toString())&&sheet.getColumnWidth(columnIndex)<map.get(mapKey).toString().getBytes().length*512){
sheet.setColumnWidth(columnIndex,map.get(mapKey).toString().getBytes().length*512);
}
}
cell.setCellValue(map.get(mapKey)==null ? null : map.get(mapKey).toString());
/*setStyle(cell,font);*/
cell.setCellStyle(cellStyle);
}catch(Exception e){
System.out.println("------------------------------------空---------------------------");
e.printStackTrace();
}
}
}
if(flag){
row = row+rowsIndex;
}else{
row = row+rowsIndex + 1;
}
rowId = row;
i++;
}
}
out = new FileOutputStream(fileDir);
workbook.write(out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 將一個 JavaBean 對象轉化爲一個 Map
* @param bean 要轉化的JavaBean 對象
* @return 轉化出來的 Map 對象
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IntrospectionException 如果分析類屬性失敗
* @throws IllegalAccessException 如果實例化 JavaBean 失敗
* @throws InvocationTargetException 如果調用屬性的 setter 方法失敗
*/
public static Map toMap(Object bean) throws ClassNotFoundException, InstantiationException {
Map<Object, Object> returnMap = new HashMap<Object, Object>();
Class clazz = null;
if(!bean.toString().contains("@")){
try {
clazz = Class.forName(bean + "");
bean = clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}else{
clazz = bean.getClass();
}
StringBuffer sb = new StringBuffer();
BeanInfo beanInfo = null;
try {
//得到的BeanInfo對象封裝了把這個類當做JavaBean看的結果信息,即屬性的信息
beanInfo = Introspector.getBeanInfo(clazz);
//獲取 clazz 類型中的 propertyName 的屬性描述器
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (int i = 0; i < propertyDescriptors.length; i++) {
PropertyDescriptor descriptor = propertyDescriptors[i];
if("class".equals(descriptor.getName())){
continue;
}
String propertyType = descriptor.getPropertyType().toString();
boolean boo = com.ifp.common.common.utils.StringUtil.isInList(propertyType, com.ifp.common.common.utils.StringUtil.arrayToList(type));
if(propertyType.contains("java.util.List")){
try {
Method readMethod = descriptor.getReadMethod();
List result = null;
//調用 set 方法將傳入的value值保存屬性中去
result = (List) readMethod.invoke(bean, new Object[0]);
for(Object o:result){
toMap(o);
}
} catch (SecurityException e) {
e.printStackTrace();
}
continue;
}else if(propertyType.contains("lang") || boo){
String propertyName = descriptor.getName();
if (!propertyName.equals("class")) {
Method readMethod = descriptor.getReadMethod();
Object result = null;
//調用 set 方法將傳入的value值保存屬性中去
result = readMethod.invoke(bean, new Object[0]);
if (null != result) {
if(returnMap!=null&&returnMap.containsKey(propertyName)){
List list1 = new ArrayList();
List list2 = new ArrayList();
list1.add(result);
if(!returnMap.get(propertyName).getClass().equals(list2.getClass())){
list2.add(returnMap.get(propertyName));
}else{
list2 = (List) returnMap.get(propertyName);
}
list1.addAll(list2);
result = list1;
}else{
result = result.toString();
}
}
returnMap.put(propertyName, result);
}
}else{
Object obj = propertyType.substring(propertyType.indexOf(" ") + 1);
Method readMethod = descriptor.getReadMethod();
Object result = null;
//調用 set 方法將傳入的value值保存屬性中去
result = readMethod.invoke(bean, new Object[0]);
toMap(result);
continue;
}
}
} catch (IntrospectionException e) {
System.out.println("分析類屬性失敗");
} catch (IllegalAccessException e) {
System.out.println("實例化 JavaBean 失敗");
} catch (IllegalArgumentException e) {
System.out.println("映射錯誤");
} catch (InvocationTargetException e) {
System.out.println("調用屬性的 setter 方法失敗");
}
return returnMap;
}
/**
* 獲取父類和當前類所有屬性(包括private)
* @param object
* @return
*/
public static List getAllFields(Object object){
Class clazz = object.getClass();
List fieldList = new ArrayList();
while (clazz != null){
for (Field field : clazz.getDeclaredFields()) {
if (field.getGenericType().toString().contains("java.util.List")){
Object obj = (Object)field.toString().substring(field.toString().lastIndexOf(".")+1);
Class clazzList = obj.getClass();
field.setAccessible(true);
String fieldName = field.getName();
fieldList.add(fieldName);
}
}
clazz = clazz.getSuperclass();
}
return fieldList;
}
/**
* 獲得傳入對象的所有屬性名
* @param object
* @return
*/
public List getFields(Object object){
Class cla = null;
if(!object.toString().contains("@")){
try {
cla = Class.forName(object + "");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}else{
cla = object.getClass();
}
for(Field field : cla.getDeclaredFields()){
boolean boo = com.ifp.common.common.utils.StringUtil.isInList(field.getGenericType().toString(), com.ifp.common.common.utils.StringUtil.arrayToList(type));
//判斷該字段的聲明類型
if(field.getGenericType().toString().contains("java.util.List")){
Object obj = (Object)(field.getGenericType().toString().substring(field.getGenericType().toString().indexOf("<")+1,field.getGenericType().toString().indexOf(">")));
getFields(obj);
continue;
}else if(field.getGenericType().toString().contains("lang") || boo){
field.setAccessible(true);
//獲取自定義註解
ColumnName anno = field.getAnnotation(ColumnName.class);
String fieldName = field.getName();
String annoValue = null;
if(anno == null){
/*annoValue = fieldName;
mapTitle.put(fieldName, fieldName);*/
//如果該字段沒有註解,直接跳過,表格中不會顯示此字段
continue;
}else{
annoValue = anno.value();
mapTitle.put(anno.value(),fieldName);
}
listAll.add(annoValue);
}else{
Object obj = field.getGenericType().toString().substring(field.getGenericType().toString().indexOf(" ") + 1);
getFields(obj);
continue;
}
}
return listAll;
}
/**
* 判斷字符串是否包含中文
* @param str
* @return
*/
public static boolean isContainChinese(String str) {
Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
Matcher m = p.matcher(str);
if (m.find()) {
return true;
}
return false;
}
//設置字體樣式
public static void setStyle(HSSFCell cell,HSSFFont font){
// 設置字體
font.setFontHeightInPoints((short) 12); //字體高度
//font.setColor(HSSFFont.COLOR_RED); //字體顏色
//font.setFontName("楷體"); //字體
//font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); //寬度
//font.setItalic(true); //是否使用斜體
//font.setStrikeout(true); //是否使用劃線
// 設置單元格類型
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setFont(font);
// cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); //水平佈局:居中
//cellStyle.setWrapText(true);
cell.setCellStyle(cellStyle);
}
public static String getCurrentOS() {
String system = "";
int OS = System.getProperty("os.name").toUpperCase().indexOf("WINDOWS");
if (OS != -1) {
system = "windows";
} else
system = "linux";
return system;
}
/**
*
* @param fileDir
* @param sheetName sheet頁名字
* @param mapList
* @throws Exception
*/
public void createExcel(String fileDir,String sheetName,List<Object> list, String name ) throws Exception{
listMap = new ArrayList();
List titleList = new ArrayList();
CreateExcelTool CreateExcelTool = new CreateExcelTool();
for(Object obj : list){
listMap.add(toMap(obj));
}
//System.out.println(listMap);
titleList = CreateExcelTool.getFields(list.get(0));
System.out.println("表頭:"+titleList);
CreateExcelTool.CreateExcelTitle(fileDir, sheetName, titleList,name);
CreateExcelTool.writeToExcel(fileDir, sheetName,listMap);
System.out.println("---------------------------------------生成表格成功-------------------------------------");
}
public static void main(String[] args) throws Exception {
List<Object> list=new ArrayList<Object>();
List<Object> list2=new ArrayList<Object>();
Map<String,String> map=new HashMap<String,String>();
/* for(int i = 0;i<3;i++){
Person p = new Person();
p.setName("2018-01-16 00:00:00.0"+i);
p.setAge("2018-01-16 00:00:00.0");
p.setSex("2018-01-16 00:00:00.0"+i);
list.add(p);
}
for(int i = 0;i<3;i++){
person2 p = new person2();
p.setName("list2少時誦詩書所所所所所所所所所所所所所所"+i);
list2.add(p);
}*/
CreateExcelTool CreateExcelTool = new CreateExcelTool();
String path ="E:/excel/123456778.xls";
CreateExcelTool.createExcel(path, "sheet1", list, "測試1");
CreateExcelTool.createExcel(path, "sheet2", list2, "測試2");
}
}
自定義註解
package com.ifp.common.common.utils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
/**
* 自定義註解,程序可以讀取註解values(該程序主要用於生成表格時,通過讀取類屬性中配置的註解,生產表格列名)
* @author cdy
* @Retention(RetentionPolicy.RUNTIME) 表示該註解在jvm運行時存在
*@Target(ElementType.FIELD) 只可以修飾屬性
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ColumnName {
String value(); }