1.controller
/**
* 條件下載賬單信息excel
*
* @param orderCode 檢索條件
* @param billDtStart 檢索條件
* @param billDtEnd 檢索條件
* @param state 檢索條件
* @param corganCodes 檢索條件
* @param status 檢索條件
* @param flag 檢索條件
* @param userNameLike 檢索條件
* @param capitalSide 資金方
* @param response 相應信息
*/
@GetMapping("/downloadBillExcel")
public void downloadBillExcel(@RequestParam(required = false) String orderCode,
@RequestParam(required = false) String billDtStart,
@RequestParam(required = false) String billDtEnd,
@RequestParam(required = false) String state,
@RequestParam(required = false) String corganCodes,
@RequestParam(required = false) String status,
@RequestParam(required = false) String flag,
@RequestParam(required = false) String userNameLike,
@RequestParam(required = false) String capitalSide, HttpServletResponse response) {
log.info(
"條件下載賬單信息excel-orderCode:{},billDtStart:{},billDtEnd:{},state:{},corganCodes:{},status:{},flag:{},userNameLike:{}",
orderCode, billDtStart, billDtEnd, state, corganCodes, status, flag, userNameLike);
PageMapperDto mapperDto = new PageMapperDto();
mapperDto.setPageStart(null);
mapperDto.setPageSize(null);
mapperDto.setUserName(userNameLike);
mapperDto.setOrderCode(orderCode);
mapperDto.setCorganCodeListByParam(VehicleUtils.stringToList(corganCodes));
mapperDto.setFlagList(VehicleUtils.stringToList(flag));
mapperDto.setStateList(VehicleUtils.stringToList(state));
mapperDto.setStatusList(VehicleUtils.stringToList(status));
mapperDto.setCapitalSideList(VehicleUtils.stringToList(capitalSide));
if (StringUtils.isNotBlank(billDtStart) && StringUtils.isNotBlank(billDtEnd)) {
mapperDto
.setBillDtStart(DateUtils.date2String(DateUtils.parseTimestampToDate(Long.parseLong(billDtStart))));
mapperDto.setBillDtEnd(DateUtils.date2String(DateUtils.parseTimestampToDate(Long.parseLong(billDtEnd))));
}
log.info("條件下載賬單信息mapperDto:{}", JSON.toJSON(mapperDto));
try {
File file = orderBillingService.genFileByCondition(mapperDto);
commonService.downloadFile(file, response);
} catch (Exception e) {
log.error("Exception:{}", JSON.toJSON(e));
}
}
2.serviceImpl
/**
* 條件獲取賬單excel文件
*
* @param mapperDto 檢索條件
* @return excel文件地址
*/
@Override
public File genFileByCondition(PageMapperDto mapperDto) {
List<OrderBillingPageResponseDto> responseDtoList = crudMapper.findOrderBillingPage(mapperDto);
log.info("條件查詢賬單:{}", responseDtoList.size());
// 文件存放目錄
String dir = tempFilePath;
BankUtils.mkDir(dir);
String billExcelPath = String.format(OrderBillingConstants.STRING_FORMAT_4, dir,
OrderBillingConstants.DOWNLOAD_EXCEL_NAME_ORDER_BILL, BankUtils.getCurrentDateTime(),
OrderBillingConstants.EXCEL_FORMAT_XLS);
log.info("準備生成的賬單excel文件地址:{}", billExcelPath);
// sheet頁名稱
String sheetName = OrderBillingConstants.DOWNLOAD_EXCEL_NAME_ORDER_BILL;
// 默認列寬
String defaultColumnLength = OrderBillingConstants.STRING_THIRTY;
// 列寬
List<String> columnLengthList = new ArrayList<>();
// 標題名稱
Object[] nameObj = Stream
.of("訂單編號", "賬單期數", "賬單日期", "承租人姓名", "申請時間", "分公司", "分期金額", "應還本金", "應還利息", "逾期違約金", "逾期違約罰息", "代扣結果",
"資方業務狀態", "賬單標記", "賬單狀態", "是否已逾期", "實際還款日期", "已還月租", "已還本金", "已還利息", "已還違約金", "已還罰息", "待還月租",
"待還本金", "待還利息", "待還違約金", "待還罰息")
.toArray();
String[] title = new String[nameObj.length];
for (int i = 0; i < title.length; i++) {
title[i] = nameObj[i].toString();
if (i == 0 || i == 4 || i == 5) {
columnLengthList.add("30");
} else {
columnLengthList.add("20");
}
}
int size = responseDtoList.size();
String[][] context = new String[size][title.length];
if (CollectionUtils.isNotEmpty(responseDtoList)) {
responseDtoList.sort(Comparator.comparing(OrderBillingPageResponseDto::getId));
for (int i = 0; i < size; i++) {
OrderBillingPageResponseDto responseDto = responseDtoList.get(i);
log.info("********responseDto:{}", JSON.toJSON(responseDto));
for (int j = 0; j < title.length; j++) {
if (j == 0) {
// 訂單編號
context[i][j] = responseDto.getOrderCode();
} else if (j == 1) {
// 賬單期數
context[i][j] = responseDto.getBillPeriod().toString();
} else if (j == 2) {
// 賬單日期
context[i][j] = DateUtils.formatDate(responseDto.getBillDt(),
OrderBillingConstants.TIME_FORMAT);
} else if (j == 3) {
// 承租人姓名
context[i][j] = String.valueOf(responseDto.getUserName());
} else if (j == 4) {
// 申請時間
if (null != responseDto.getApplyTime()) {
context[i][j] = DateUtils.formatDate(responseDto.getApplyTime(),
VehicleConstants.TIANYI_TIME_FORMAT);
}
} else if (j == 5) {
// 分公司
context[i][j] = responseDto.getOrganName();
} else if (j == 6) {
// 分期金額
context[i][j] = String.valueOf(responseDto.getBillFee());
} else if (j == 7) {
// 賬單應還本金
context[i][j] = String.valueOf(responseDto.getBillCapital());
} else if (j == 8) {
// 賬單應還利息
context[i][j] = String.valueOf(responseDto.getBillInterest());
} else if (j == 9) {
// 逾期違約金
context[i][j] = String.valueOf(responseDto.getOverdueContractAmt());
} else if (j == 10) {
// 逾期罰息
context[i][j] = String.valueOf(responseDto.getOverduePenalty());
} else if (j == 11) {
// 代扣結果
context[i][j] = responseDto.getWithholdResult();
} else if (j == 12) {
BillStateEnum billStateEnum = BillStateEnum.getEnumByCode(responseDto.getState());
// 資方業務狀態
if (billStateEnum != null) {
context[i][j] = billStateEnum.getMsg();
}
} else if (j == 13) {
// 賬單標記
BillFlagEnum billFlagEnum = BillFlagEnum.getEnumByCode(responseDto.getFlag());
if (billFlagEnum != null) {
context[i][j] = billFlagEnum.getMsg();
}
} else if (j == 14) {
// 狀態
BillStatusEnum billStatusEnum = BillStatusEnum.getEnumByCode(responseDto.getStatus());
if (billStatusEnum != null) {
context[i][j] = billStatusEnum.getMsg();
}
} else if (j == 15) {
// 是否已逾期
YesNoEnum yesNoEnum = YesNoEnum.getEnumByCode(responseDto.getIsOverdue());
if (yesNoEnum != null) {
context[i][j] = yesNoEnum.getMsg();
}
} else if (j == 16) {
// 實際還款日期
if (null != responseDto.getBillRepayDt()) {
context[i][j] = DateUtils.formatDate(responseDto.getBillRepayDt(),
OrderBillingConstants.TIME_FORMAT);
}
} else if (j == 17) {
// 已還月租
context[i][j] = responseDto.getPaidFee().toString();
} else if (j == 18) {
// 已還本金
context[i][j] = responseDto.getBillCapital()
.subtract(responseDto.getUnpaidCapital())
.toString();
} else if (j == 19) {
// 已還利息
context[i][j] = responseDto.getBillInterest()
.subtract(responseDto.getUnpaidIntrest())
.toString();
} else if (j == 20) {
// 已還違約金
context[i][j] = responseDto.getOverdueContractAmt()
.subtract(responseDto.getUnpaidContractAmt())
.toString();
} else if (j == 21) {
// 已還罰息
context[i][j] = responseDto.getOverduePenalty()
.subtract(responseDto.getUnpaidPenalty())
.toString();
} else if (j == 22) {
// 待還月租
context[i][j] = responseDto.getUnpaidFee().toString();
} else if (j == 23) {
// 待還本金
context[i][j] = responseDto.getUnpaidCapital().toString();
} else if (j == 24) {
// 待還利息
context[i][j] = responseDto.getUnpaidIntrest().toString();
} else if (j == 25) {
// 待還違約金
context[i][j] = responseDto.getUnpaidContractAmt().toString();
} else {
// 待還罰息
context[i][j] = responseDto.getUnpaidPenalty().toString();
}
}
}
}
List<Label> labelList = new ArrayList<>();
List<ExcelMergeCellsDto> mergeCellsDtoList = new ArrayList<>();
// 生成excel文件
ExcelUtils.exportExcel(billExcelPath, sheetName, defaultColumnLength, columnLengthList, title, context,
labelList, mergeCellsDtoList);
return new File(billExcelPath);
}
3. ExcelUtils
import java.io.File;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import com.yifenqi.dto.ExcelMergeCellsDto;
import jxl.CellView;
import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.Colour;
import jxl.format.UnderlineStyle;
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 lombok.extern.slf4j.Slf4j;
/**
* Excel處理工具類
*/
@Slf4j
public class ExcelUtils {
/**
* WORD_TO_PDF_OPERAND
*/
private static final Integer WORD_TO_PDF_OPERAND = 17;
/**
* PPT_TO_PDF_OPERAND
*/
private static final Integer PPT_TO_PDF_OPERAND = 32;
/**
* EXCEL_TO_PDF_OPERAND
*/
private static final Integer EXCEL_TO_PDF_OPERAND = 0;
/**
* 生成Excel到filePath路徑中
*
* @param filePath 生成Excel的保存路徑
* @param sheetName Excel中sheet名
* @param defaultColumnLength 整個Excel的默認單元格寬度
* @param columnLengthList 定義每個列寬
* @param title 標題
* @param context 內容
* @param labelList 需要合併處文字設置
* @param mergeCellsDtoList 單元格合併座標列表
*/
public static void exportExcel(String filePath, String sheetName, String defaultColumnLength,
List<String> columnLengthList, String[] title, String[][] context,
List<Label> labelList, List<ExcelMergeCellsDto> mergeCellsDtoList) {
exportExcel(filePath, sheetName, defaultColumnLength, columnLengthList, title, context, labelList,
mergeCellsDtoList, null);
}
/**
* 生成Excel到filePath路徑中
*
* @param filePath 生成Excel的保存路徑
* @param sheetName Excel中sheet名
* @param defaultColumnLength 整個Excel的默認單元格寬度
* @param columnLengthList 定義每個列寬
* @param title 標題
* @param context 內容
* @param labelList 需要合併處文字設置
* @param mergeCellsDtoList 單元格合併座標列表
* @param rowHeightMap 定義行高
*/
public static void exportExcel(String filePath, String sheetName, String defaultColumnLength,
List<String> columnLengthList, String[] title, String[][] context,
List<Label> labelList, List<ExcelMergeCellsDto> mergeCellsDtoList,
Map<Integer, Integer> rowHeightMap) {
//操作執行
try {
//t.xls爲要新建的文件名
WritableWorkbook book = Workbook.createWorkbook(new File(filePath));
//生成名爲“第一頁”的工作表,參數0表示這是第一頁
WritableSheet sheet = book.createSheet(sheetName, 0);
if (!StringUtils.isBlank(defaultColumnLength)) {
sheet.getSettings().setDefaultColumnWidth(Integer.valueOf(defaultColumnLength));
}
//Excel相關默認設置
WritableCellFormat titleFormat = genTitleFormat();
WritableCellFormat contentFormat = genContentFormat();
CellView cellView = new CellView();
cellView.setAutosize(true);
//寫入標題
for (int i = 0; i < title.length; i++) {
//title
sheet.addCell(new Label(i, 0, title[i], titleFormat));
if (!CollectionUtils.isEmpty(columnLengthList) && columnLengthList.size() >= title.length) {
sheet.setColumnView(i, Integer.valueOf(columnLengthList.get(i)));
}
}
//Excel的內容
//context
for (int i = 0; i < context.length; i++) {
for (int j = 0; j < context[i].length; j++) {
sheet.addCell(new Label(j, i + 1, context[i][j], contentFormat));
}
}
//合併單元格
if (!CollectionUtils.isEmpty(labelList)) {
for (int i = 0; i < labelList.size(); i++) {
addCell(sheet, labelList.get(i));
}
}
if (!CollectionUtils.isEmpty(mergeCellsDtoList)) {
for (int i = 0; i < mergeCellsDtoList.size(); i++) {
ExcelMergeCellsDto record = mergeCellsDtoList.get(i);
mergeCells(sheet, record.getM(), record.getN(), record.getP(), record.getQ());
}
}
//設置行高
if (null != rowHeightMap) {
for (Map.Entry<Integer, Integer> entry : rowHeightMap.entrySet()) {
sheet.setRowView(entry.getKey(), entry.getValue());
}
}
// 空白行,列刪除
removeColumns(sheet);
//寫入數據
book.write();
//關閉文件
book.close();
} catch (Exception e) {
log.error("exportExcel error{}", e);
}
}
/**
* 組裝數據
*
* @param book 文件
* @param sheetName Excel中sheet名
* @param defaultColumnLength 整個Excel的默認單元格寬度
* @param columnLengthList 定義每個列寬
* @param title 標題
* @param context 內容
* @param labelList 需要合併處文字設置
* @param mergeCellsDtoList 單元格合併座標列表
*/
public static void exportExcelData(WritableWorkbook book, String sheetName, String defaultColumnLength,
List<String> columnLengthList, String[] title, String[][] context,
List<Label> labelList, List<ExcelMergeCellsDto> mergeCellsDtoList) {
exportExcelData(book, sheetName, defaultColumnLength, columnLengthList, title, context, labelList,
mergeCellsDtoList, null);
}
/**
* 組裝Excel數據
*
* @param book ExcelBook
* @param sheetName Excel中sheet名
* @param defaultColumnLength 整個Excel的默認單元格寬度
* @param columnLengthList 定義每個列寬
* @param title 標題
* @param context 內容
* @param labelList 需要合併處文字設置
* @param mergeCellsDtoList 單元格合併座標列表
* @param rowHeightMap 定義行高
*/
public static void exportExcelData(WritableWorkbook book, String sheetName, String defaultColumnLength,
List<String> columnLengthList, String[] title, String[][] context,
List<Label> labelList, List<ExcelMergeCellsDto> mergeCellsDtoList,
Map<Integer, Integer> rowHeightMap) {
//操作執行
try {
//生成名爲“第一頁”的工作表,參數0表示這是第一頁
WritableSheet sheet = book.createSheet(sheetName, 0);
if (!StringUtils.isBlank(defaultColumnLength)) {
sheet.getSettings().setDefaultColumnWidth(Integer.valueOf(defaultColumnLength));
}
//Excel相關默認設置
WritableCellFormat titleFormat = genTitleFormat();
WritableCellFormat contentFormat = genContentFormat();
CellView cellView = new CellView();
cellView.setAutosize(true);
//寫入標題
for (int i = 0; i < title.length; i++) {
//title
sheet.addCell(new Label(i, 0, title[i], titleFormat));
if (!CollectionUtils.isEmpty(columnLengthList) && columnLengthList.size() >= title.length) {
sheet.setColumnView(i, Integer.valueOf(columnLengthList.get(i)));
}
}
//Excel的內容
//context
for (int i = 0; i < context.length; i++) {
for (int j = 0; j < context[i].length; j++) {
sheet.addCell(new Label(j, i + 1, context[i][j], contentFormat));
}
}
//合併單元格
if (!CollectionUtils.isEmpty(labelList)) {
for (int i = 0; i < labelList.size(); i++) {
addCell(sheet, labelList.get(i));
}
}
if (!CollectionUtils.isEmpty(mergeCellsDtoList)) {
for (int i = 0; i < mergeCellsDtoList.size(); i++) {
ExcelMergeCellsDto record = mergeCellsDtoList.get(i);
mergeCells(sheet, record.getM(), record.getN(), record.getP(), record.getQ());
}
}
//設置行高
if (null != rowHeightMap) {
for (Map.Entry<Integer, Integer> entry : rowHeightMap.entrySet()) {
sheet.setRowView(entry.getKey(), entry.getValue());
}
}
// 空白行,列刪除
removeColumns(sheet);
} catch (Exception e) {
log.error("exportExcel error{}", e);
}
}
/**
* 特殊單元格數據設置
*
* @param sheet Excel中的sheet
* @param label 頁面
*/
public static void addCell(WritableSheet sheet, Label label) {
try {
sheet.addCell(label);
} catch (WriteException e) {
log.error("addCell error{}", e);
}
}
/**
* 合併單元格.合併既可以是橫向的,也可以是縱向的 WritableSheet.mergeCells(int m,int n,int p,int
* q); 表示由(m,n)到(p,q)的單元格組成的矩形區域合併
*
* @param sheet Excel中的sheet
* @param m 開始單元格x座標
* @param n 開始單元格y座標
* @param p 結束單元格x座標
* @param q 結束單元格y座標
*/
public static void mergeCells(WritableSheet sheet, int m, int n, int p, int q) {
try {
sheet.mergeCells(m, n, p, q);
} catch (WriteException e) {
log.error("mergeCells error{}", e);
}
}
/**
* Excel中的標題格式
*
* @return 標題格式
*/
public static WritableCellFormat genTitleFormat() {
WritableCellFormat cellFormat = null;
//設置垂直居中;
try {
//設置字體;
WritableFont fontTitle = new WritableFont(WritableFont.ARIAL, 14, WritableFont.BOLD, false,
UnderlineStyle.NO_UNDERLINE, Colour.BLACK);
cellFormat = new WritableCellFormat(fontTitle);
//設置背景顏色;
cellFormat.setBackground(Colour.GRAY_25);
//設置邊框;
cellFormat.setBorder(Border.ALL, BorderLineStyle.THIN);
//設置自動換行;
cellFormat.setWrap(true);
//設置文字對齊方式;
cellFormat.setAlignment(Alignment.CENTRE);
cellFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
} catch (WriteException e) {
log.error("genTitleFormat Exception is{}", e);
}
return cellFormat;
}
/**
* Excel中的內容格式
*
* @return 內容格式
*/
public static WritableCellFormat genContentFormat() {
WritableCellFormat cellFormat = null;
//設置垂直居中;
try {
//設置字體;
WritableFont fontTitle = new WritableFont(WritableFont.ARIAL, 12, WritableFont.NO_BOLD, false,
UnderlineStyle.NO_UNDERLINE, Colour.BLACK);
cellFormat = new WritableCellFormat(fontTitle);
//設置背景顏色;
cellFormat.setBackground(Colour.WHITE);
//設置邊框;
cellFormat.setBorder(Border.ALL, BorderLineStyle.THIN);
//設置自動換行;
cellFormat.setWrap(true);
//設置文字對齊方式;
cellFormat.setAlignment(Alignment.LEFT);
cellFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
} catch (WriteException e) {
log.error("genContentFormat Exception is{}", e);
}
return cellFormat;
}
/**
* 刪除空白行
*
* @param sheet Excel中的sheet
*/
public static void removeColumns(WritableSheet sheet) {
//列數
int rsCols = sheet.getColumns();
//行數
int rsRows = sheet.getRows();
int nullCellNum;
//統計行中爲空的單元格數
for (int i = 1; i < rsRows; i++) {
nullCellNum = 0;
for (int j = 0; j < rsCols; j++) {
String val = sheet.getCell(j, i).getContents();
val = StringUtils.trimToEmpty(val);
if (StringUtils.isBlank(val)) {
nullCellNum++;
}
//如果nullCellNum大於或等於總的列數
if (nullCellNum >= rsCols) {
sheet.removeColumn(j);
}
}
}
}
}
4.commonServiceImpl
/**
* 下載單個文件
*
* @param file 文件信息
* @param response 響應信息
*/
@Override
public void downloadFile(File file, HttpServletResponse response) {
long start = System.currentTimeMillis();
try {
int fileBufferSize = CommConstant.FILE_BUFFER_SIZE_DEFAULT;
DictCode dictCode = dictCodeService.findByGroupAndCodeNoCache(CommConstant.FILE_BUFFER_SIZE,
CommonFlag.Y.getCode());
if (dictCode != null) {
fileBufferSize = Integer.valueOf(dictCode.getName());
}
if (file == null) {
response.getWriter().println("file is null , please check file!");
return;
} else if (!file.exists() || file.isDirectory()) {
response.getWriter().println("file is error , please check file!");
return;
}
log.error("下載-{}-開始", file.getName());
response.reset();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition",
"attachment;filename=" + new String((file.getName()).getBytes("gb2312"), "ISO8859-1"));
InputStream in = new FileInputStream(file);
OutputStream out = response.getOutputStream();
byte[] car = new byte[fileBufferSize];
int l;
while ((l = in.read(car)) != -1) {
out.write(car, 0, l);
}
out.flush();
out.close();
in.close();
log.error("下載-完成-文件大小:{} , fileBufferSize:{} byte, 耗時:{} ms", VehicleUtils.getFileSize(file),
fileBufferSize, System.currentTimeMillis() - start);
boolean deleteResult = IOUtils.deleteDir(file);
log.error("下載-完成-刪除本地文件:{}", deleteResult);
} catch (Exception e) {
log.error("下載-異常:{}", JSON.toJSON(e));
}
}
5.IOUtils
/**
* 遞歸刪除目錄下的所有文件及子目錄下所有文件
*
* @param dir 將要刪除的文件目錄
* @return boolean Returns "true" if all deletions were successful. If a
* deletion fails, the method stops attempting to delete and returns
* "false".
*/
public static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
//遞歸刪除目錄中的子目錄下
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// 目錄此時爲空,可以刪除
return dir.delete();
}