問題描述:項目中導出execl數據量非常大,導致了頁面長時間得不到響應而崩潰掉了,所以導出execl失敗!
處理方案:前端采用定時刷新+進度條方式,后端導出采用緩存線程實現導出,導出改用每次請求后端直接返回進度條數值,開啟一個線程讓它去執行查詢與導出操作。當導出執行完成將進度條寫成100返回給前端,前端判斷100后關閉進度條加載后端一個下載接口,將數據寫出到瀏覽器
代碼參考:
后端代碼參考:
/**
* 獲取進度查詢
*
* @param uuid
* @return
*/
@RequestMapping(value = "/progress", method = RequestMethod.POST)
public @ResponseBody Result progress(@RequestParam String uuid) {
Result result = new Result();
result.setData(cacheManager.get(uuid));
result.setSuccess(true);
return result;
}
/**
* 獲取進度查詢
*
* @param uuid
* @return
*/
@RequestMapping(value = "/progress", method = RequestMethod.POST)
public @ResponseBody Result progress(@RequestParam String uuid) {
Result result = new Result();
result.setData(cacheManager.get(uuid));
result.setSuccess(true);
return result;
}
/**
* 導出
*
* @param request
* @param response
* @return
*/
@SuppressWarnings({ "static-access", "unchecked" })
@RequestMapping(value = "/excelExport", method = RequestMethod.POST)
public @ResponseBody Result exportData(@RequestParam String exportdata,
HttpServletRequest request, HttpServletResponse response) {
Result result = new Result();
String uuid = UUID.randomUUID().toString();
result.setData(uuid);
cacheManager.setex(uuid, 0, 600);
executor.submit(new Runnable() {
@Override
public void run() {
try {
Map<String, List<TestResultVO>> exportMap = new LinkedHashMap<String, List<TestResultVO>>();
PageVO pageVO = JSONObject.parseObject(exportdata,
PageVO.class);
if (pageVO.getSearchParams() == null) {
ExceptionUtils.wrapBusinessException("當前參數數據有誤");
}
List<TestResultVO> testvos = resultMapper
.getTestResultList(pageVO.getSearchParams());
cacheManager.setex(uuid, 7, 600);
for (TestResultVO vo : testvos) {
List<ResultVO> resultVOs = vo.getResults();
StringBuffer sb = new StringBuffer(
"{'sampleno':'樣品編號','samplename':'樣品名稱','sampledatestr':'取樣日期','uploadtime':'上傳時間','batch':'批次','furnaceno':'爐號','furnacetimes':'爐次'");
if (vo.getSampledate() != null) {
vo.setSampledatestr(new SimpleDateFormat(
"yyyy-MM-dd").format(vo.getSampledate()));// 將取樣日期轉化為yyyy-MM-dd格式導出
}
if (resultVOs != null && resultVOs.size() > 0) {
Field fields[] = vo.getClass().getDeclaredFields();
for (int i = 0; i < resultVOs.size(); i++) {
if (i == resultVOs.size() - 1) {
sb.append(",'element")
.append(i + 1)
.append("':'")
.append(resultVOs.get(i)
.getItemname()
+ "("
+ resultVOs.get(i)
.getMeasdocname()
+ ")").append("'}");
} else {
sb.append(",'element")
.append(i + 1)
.append("':'")
.append(resultVOs.get(i)
.getItemname()
+ "("
+ resultVOs.get(i)
.getMeasdocname()
+ ")").append("'");
}
// 將子表元素值反射到主表自定義字段,以便導出使用
for (Field field : fields) {
String lastzf = null;
if (i > 8) {// 將子表元素根據下標+1與主表截取最后兩位相同的賦值
lastzf = field.getName().substring(
field.getName().length() - 2);
} else {// 將子表元素根據下標+1與主表截取最后一位相同的賦值
lastzf = field.getName().substring(
field.getName().length() - 1);
}
if (NumberUtils.isDigits(lastzf)) {// 判斷該類型是否為整數字符串
if (Integer.valueOf(lastzf) == i + 1) {
field.setAccessible(true);
field.set(vo, resultVOs.get(i)
.getConfirmvalue());
field.setAccessible(false);
}
}
}
}
} else {
sb.append("}");
}
List<TestResultVO> list = new ArrayList<TestResultVO>();
list.add(vo);
Boolean falg = true;// 這段邏輯處理不同元素名稱,相同元素個數的情況
for (Map.Entry<String, List<TestResultVO>> enMap : exportMap
.entrySet()) {
if (enMap.getKey().contains(sb.toString())) {
falg = false;
enMap.getValue().addAll(list);
}
}
if (falg) {
exportMap.put(sb.toString(), list);
}
}
// }
// 獲取瀏覽器信息,對文件名進行重新編碼
String fileName = "化驗結果查詢"+uuid+".xlsx";
File directory = new File("");// 參數為空
String courseFile = directory.getCanonicalPath();
isDirExist(courseFile + "/export");
String path = courseFile
+ "/export/" + fileName;
OutputStream os = new FileOutputStream(path);
ExcelExportImportUtils.ListtoExecl(exportMap, os,uuid);
//因為分布式原因將流轉成二進制存入緩存,進度條100時直接取緩存值
FileInputStream input = new FileInputStream(path);
byte[] b = InputStreamToByte(input);
cacheManager.setex(qcTestResultURL+uuid,b, 600);
cacheManager.setex(uuid, 100, 600);
File file = new File(path);
input.close();
//刪除服務器文件
file.delete();
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
log.info("end method exportData,return" + result);
return result;
}
這里說下為什么寫出的時候redis沒存文件地址而是存了二進制流,因為項目是分布式部署,所以寫地址進度條100的時候有可能找到的服務器與你寫入的機器不是同一個,所以這里我直接緩存了二進制流,在下面直接取流給瀏覽器
/**
* 進度條100的時候將文件流寫出到瀏覽器
* @Title: download
* @author zhangdengke
* @Description: TODO
* @param @param req
* @param @param res
* @param @return
* @return Result
* @throws
*/
@RequestMapping(value = "/download", method = RequestMethod.GET)
public @ResponseBody Result download(HttpServletRequest req, HttpServletResponse res) {
Result result = new Result();
String uuid = req.getQueryString().substring(0);
String fileName = "化驗結果查詢"+".xlsx";
OutputStream out = null;
try {
String agent = req.getHeader("User-Agent"); // 獲取瀏覽器
if (agent.contains("Firefox")) {
Base64Encoder base64Encoder = new Base64Encoder();
fileName = "=?utf-8?B?"
+ base64Encoder.encode(fileName.getBytes("utf-8"))
+ "?=";
} else if (agent.contains("MSIE")) {
fileName = URLEncoder.encode(fileName, "utf-8");
} else if (agent.contains("Safari")) {
fileName = new String(fileName.getBytes("utf-8"),
"ISO8859-1");
} else {
fileName = URLEncoder.encode(fileName, "utf-8");
}
//設置返回的信息頭
res.setHeader("Content-Disposition",
"attachment;filename="
+ fileName);
res.setContentType("application/vnd.ms-excel");
byte[] b = cacheManager.get(qcTestResultURL+uuid);
out = res.getOutputStream();
out.write(b);
} catch (Exception e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
}finally{
try {
out.flush();
out.close();
} catch (IOException e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
}
}
return result;
}
/**
* @param 當前文件夾路徑
* */
public void isDirExist(String fileDir) {
File file = new File(fileDir);
if (!file.exists()) {
file.mkdir();
}
}
public static byte[] InputStreamToByte(InputStream iStrm) throws IOException {
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
int ch;
while ((ch = iStrm.read()) != -1)
{
bytestream.write(ch);
}
byte imgdata[]=bytestream.toByteArray();
bytestream.close();
return imgdata;
}
導出公共類:
package com.yonyou.scm.qc.core.utils;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DateFormat;
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 net.sf.json.JSONObject;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ContextLoader;
import com.yonyou.iuap.cache.CacheManager;
/**
* Excel導出導出數據工具類
*
* @author zhangdke
* @date 2019年12月4日
*
*/
public class ExcelExportImportUtils {
static int sheetsize = 2000;
static int sheetsize1 = 50000;
@Autowired
private CacheManager cacheManager;
/**
* @Description: 導入到EXCEL(單行表頭)
* @param data
* 導入到excel中的數據
* @param out
* 數據寫入的文件
* @param fields
* 需要注意的是這個方法中的map中:每一列對應的實體類的英文名為鍵,excel表格中每一列名為值
*/
public static <T> void ListtoExecl(List<T> data, OutputStream out,
Map<String, String> fields) throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook();
// 如果導入數據為空,則拋出異常。
if (data == null || data.size() == 0) {
workbook.close();
throw new Exception("導入的數據為空");
}
// 根據data計算有多少頁sheet
int pages = data.size() / sheetsize;
if (data.size() % sheetsize > 0) {
pages += 1;
}
// 提取表格的字段名(英文字段名是為了對照中文字段名的)
String[] egtitles = new String[fields.size()];
String[] cntitles = new String[fields.size()];
Iterator<String> it = fields.keySet().iterator();
int count = 0;
while (it.hasNext()) {
String egtitle = (String) it.next();
String cntitle = fields.get(egtitle);
egtitles[count] = egtitle;
cntitles[count] = cntitle;
count++;
}
// 添加數據
for (int i = 0; i < pages; i++) {
int rownum = 0;
// 計算每頁的起始數據和結束數據
int startIndex = i * sheetsize;
int endIndex = (i + 1) * sheetsize - 1 > data.size() ? data.size()
: (i + 1) * sheetsize - 1;
// 創建每頁,並創建第一行
XSSFSheet sheet = workbook.createSheet();
XSSFRow row = sheet.createRow(rownum);
// 在每頁sheet的第一行中,添加字段名
for (int f = 0; f < cntitles.length; f++) {
XSSFCell cell = row.createCell(f);
cell.setCellValue(cntitles[f]);
}
rownum++;
// 將數據添加進表格
for (int j = startIndex; j < endIndex; j++) {
row = sheet.createRow(rownum);
T item = data.get(j);
for (int h = 0; h < cntitles.length; h++) {
Field fd = item.getClass().getDeclaredField(egtitles[h]);
fd.setAccessible(true);
Object o = fd.get(item);
String value = o == null ? "" : o.toString();
XSSFCell cell = row.createCell(h);
cell.setCellValue(value);
}
rownum++;
}
}
// 將創建好的數據寫入輸出流
workbook.write(out);
// 關閉workbook
workbook.close();
}
/**
*
* @Title: 出入參數為map時的導出方式
* @author zhangdke
* @Description: TODO
* @param @param data
* @param @param out
* @param @param fields
* @param @throws Exception
* @return void
* @throws
*/
public static <T> void ListMaptoExecl(List<Map<String, Object>> data, OutputStream out,
Map<String, Object> fields) throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook();
// 如果導入數據為空,則拋出異常。
if (data == null || data.size() == 0) {
workbook.close();
throw new Exception("導入的數據為空");
}
// 根據data計算有多少頁sheet
int pages = data.size() / sheetsize;
if (data.size() % sheetsize > 0) {
pages += 1;
}
// 提取表格的字段名(英文字段名是為了對照中文字段名的)
String[] egtitles = new String[fields.size()];
String[] cntitles = new String[fields.size()];
Iterator<String> it = fields.keySet().iterator();
int count = 0;
while (it.hasNext()) {
String egtitle = (String) it.next();
String cntitle = (String) fields.get(egtitle);
egtitles[count] = egtitle;
cntitles[count] = cntitle;
count++;
}
// 添加數據
for (int i = 0; i < pages; i++) {
int rownum = 0;
// 計算每頁的起始數據和結束數據
int startIndex = i * sheetsize;
int endIndex = (i + 1) * sheetsize - 1 > data.size() ? data.size()
: (i + 1) * sheetsize - 1;
// 創建每頁,並創建第一行
XSSFSheet sheet = workbook.createSheet();
XSSFRow row = sheet.createRow(rownum);
// 在每頁sheet的第一行中,添加字段名
for (int f = 0; f < cntitles.length; f++) {
XSSFCell cell = row.createCell(f);
cell.setCellValue(cntitles[f]);
}
rownum++;
// 將數據添加進表格
for (int j = startIndex; j < endIndex; j++) {
row = sheet.createRow(rownum);
Map<String, Object> map = data.get(j);
for (int h = 0; h < cntitles.length; h++) {
Object o = map.get(egtitles[h]);
String value = o == null ? "" : o.toString();
XSSFCell cell = row.createCell(h);
cell.setCellValue(value);
}
rownum++;
}
// 必須在單元格設值以后進行
// 設置為根據內容自動調整列寬
for (int k = 0; k < cntitles.length; k++) {
sheet.autoSizeColumn(k);
}
// 處理中文不能自動調整列寬的問題
setSizeColumn(sheet, cntitles.length);
}
// 將創建好的數據寫入輸出流
workbook.write(out);
// 關閉workbook
workbook.close();
}
/**
* @Description: 導入到EXCEL(表頭合並,數據單列)
* @param data
* 導入到excel中的數據
* @param out
* 數據寫入的文件
* @param fields
* 需要注意的是這個方法中的map中:每一列對應的實體類的英文名為鍵,excel表格中每一列名為值
* @param workbook
* 創建好表頭的XSSFWorkbook對象
*/
public static <T> void ListtoComplexExecl(List<T> data, OutputStream out,
Map<String, String> fields, XSSFWorkbook workbook) throws Exception {
// 提取表格的字段名(英文字段名是為了對照中文字段名的)
String[] egtitles = new String[fields.size()];
String[] cntitles = new String[fields.size()];
Iterator<String> it = fields.keySet().iterator();
int count = 0;
while (it.hasNext()) {
String egtitle = (String) it.next();
String cntitle = fields.get(egtitle);
egtitles[count] = egtitle;
cntitles[count] = cntitle;
count++;
}
// 添加數據
int rownum = workbook.getNumberOfSheets() + 1;
// 單頁
XSSFSheet sheet = workbook.getSheetAt(0);
XSSFRow row = sheet.createRow(rownum);
// 將數據添加進表格
for (int i = 0; i < data.size(); i++) {
row = sheet.createRow(rownum);
T item = data.get(i);
for (int h = 0; h < cntitles.length; h++) {
Field fd = item.getClass().getDeclaredField(egtitles[h]);
fd.setAccessible(true);
Object o = fd.get(item);
String value = o == null ? "" : o.toString();
XSSFCell cell = row.createCell(h);
cell.setCellValue(value);
}
rownum++;
}
// 將創建好的數據寫入輸出流
workbook.write(out);
// 關閉workbook
workbook.close();
}
/**
* @Description: 導入到excel中的數據
* @param in
* excel文件
* @param entityClass
* excel中每一行數據的實體類
* @param fields
* 字段名字
* @return List<T>
*/
public static <T> List<T> ExecltoList(InputStream in, Class<T> entityClass,
Map<String, String> fields) throws Exception {
List<T> resultList = new ArrayList<T>();
XSSFWorkbook workbook = new XSSFWorkbook(in);
// excel中字段的中英文名字數組
String[] egtitles = new String[fields.size()];
String[] cntitles = new String[fields.size()];
Iterator<String> it = fields.keySet().iterator();
int count = 0;
while (it.hasNext()) {
String cntitle = (String) it.next();
String egtitle = fields.get(cntitle);
egtitles[count] = egtitle;
cntitles[count] = cntitle;
count++;
}
// 得到excel中sheet總數
int sheetcount = workbook.getNumberOfSheets();
if (sheetcount == 0) {
workbook.close();
throw new Exception("Excel文件中沒有任何數據");
}
// 數據的導出
for (int i = 0; i < sheetcount; i++) {
XSSFSheet sheet = workbook.getSheetAt(i);
if (sheet == null) {
continue;
}
// 每頁中的第一行為標題行,對標題行的特殊處理
XSSFRow firstRow = sheet.getRow(0);
int celllength = firstRow.getLastCellNum();
String[] excelFieldNames = new String[celllength];
LinkedHashMap<String, Integer> colMap = new LinkedHashMap<String, Integer>();
// 獲取Excel中的列名
for (int f = 0; f < celllength; f++) {
XSSFCell cell = firstRow.getCell(f);
excelFieldNames[f] = cell.getStringCellValue().trim();
// 將列名和列號放入Map中,這樣通過列名就可以拿到列號
for (int g = 0; g < excelFieldNames.length; g++) {
colMap.put(excelFieldNames[g], g);
}
}
// 由於數組是根據長度創建的,所以值是空值,這里對列名map做了去空鍵的處理
colMap.remove(null);
// 判斷需要的字段在Excel中是否都存在
// 需要注意的是這個方法中的map中:中文名為鍵,英文名為值
boolean isExist = true;
List<String> excelFieldList = Arrays.asList(excelFieldNames);
for (String cnName : fields.keySet()) {
if (!excelFieldList.contains(cnName)) {
isExist = false;
break;
}
}
// 如果有列名不存在,則拋出異常,提示錯誤
if (!isExist) {
workbook.close();
throw new Exception("Excel中缺少必要的字段,或字段名稱有誤");
}
// 將sheet轉換為list
for (int j = 1; j <= sheet.getLastRowNum(); j++) {
XSSFRow row = sheet.getRow(j);
// 根據泛型創建實體類
T entity = entityClass.newInstance();
// 給對象中的字段賦值
for (Entry<String, String> entry : fields.entrySet()) {
// 獲取中文字段名
String cnNormalName = entry.getKey();
// 獲取英文字段名
String enNormalName = entry.getValue();
// 根據中文字段名獲取列號
int col = colMap.get(cnNormalName);
// 獲取當前單元格中的內容
String content = row.getCell(col).toString().trim();
// 給對象賦值
setFieldValueByName(enNormalName, content, entity);
}
resultList.add(entity);
}
}
workbook.close();
return resultList;
}
/**
* @MethodName : setFieldValueByName
* @Description : 根據字段名給對象的字段賦值
* @param fieldName
* 字段名
* @param fieldValue
* 字段值
* @param o
* 對象
*/
private static void setFieldValueByName(String fieldName,
Object fieldValue, Object o) throws Exception {
Field field = getFieldByName(fieldName, o.getClass());
if (field != null) {
field.setAccessible(true);
// 獲取字段類型
Class<?> fieldType = field.getType();
// 根據字段類型給字段賦值
if (String.class == fieldType) {
field.set(o, String.valueOf(fieldValue));
} else if ((Integer.TYPE == fieldType)
|| (Integer.class == fieldType)) {
field.set(o, Integer.parseInt(fieldValue.toString()));
} else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
field.set(o, Long.valueOf(fieldValue.toString()));
} else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
field.set(o, Float.valueOf(fieldValue.toString()));
} else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {
field.set(o, Short.valueOf(fieldValue.toString()));
} else if ((Double.TYPE == fieldType)
|| (Double.class == fieldType)) {
field.set(o, Double.valueOf(fieldValue.toString()));
} else if (Character.TYPE == fieldType) {
if ((fieldValue != null)
&& (fieldValue.toString().length() > 0)) {
field.set(o,
Character.valueOf(fieldValue.toString().charAt(0)));
}
} else if (Date.class == fieldType) {
field.set(o, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.parse(fieldValue.toString()));
} else if (BigDecimal.class == fieldType) {
field.set(o, new BigDecimal(fieldValue.toString()));
} else {
field.set(o, fieldValue);
}
} else {
throw new Exception(o.getClass().getSimpleName() + "類不存在字段名 "
+ fieldName);
}
}
/**
* @MethodName : getFieldByName
* @Description : 根據字段名獲取字段
* @param fieldName
* 字段名
* @param clazz
* 包含該字段的類
* @return 字段
*/
private static Field getFieldByName(String fieldName, Class<?> clazz) {
// 拿到本類的所有字段
Field[] selfFields = clazz.getDeclaredFields();
// 如果本類中存在該字段,則返回
for (Field field : selfFields) {
if (field.getName().equals(fieldName)) {
return field;
}
}
// 否則,查看父類中是否存在此字段,如果有則返回
Class<?> superClazz = clazz.getSuperclass();
if (superClazz != null && superClazz != Object.class) {
return getFieldByName(fieldName, superClazz);
}
// 如果本類和父類都沒有,則返回空
return null;
}
/**
* @Title: 生成動態多表頭execl
* @author zhangdke
* @Description: TODO
* @param map
* @param out
* @return void
* @throws
*/
public static <T> void ListtoExecl(Map<String, List<T>> map,
OutputStream out,String rediskey) throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook();
// 如果導入數據為空,則拋出異常。
if (map.isEmpty()) {
workbook.close();
throw new Exception("導入的數據為空");
}
XSSFCellStyle headStyle = getHeadStyle(workbook);//表頭樣式
XSSFCellStyle bodyStyle = getBodyStyle(workbook);//表體樣式
int size = 0;//行
XSSFSheet sheet = workbook.createSheet();
ApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
CacheManager cacheManager = context.getBean(CacheManager.class);
int provalue = 93/map.size();//服務器寫出execl時間大約為93%,計算每次執行百分比,每次執行更新緩存
for (Map.Entry<String, List<T>> entry : map.entrySet()) {
int redisvalue = cacheManager.get(rediskey);
redisvalue = redisvalue+provalue;//
cacheManager.setex(rediskey,redisvalue, 600);
List<T> list = entry.getValue();
Map<String, String> fields = (Map<String, String>) JSONObject
.fromObject(entry.getKey());
// 提取表格的字段名(英文字段名是為了對照中文字段名的)
String[] egtitles = new String[fields.size()];
String[] cntitles = new String[fields.size()];
Iterator<String> it = fields.keySet().iterator();
int count = 0;
while (it.hasNext()) {
String egtitle = (String) it.next();
String cntitle = fields.get(egtitle);
egtitles[count] = egtitle;
cntitles[count] = cntitle;
count++;
}
XSSFRow row = sheet.createRow(size);
// 添加表頭信息
for (int f = 0; f < cntitles.length; f++) {
XSSFCell cell = row.createCell(f);
cell.setCellValue(cntitles[f]);
cell.setCellStyle(headStyle);
}
for (T t : list) {
size++;
row = sheet.createRow(size);
for (int h = 0; h < cntitles.length; h++) {
Field fd = t.getClass().getDeclaredField(egtitles[h]);
fd.setAccessible(true);
Object o = fd.get(t);
String value = typeConversion(o);
XSSFCell cell = row.createCell(h);
cell.setCellValue(value);
cell.setCellStyle(bodyStyle);
}
}
size++;
// 必須在單元格設值以后進行
// 設置為根據內容自動調整列寬
for (int k = 0; k < cntitles.length; k++) {
sheet.autoSizeColumn(k);
}
// 處理中文不能自動調整列寬的問題
setSizeColumn(sheet, cntitles.length);
}
// 將創建好的數據寫入輸出流
workbook.write(out);
// 關閉workbook
workbook.close();
}
/**
* @Title: 自適應列寬度中文支持
* @author zhangdke
* @Description: TODO
* @param sheet
* @param size
* @return void
* @throws
*/
private static void setSizeColumn(XSSFSheet sheet, int size) {
for (int columnNum = 0; columnNum < size; columnNum++) {
int columnWidth = sheet.getColumnWidth(columnNum) / 256;
for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
XSSFRow currentRow;
// 當前行未被使用過
if (sheet.getRow(rowNum) == null) {
currentRow = sheet.createRow(rowNum);
} else {
currentRow = sheet.getRow(rowNum);
}
if (currentRow.getCell(columnNum) != null) {
XSSFCell currentCell = currentRow.getCell(columnNum);
if (currentCell.getCellType() == XSSFCell.CELL_TYPE_STRING) {
int length = currentCell.getStringCellValue()
.getBytes().length;
if (columnWidth < length) {
columnWidth = length;
}
}
}
}
sheet.setColumnWidth(columnNum, columnWidth * 256);
}
}
/**
* @Title: 字符串轉換規則
* @author zhangdke
* @Description: TODO
* @param columnVal
* @return String
* @throws
*/
private static String typeConversion(Object columnVal) throws Exception {
String value = null;
if (null == columnVal) {
value = "";
} else {
if (columnVal.getClass().equals(Timestamp.class)) {
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Timestamp timestamp = (Timestamp) columnVal;
value = sdf.format(timestamp);
} else {
value = columnVal.toString();
}
}
return value;
}
/**
* @Title: 表頭樣式
* @author zhangdke
* @Description: TODO
* @param workbook
* @return XSSFCellStyle
* @throws
*/
private static XSSFCellStyle getHeadStyle(XSSFWorkbook workbook){
// 字體樣式
XSSFFont xssfFont = workbook.createFont();
// 加粗
xssfFont.setBold(true);
// 字體名稱
xssfFont.setFontName("楷體");
// 字體大小
xssfFont.setFontHeight(12);
// 表頭樣式
XSSFCellStyle headStyle = workbook.createCellStyle();
// 設置字體css
headStyle.setFont(xssfFont);
// 豎向居中
headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 橫向居中
headStyle.setAlignment(HorizontalAlignment.CENTER);
// 邊框
headStyle.setBorderBottom(BorderStyle.THIN);
headStyle.setBorderLeft(BorderStyle.THIN);
headStyle.setBorderRight(BorderStyle.THIN);
headStyle.setBorderTop(BorderStyle.THIN);
return headStyle;
}
/**
* @Title: 表體樣式
* @author zhangdke
* @Description: TODO
* @param workbook
* @return XSSFCellStyle
* @throws
*/
private static XSSFCellStyle getBodyStyle(XSSFWorkbook workbook){
// 內容字體樣式
XSSFFont contFont = workbook.createFont();
// 加粗
contFont.setBold(false);
// 字體名稱
contFont.setFontName("楷體");
// 字體大小
contFont.setFontHeight(11);
// 內容樣式
XSSFCellStyle bodyStyle = workbook.createCellStyle();
// 設置字體css
bodyStyle.setFont(contFont);
// 豎向居中
bodyStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 橫向居中
bodyStyle.setAlignment(HorizontalAlignment.CENTER);
// 邊框
bodyStyle.setBorderBottom(BorderStyle.THIN);
bodyStyle.setBorderLeft(BorderStyle.THIN);
bodyStyle.setBorderRight(BorderStyle.THIN);
bodyStyle.setBorderTop(BorderStyle.THIN);
return bodyStyle;
}
}