添加 maven 依賴
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.0</version>
</dependency>
編寫工具類
- 可以實現
- 1.導出Excel 到本地 / 瀏覽器
- 2.導出包含多個 Sheet 的 Excel 到本地 / 瀏覽器
package com.geotmt.billingcenter.common.utils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Descriptinon: Excel 導出類
* @Author: yanghanwei
* @Mail: [email protected]
* @CreateDate: 2018/12/3 17:15
* @Version: v1
*/
public class ExportExcelUtils {
private static final String ATTR_ARR_STR = "attrArr";
private static final String DATA_LIST_STR = "dataList";
private static final String TITLE_ARR_STR = "titleArr";
private static final String SHEET_NAME = "Sheet";
private static final String SHEET_NAME_STR = "sheetName";
/**
* 默認單元格寬度
*/
private static final Integer DEFAULT_CELL_WIDTH = 3000;
private static FileOutputStream fout = null;
private static OutputStream out = null;
private static OutputStream setResponseHeaderFileName(HttpServletResponse response, String filename) throws IOException {
response.setContentType("application/octet-stream;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(filename+".xls","UTF-8"));
OutputStream out = new BufferedOutputStream(response.getOutputStream());
return out;
}
private static final Logger logger = LoggerFactory.getLogger(ExportExcelUtils.class);
/**
* 導出 exccel到本地 工具類(多個sheet導出)
* @param mapList
* @param filePath 本地路徑
* sheetName: sheet名字
* titleArr: 表頭中文名數組
* attrArr: 數據對應的實體類屬性數組(與表頭一一對應)
* dataList: 到處的數據list
*/
public static void buildExcelTemplate( List<Map<String, Object>> mapList,String filePath, Integer cellWidth) {
HSSFWorkbook wb = new HSSFWorkbook();
FileOutputStream fout = null;
try{
// 將文件存到指定位置
fout = new FileOutputStream(filePath);
if (!mapList.isEmpty()) {
for (int a = 0; a < mapList.size(); a++) {
String sheetName = "Sheet1";
if(!StringUtils.isEmpty(mapList.get(a).get(SHEET_NAME_STR))){
sheetName = String.valueOf(mapList.get(a).get(SHEET_NAME_STR));
}
String[] titleArr = (String[]) mapList.get(a).get("titleArr");
String[] attrArr = (String[]) mapList.get(a).get("attrArr");
Object dataList = mapList.get(a).get("dataList");
// 第二步,在webbook中添加一個sheet,對應Excel文件中的sheet
HSSFSheet sheetMonitor = wb.createSheet(sheetName);
// 第三步,在sheet中添加表頭第0行,注意老版本poi對Excel的行數列數有限制short
HSSFRow rowMonitor = sheetMonitor.createRow(0);
// 第四步,創建單元格,並設置值表頭 設置表頭居中
HSSFCellStyle style = ExportExcelUtils.getColumnTopStyle(wb);
HSSFCell cellMonitor = rowMonitor.createCell(0);
for (int i = 0; i < titleArr.length; i++) {
cellMonitor.setCellValue(titleArr[i]);
cellMonitor.setCellStyle(style);
cellMonitor = rowMonitor.createCell((i + 1));
}
String jsonString = JSONObject.toJSONString(dataList);
JSONArray jsonArray = JSONObject.parseArray(jsonString);
if (jsonArray != null && !jsonArray.isEmpty()) {
for (int i = 0; i < jsonArray.size(); i++) {
sheetMonitor.setColumnWidth(i, null == cellWidth ? DEFAULT_CELL_WIDTH : cellWidth);
Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(jsonArray.get(i)), Map.class);
if(null != map){
for (int j = 0; j < titleArr.length; j++) {
rowMonitor = sheetMonitor.createRow(i + 1);
// 第五步,寫入實體數據 實際應用中這些數據從數據庫得到,
for (int k = 0; k < attrArr.length; k++) {
if (map.containsKey(attrArr[k]) && !StringUtils.isEmpty(map.get(attrArr[k]))) {
// 第四步,創建單元格,並設置值
if(!StringUtils.isEmpty(map.get(attrArr[k]))){
String value = String.valueOf(map.get(attrArr[k]));
rowMonitor.createCell(k).setCellValue(value);
}else{
rowMonitor.createCell(k).setCellValue("");
}
}
}
}
}
}
}
}
}
wb.write(fout);
}catch (Exception e){
logger.error("導出Excel失敗,Exception:" + e);
logger.info("導出Excel失敗,Exception:{0}", e);
}finally {
try {
if(null != fout){
fout.close();
}
}catch (Exception e){
logger.error("關閉流異常:[{}]",e);
}
}
}
/**
* 導出 exccel 到瀏覽器工具類(1個sheet導出)
* @param dataListForMap
* sheetName: sheet名字
* titleArr: 表頭中文名數組
* attrArr: 數據對應的實體類屬性數組(與表頭一一對應)
* dataListForMap: 導出的數據list
*/
public static void buildExcelTemplate(Map<String, Object> dataListForMap, HttpServletResponse response, String fileName, Integer cellWidth) {
HSSFWorkbook wb = new HSSFWorkbook();
// 第二步,在webbook中添加一個sheet,對應Excel文件中的sheet
Object sheetName = dataListForMap.get("sheetName");
HSSFSheet sheetMonitor = wb.createSheet(!StringUtils.isEmpty(sheetName) ? sheetName + "" : SHEET_NAME);
// 第三步,在sheet中添加表頭第0行,注意老版本poi對Excel的行數列數有限制short
HSSFRow rowMonitor = sheetMonitor.createRow(0);
try{
out = setResponseHeaderFileName(response,fileName);
//創建excel標題,設置列寬
createTitle(wb, rowMonitor, dataListForMap, sheetMonitor, cellWidth);
//寫入數據
writeData(sheetMonitor,1,dataListForMap);
wb.write(out);
}catch (Exception e){
logger.info("導出Excel失敗,Exception:{}",e);
}finally {
try {
out.close();
}catch (Exception e){
logger.error("關閉流異常:[{}]",e);
}
}
}
/**
* 導出多個 sheet 到瀏覽器
* @param mapList
* * sheetName: sheet名字
* * titleArr: 表頭中文名數組
* * attrArr: 數據對應的實體類屬性數組(與表頭一一對應)
* * dataList: 到處的數據list
* @param response
* @param fileName 文件名稱
*/
public static void buildExcelTemplate(List<Map<String, Object>> mapList, HttpServletResponse response, String fileName, Integer cellWidth) {
HSSFWorkbook wb = new HSSFWorkbook();
if(null != mapList && !mapList.isEmpty()){
try{
for (int i=0; i<mapList.size(); i++) {
Map<String, Object> dataListForMap = mapList.get(i);
// 第二步,在webbook中添加一個sheet,對應Excel文件中的sheet
Object sheetName = dataListForMap.get(SHEET_NAME_STR);
String sheetNameRt = !StringUtils.isEmpty(sheetName) ? sheetName + "" : SHEET_NAME + (i+1);
HSSFSheet sheetMonitor = wb.createSheet(sheetNameRt);
// 第三步,在sheet中添加表頭第0行,注意老版本poi對Excel的行數列數有限制short
HSSFRow rowMonitor = sheetMonitor.createRow(0);
out = setResponseHeaderFileName(response,fileName);
//創建excel標題
createTitle(wb, rowMonitor, dataListForMap, sheetMonitor, cellWidth);
//寫入數據
writeData(sheetMonitor,1,dataListForMap);
}
wb.write(out);
}catch (IOException e){
e.printStackTrace();
logger.info("導出Excel失敗,Exception:{}",e);
}catch (Exception e) {
logger.info("導出Excel失敗,Exception:{}",e);
}finally {
try {
out.close();
}catch (Exception e){
logger.error("關閉流異常:[{}]",e);
}
}
}
}
/**
* 創建excel標題
* @param dataListForMap
*/
private static void createTitle(HSSFWorkbook wb, HSSFRow rowMonitor, Map<String, Object> dataListForMap, HSSFSheet sheetMonitor, Integer cellWidth){
String[] titleArr = (String[]) dataListForMap.get(TITLE_ARR_STR);
//居中樣式
HSSFCellStyle centerStyle = ExportExcelUtils.getColumnTopStyle(wb);
for (int i = 0; i < titleArr.length; i++) {
// 設置表格寬度(自適應)
sheetMonitor.setColumnWidth(i, null == cellWidth ? DEFAULT_CELL_WIDTH : cellWidth);
HSSFCell cellMonitor = rowMonitor.createCell(i);
cellMonitor.setCellStyle(centerStyle);
cellMonitor.setCellValue(titleArr[i]);
}
}
/**
* 寫入數據
* @param sheetMonitor
* @param startRow
* @param dataListForMap
*/
public static void writeData(HSSFSheet sheetMonitor, Integer startRow, Map<String, Object> dataListForMap){
String[] titleArr = (String[]) dataListForMap.get(TITLE_ARR_STR);
String[] attrArr = (String[]) dataListForMap.get(ATTR_ARR_STR);
Object dataList = dataListForMap.get(DATA_LIST_STR);
String jsonString = JSONObject.toJSONString(dataList);
JSONArray jsonArray = JSONObject.parseArray(jsonString);
if (jsonArray != null && !jsonArray.isEmpty()) {
for (int i = 0; i < jsonArray.size(); i++) {
Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(jsonArray.get(i)), Map.class);
for (int j = 0; j < titleArr.length; j++) {
HSSFRow rowMonitor = sheetMonitor.createRow( i + startRow);
// 第五步,寫入實體數據 實際應用中這些數據從數據庫得到,
for (int k = 0; k < attrArr.length; k++) {
if (map != null && attrArr[k] != null && map.containsKey(attrArr[k]) && !StringUtils.isEmpty(map.get(attrArr[k]))) {
// 第四步,創建單元格,並設置值
if(!StringUtils.isEmpty(map.get(attrArr[k]))){
String value = String.valueOf(map.get(attrArr[k]));
rowMonitor.createCell(k).setCellValue(value);
}else{
rowMonitor.createCell(k).setCellValue("");
}
}
}
}
}
}
}
/**
* 列頭單元格樣式
* @param workbook
* @return
*/
private static HSSFCellStyle getColumnTopStyle(HSSFWorkbook workbook) {
// 設置字體
HSSFFont font = workbook.createFont();
//設置字體大小
font.setFontHeightInPoints((short)12);
//字體加粗
font.setBold(true);
//設置字體名字
font.setFontName("Courier New");
//設置樣式;
HSSFCellStyle style = workbook.createCellStyle();
//設置底邊框;
style.setBorderBottom(BorderStyle.THIN);
//設置底邊框顏色;
style.setBottomBorderColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex());
//設置左邊框;
style.setBorderLeft(BorderStyle.THIN);
//設置左邊框顏色;
style.setLeftBorderColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex());
//設置右邊框;
style.setBorderRight(BorderStyle.THIN);
//設置右邊框顏色;
style.setRightBorderColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex());
//設置頂邊框;
style.setBorderTop(BorderStyle.THIN);
//設置頂邊框顏色;
style.setTopBorderColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex());
style.setFillBackgroundColor(HSSFColor.HSSFColorPredefined.DARK_RED.getIndex());
style.setFillForegroundColor(HSSFColor.HSSFColorPredefined.DARK_RED.getIndex());
//在樣式用應用設置的字體;
style.setFont(font);
//設置自動換行;
style.setWrapText(false);
//設置水平對齊的樣式爲居中對齊;
style.setAlignment(HorizontalAlignment.CENTER);
//設置垂直對齊的樣式爲居中對齊;
style.setVerticalAlignment(VerticalAlignment.CENTER);
return style;
}
/**
* 列數據信息單元格樣式
* @param workbook
* @return
*/
private HSSFCellStyle getStyle(HSSFWorkbook workbook) {
// 設置字體
HSSFFont font = workbook.createFont();
//設置字體大小
font.setFontHeightInPoints((short)12);
font.setFontName("Courier New");
//設置樣式;
HSSFCellStyle style = workbook.createCellStyle();
//設置底邊框;
style.setBorderBottom(BorderStyle.THIN);
//設置底邊框顏色;
style.setBottomBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
//設置左邊框;
style.setBorderLeft(BorderStyle.THIN);
//設置左邊框顏色;
style.setLeftBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
//設置右邊框;
style.setBorderRight(BorderStyle.THIN);
//設置右邊框顏色;
style.setRightBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
//設置頂邊框;
style.setBorderTop(BorderStyle.THIN);
//設置頂邊框顏色;
style.setTopBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
//在樣式用應用設置的字體;
style.setFillBackgroundColor(HSSFColor.HSSFColorPredefined.BRIGHT_GREEN.getIndex());
style.setFont(font);
//設置自動換行;
style.setWrapText(false);
//設置水平對齊的樣式爲居中對齊;
style.setAlignment(HorizontalAlignment.CENTER);
//設置垂直對齊的樣式爲居中對齊;
style.setVerticalAlignment(VerticalAlignment.CENTER);
return style;
}
/**
* 判斷是否是整數
* @param str
* @return
*/
private static Pattern pattern = Pattern.compile("^\\d+$");
public static boolean isIntNum(String str) {
Matcher isIntNum = pattern.matcher(str);
if (!isIntNum.matches()) {
return false;
}
return true;
}
/**
* 判斷是否是浮點數
* @param str
* @return
*/
private static Pattern pattern2 = Pattern.compile("\\d+\\.\\d+$|-\\d+\\.\\d+$");
public static boolean isDoubleNum(String str) {
Matcher isDoubleNum = pattern2.matcher(str);
if (!isDoubleNum.matches()) {
return false;
}
return true;
}
}
簡單使用
@ApiOperation(value = "導出成本統計")
@RequestMapping(value = "/exportList",method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public void ExportConsumeStatis(@RequestBody ParamsCost obj,
HttpServletResponse response){
logger.info("導出成本統計,ParamsConsume:{}",obj);
try{
if(null == obj.getEffectStartTime() || null == obj.getEffectEndTime()){
throw new MyException("開始時間和結束時間不能爲空!", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
String startStr = GeoDateUtils.getDateStr(obj.getEffectStartTime(), GeoDateUtils.DATE_FORMAT2);
String endStr = GeoDateUtils.getDateStr(obj.getEffectEndTime(), GeoDateUtils.DATE_FORMAT2);
String fileName = startStr + "-" + endStr + "(成本統計)";
List<CostStatisVo> consumeStatisVos = costStatisService.costStatisList(obj);
if (null != consumeStatisVos) {
consumeStatisVos.add(costStatisService.costStatisTotal(obj));
}
// 拼接 Excel 數據
Map<String,Object> map = new HashMap<>(3);
String[] titleArr = {"日期","產品","客戶","用戶","用戶賬號","用戶ID","運營商","內部接口","外部接口","計費數","金額"};
String[] attrArr = {"dayFlag","productName","companyName","cuserName","account","cuserId","isp","interfaceName","outInterfaceName","countCharging","cost"};
map.put("titleArr",titleArr);
map.put("attrArr",attrArr);
map.put("dataList", consumeStatisVos);
ExportExcelUtils.buildExcelTemplate(map, response, fileName,4000);
}catch (Exception e) {
e.printStackTrace();
logger.error("導出消耗統計,Exception:",e);
}
}