poi 動態生成多表頭execl


如果所示,我要導出的數據界面是下面這樣的,前面樣品編號、樣品名稱、爐次為主表數據,而檢驗結果是子表數據,這里子表的數據作為了主表的數據的一個字段(集合屬性),下面代碼會給大家看vo結構

 

 下圖為要導出的execl效果

 

 開發思路:

1、該表頭表體是根據主表樣品名稱不同而子表元素個數就會不同,所以第一步就是將前端傳來的數據按樣品名稱分組

 

 2、由於導出的數據順序會亂,所以還是需要map排序下,這里我們可以按key排序

 

 3、由於我要導出的數據是主子表結構,所以要將表體數據利用反射映射到表頭去,以方便導出使用,這里有個細節就是最終組成的map其實現類要用LinkedHashMap這樣才能保證順序不亂

主表結構如下:

 

子表結構如下:

 

 

 組裝數據如下:

 4、組裝導出信息

 

 

 

 5、組好數據去調用寫的導出工具類解析表頭表體寫進相應行設置樣式,然后寫出流就可以了

下面貼出主要代碼,兩個實體類這里就不貼了

pom文件先導入依賴

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.14</version>
</dependency>

 

@RequestMapping(value="/excelExport",method=RequestMethod.POST)
public @ResponseBody Result exportData(@RequestParam String exportdata, HttpServletRequest request, HttpServletResponse response){
Result result=new Result();
try {
List<TestResultVO> list = JSONArray.parseArray(exportdata, TestResultVO.class);
Map<String, List<TestResultVO>> groupmap = list.stream().collect(Collectors.groupingBy(TestResultVO :: getSamplename));//按樣品名稱分組(元素相同的一組制作表頭)
Map<String, List<TestResultVO>> sortmap = this.sortByKey(groupmap, false);//升序排序
Map<String, List<TestResultVO>> exportMap = new LinkedHashMap<String, List<TestResultVO>>();
for (Map.Entry<String, List<TestResultVO>> entry : sortmap.entrySet()) {
//制作表頭
StringBuffer sb = new StringBuffer("{'sampleno':'樣品編號','samplename':'樣品名稱'");
List<TestResultVO> testvos = entry.getValue();
for (TestResultVO vo : testvos) {
List<ResultVO> resultVOs = vo.getResults();
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()).append("'}");
}else {
sb.append(",'element").append(i+1).append("':'").append(resultVOs.get(i).getItemname()).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("}");
}
}

Boolean falg = true;//這段邏輯處理不同元素名稱,相同元素個數的情況
for (Map.Entry<String, List<TestResultVO>> enMap : exportMap.entrySet()) {
if (enMap.getKey().contains(sb.toString())) {
falg = false;
enMap.getValue().addAll(entry.getValue());
}
}
if (falg) {
exportMap.put(sb.toString(), entry.getValue());
}


}
// 獲取瀏覽器信息,對文件名進行重新編碼
String fileName = "化驗結果查詢.xlsx";
String agent = request.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");
}
// 設置返回的信息頭
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.setContentType("application/vnd.ms-excel");

// Excel寫入
OutputStream os = response.getOutputStream();

ExcelExportImportUtils.ListtoExecl(exportMap, os);

// 關閉資源
os.flush();
os.close();
} catch (Exception e) {
result = ExceptionResult.process(e);
}
log.info("end method exportData,return"+result);
return result;
}

 

/**
* @Title: sortByKey 
* @author zhangdke
* @Description: map 按key排序
* @param map 要排序的map
* @param isDesc 是否降序,true降序,false升序
* @return Map<K,V> 
* @throws
*/
public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map, boolean isDesc) {
Map<K, V> result = Maps.newLinkedHashMap();
if (isDesc) {
map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey().reversed())
.forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
} else {
map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey())
.forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
}
return result;
}

 

package com.yonyou.scm.qc.core.pub;

import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONObject;

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;

/**
* Excel導出數據工具類

* @author zhangdke
* @date 2019年12月4日
*
*/
public class ExcelExportImportUtils {



/**
* @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) 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();
for (Map.Entry<String, List<T>> entry : map.entrySet()) {
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 = o == null ? "" : o.toString();
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 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;
}


}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM