导出报表 11点报表
This commit is contained in:
@@ -8,43 +8,16 @@ import com.rj.service.ILbDailyUserTradeReportService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.DataFormat;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
|
||||
import org.apache.poi.ss.usermodel.ComparisonOperator;
|
||||
import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
|
||||
import org.apache.poi.ss.usermodel.FontFormatting;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
||||
import org.apache.poi.xssf.usermodel.XSSFColor;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@@ -658,213 +631,6 @@ public class LbDailyUserTradeReportController {
|
||||
@Parameter(description = "租户ID", required = true)
|
||||
@RequestParam String tenantId,
|
||||
HttpServletResponse response) {
|
||||
try {
|
||||
if (tenantId == null || tenantId.trim().isEmpty()) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "tenantId不能为空");
|
||||
return;
|
||||
}
|
||||
if (reportDate == null || reportDate.trim().isEmpty()) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "reportDate不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
LocalDate parsedReportDate;
|
||||
try {
|
||||
parsedReportDate = LocalDate.parse(reportDate.trim());
|
||||
} catch (Exception e) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "报表日期格式错误,请使用 yyyy-MM-dd");
|
||||
return;
|
||||
}
|
||||
|
||||
LocalDateTime start = parsedReportDate.atStartOfDay();
|
||||
LocalDateTime end = parsedReportDate.plusDays(1).atStartOfDay();
|
||||
|
||||
LambdaQueryWrapper<LbDailyUserTradeReport> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(LbDailyUserTradeReport::getTenantId, tenantId.trim())
|
||||
.ge(LbDailyUserTradeReport::getReportDate, start)
|
||||
.lt(LbDailyUserTradeReport::getReportDate, end)
|
||||
.orderByDesc(LbDailyUserTradeReport::getCreatedAt);
|
||||
|
||||
List<LbDailyUserTradeReport> rows = lbDailyUserTradeReportService.list(queryWrapper);
|
||||
rows.sort(
|
||||
Comparator
|
||||
.comparingInt((LbDailyUserTradeReport o) -> "report_sum".equals(o.getDataType()) ? 1 : 0)
|
||||
.thenComparing((a, b) -> {
|
||||
BigDecimal da = a.getDiffAmt() == null ? BigDecimal.ZERO : a.getDiffAmt();
|
||||
BigDecimal db = b.getDiffAmt() == null ? BigDecimal.ZERO : b.getDiffAmt();
|
||||
return db.compareTo(da);
|
||||
})
|
||||
);
|
||||
|
||||
try (Workbook workbook = new XSSFWorkbook()) {
|
||||
Sheet sheet = workbook.createSheet("report");
|
||||
|
||||
DateTimeFormatter mmdd = DateTimeFormatter.ofPattern("MM-dd");
|
||||
String d0 = parsedReportDate.format(mmdd);
|
||||
String d1 = parsedReportDate.minusDays(1).format(mmdd);
|
||||
|
||||
float rowHeightFactor = 1.3f;
|
||||
sheet.setDefaultRowHeightInPoints(sheet.getDefaultRowHeightInPoints() * rowHeightFactor);
|
||||
|
||||
DataFormat dataFormat = workbook.createDataFormat();
|
||||
|
||||
CellStyle headerStyle = workbook.createCellStyle();
|
||||
Font headerFont = workbook.createFont();
|
||||
headerFont.setBold(true);
|
||||
headerFont.setColor(IndexedColors.DARK_BLUE.getIndex());
|
||||
headerStyle.setFont(headerFont);
|
||||
headerStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
headerStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
|
||||
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
headerStyle.setBorderTop(BorderStyle.THIN);
|
||||
headerStyle.setBorderBottom(BorderStyle.THIN);
|
||||
headerStyle.setBorderLeft(BorderStyle.THIN);
|
||||
headerStyle.setBorderRight(BorderStyle.THIN);
|
||||
|
||||
CellStyle textStyle = workbook.createCellStyle();
|
||||
textStyle.setAlignment(HorizontalAlignment.LEFT);
|
||||
textStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
textStyle.setBorderTop(BorderStyle.THIN);
|
||||
textStyle.setBorderBottom(BorderStyle.THIN);
|
||||
textStyle.setBorderLeft(BorderStyle.THIN);
|
||||
textStyle.setBorderRight(BorderStyle.THIN);
|
||||
|
||||
CellStyle zebraTextStyle = workbook.createCellStyle();
|
||||
zebraTextStyle.cloneStyleFrom(textStyle);
|
||||
zebraTextStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
CellStyle intStyle = workbook.createCellStyle();
|
||||
intStyle.setAlignment(HorizontalAlignment.RIGHT);
|
||||
intStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
intStyle.setDataFormat(dataFormat.getFormat("#,##0"));
|
||||
intStyle.setBorderTop(BorderStyle.THIN);
|
||||
intStyle.setBorderBottom(BorderStyle.THIN);
|
||||
intStyle.setBorderLeft(BorderStyle.THIN);
|
||||
intStyle.setBorderRight(BorderStyle.THIN);
|
||||
|
||||
CellStyle zebraIntStyle = workbook.createCellStyle();
|
||||
zebraIntStyle.cloneStyleFrom(intStyle);
|
||||
zebraIntStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
// 更淡的斑马纹底色(接近白色)
|
||||
XSSFColor zebraFill = new XSSFColor(new Color(242, 244, 248), null);
|
||||
((XSSFCellStyle) zebraTextStyle).setFillForegroundColor(zebraFill);
|
||||
((XSSFCellStyle) zebraIntStyle).setFillForegroundColor(zebraFill);
|
||||
|
||||
CellStyle summaryTextStyle = workbook.createCellStyle();
|
||||
summaryTextStyle.cloneStyleFrom(textStyle);
|
||||
summaryTextStyle.setFillForegroundColor(IndexedColors.LEMON_CHIFFON.getIndex());
|
||||
summaryTextStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
Font summaryFont = workbook.createFont();
|
||||
summaryFont.setBold(true);
|
||||
summaryTextStyle.setFont(summaryFont);
|
||||
summaryTextStyle.setBorderTop(BorderStyle.THIN);
|
||||
|
||||
CellStyle summaryIntStyle = workbook.createCellStyle();
|
||||
summaryIntStyle.cloneStyleFrom(intStyle);
|
||||
summaryIntStyle.setFillForegroundColor(IndexedColors.LEMON_CHIFFON.getIndex());
|
||||
summaryIntStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
summaryIntStyle.setFont(summaryFont);
|
||||
summaryIntStyle.setBorderTop(BorderStyle.THIN);
|
||||
|
||||
int r = 0;
|
||||
Row header = sheet.createRow(r++);
|
||||
header.setHeightInPoints(20 * rowHeightFactor);
|
||||
createHeaderCell(header, 0, "昵称", headerStyle);
|
||||
createHeaderCell(header, 1, d1 + "买货", headerStyle);
|
||||
createHeaderCell(header, 2, d0 + "卖货", headerStyle);
|
||||
createHeaderCell(header, 3, d0 + "买货", headerStyle);
|
||||
createHeaderCell(header, 4, "服务费", headerStyle);
|
||||
createHeaderCell(header, 5, "差额", headerStyle);
|
||||
createHeaderCell(header, 6, "应收应付", headerStyle);
|
||||
createHeaderCell(header, 7, "抵扣金额", headerStyle);
|
||||
|
||||
sheet.createFreezePane(0, 1);
|
||||
sheet.setAutoFilter(new CellRangeAddress(0, 0, 0, 7));
|
||||
|
||||
for (LbDailyUserTradeReport item : rows) {
|
||||
Row row = sheet.createRow(r++);
|
||||
row.setHeightInPoints(row.getHeightInPoints() * rowHeightFactor);
|
||||
boolean isSummary = "report_sum".equals(item.getDataType());
|
||||
boolean zebra = (r % 2 == 0);
|
||||
|
||||
CellStyle tStyle = isSummary ? summaryTextStyle : (zebra ? zebraTextStyle : textStyle);
|
||||
CellStyle nStyle = isSummary ? summaryIntStyle : (zebra ? zebraIntStyle : intStyle);
|
||||
|
||||
createTextCell(row, 0, item.getNickname() == null ? "" : item.getNickname(), tStyle);
|
||||
createIntCell(row, 1, roundedInt(item.getYestodayBuyAmt()), nStyle);
|
||||
createIntCell(row, 2, roundedInt(item.getDailySellAmt()), nStyle);
|
||||
createIntCell(row, 3, roundedInt(item.getDailyBuyAmt()), nStyle);
|
||||
createIntCell(row, 4, roundedInt(item.getServiceAmt()), nStyle);
|
||||
createIntCell(row, 5, roundedInt(item.getDiffAmt()), nStyle);
|
||||
createIntCell(row, 6, roundedInt(item.getActualReceiptsPayments()), nStyle);
|
||||
createIntCell(row, 7, roundedInt(item.getDikouAmt()), nStyle);
|
||||
}
|
||||
|
||||
if (r > 1) {
|
||||
SheetConditionalFormatting scf = sheet.getSheetConditionalFormatting();
|
||||
ConditionalFormattingRule negative = scf.createConditionalFormattingRule(ComparisonOperator.LT, "0");
|
||||
FontFormatting ff = negative.createFontFormatting();
|
||||
ff.setFontColorIndex(IndexedColors.DARK_RED.getIndex());
|
||||
ff.setFontStyle(false, false);
|
||||
scf.addConditionalFormatting(new CellRangeAddress[]{new CellRangeAddress(1, r - 1, 5, 5)}, negative);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
sheet.autoSizeColumn(i);
|
||||
int currentWidth = sheet.getColumnWidth(i);
|
||||
int widened = (int) Math.min(255 * 256, Math.round(currentWidth * 1.5));
|
||||
sheet.setColumnWidth(i, widened);
|
||||
}
|
||||
|
||||
String filename = "当日汇总报表" + parsedReportDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + ".xlsx";
|
||||
String encoded = URLEncoder.encode(filename, StandardCharsets.UTF_8).replaceAll("\\+", "%20");
|
||||
|
||||
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encoded);
|
||||
|
||||
try (ServletOutputStream os = response.getOutputStream()) {
|
||||
workbook.write(os);
|
||||
os.flush();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
response.reset();
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
response.setContentType("text/plain;charset=UTF-8");
|
||||
response.getWriter().write("导出异常:" + e.getMessage());
|
||||
} catch (Exception ignored) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static long roundedInt(BigDecimal value) {
|
||||
if (value == null) {
|
||||
return 0L;
|
||||
}
|
||||
return value.setScale(0, RoundingMode.HALF_UP).longValue();
|
||||
}
|
||||
|
||||
private static void createHeaderCell(Row row, int col, String text, CellStyle style) {
|
||||
Cell cell = row.createCell(col);
|
||||
cell.setCellValue(text);
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
|
||||
private static void createTextCell(Row row, int col, String text, CellStyle style) {
|
||||
Cell cell = row.createCell(col);
|
||||
cell.setCellValue(text);
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
|
||||
private static void createIntCell(Row row, int col, long value, CellStyle style) {
|
||||
Cell cell = row.createCell(col);
|
||||
cell.setCellValue((double) value);
|
||||
cell.setCellStyle(style);
|
||||
lbDailyUserTradeReportService.exportByDateAndTenant(reportDate, tenantId, response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.rj.entity.LbDailyUserTrade;
|
||||
import com.rj.entity.LbDailyUserTradeReport;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -33,4 +35,9 @@ public interface ILbDailyUserTradeReportService extends IService<LbDailyUserTrad
|
||||
*/
|
||||
Map<String, Object> listUserTradeAmountWithTeamByDateRangeAndTenant(
|
||||
LocalDate startDate, LocalDate endDate, String tenantId);
|
||||
|
||||
/**
|
||||
* 按报表日期与租户导出 Excel。
|
||||
*/
|
||||
void exportByDateAndTenant(String reportDate, String tenantId, HttpServletResponse response);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.rj.service;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.rj.entity.LbDeductionAmount;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ILbDeductionAmountService extends IService<LbDeductionAmount> {
|
||||
@@ -25,4 +27,9 @@ public interface ILbDeductionAmountService extends IService<LbDeductionAmount> {
|
||||
* 根据自然语言文本调用大模型解析为 {@link LbDeductionAmount} 并落库。
|
||||
*/
|
||||
Map<String, Object> parseFromTextByLlmAndSave(String tenantId, String text);
|
||||
|
||||
/**
|
||||
* 按租户、报表日期汇总抵扣金额:key 为 user_name(trim),value 为同日 create_time 记录的 dikou_amt 之和。
|
||||
*/
|
||||
Map<String, BigDecimal> sumDikouAmtByUserNameForReportDate(String tenantId, LocalDate reportDate);
|
||||
}
|
||||
|
||||
@@ -6,12 +6,15 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.rj.entity.LbDailyUserTrade;
|
||||
import com.rj.entity.LbDailyUserTradeReport;
|
||||
import com.rj.entity.LbDepartmentUser;
|
||||
import com.rj.service.ILbDeductionAmountService;
|
||||
import com.rj.mapper.LbDailyUserTradeMapper;
|
||||
import com.rj.mapper.LbDailyUserTradeReportMapper;
|
||||
import com.rj.service.ILbDailyUserTradeReportService;
|
||||
import com.rj.service.ILbDepartmentUserService;
|
||||
import com.rj.service.support.LbDailyUserTradeReportExportSupport;
|
||||
import com.rj.service.support.LbDailyUserTradeReportWriteSupport;
|
||||
import com.rj.tenant.TenantContextHolder;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -53,6 +56,8 @@ public class LbDailyUserTradeReportServiceImpl extends ServiceImpl<LbDailyUserTr
|
||||
private LbDailyUserTradeMapper lbDailyUserTradeMapper;
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
@Autowired
|
||||
private ILbDeductionAmountService lbDeductionAmountService;
|
||||
|
||||
@Override
|
||||
public Page<LbDailyUserTrade> pageDailyUserTradeByUserIdAndDateRange(
|
||||
@@ -498,6 +503,60 @@ public class LbDailyUserTradeReportServiceImpl extends ServiceImpl<LbDailyUserTr
|
||||
checkInfo.put("detailCheckPassed", mismatchUsers.isEmpty() && missingInTodayUsers.isEmpty() && extraInTodayUsers.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportByDateAndTenant(String reportDate, String tenantId, HttpServletResponse response) {
|
||||
try {
|
||||
if (tenantId == null || tenantId.trim().isEmpty()) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "tenantId不能为空");
|
||||
return;
|
||||
}
|
||||
if (reportDate == null || reportDate.trim().isEmpty()) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "reportDate不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
LocalDate parsedReportDate;
|
||||
try {
|
||||
parsedReportDate = LocalDate.parse(reportDate.trim());
|
||||
} catch (Exception e) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "报表日期格式错误,请使用 yyyy-MM-dd");
|
||||
return;
|
||||
}
|
||||
|
||||
String tenantIdTrim = tenantId.trim();
|
||||
List<LbDailyUserTradeReport> rows = listReportsForExport(tenantIdTrim, parsedReportDate);
|
||||
Map<String, BigDecimal> deductionByUserName =
|
||||
lbDeductionAmountService.sumDikouAmtByUserNameForReportDate(tenantIdTrim, parsedReportDate);
|
||||
LbDailyUserTradeReportExportSupport.writeExcel(
|
||||
parsedReportDate, rows, deductionByUserName, response);
|
||||
} catch (Exception e) {
|
||||
LbDailyUserTradeReportExportSupport.writeExportError(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<LbDailyUserTradeReport> listReportsForExport(String tenantId, LocalDate reportDate) {
|
||||
LocalDateTime start = reportDate.atStartOfDay();
|
||||
LocalDateTime end = reportDate.plusDays(1).atStartOfDay();
|
||||
|
||||
LambdaQueryWrapper<LbDailyUserTradeReport> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(LbDailyUserTradeReport::getTenantId, tenantId)
|
||||
.ge(LbDailyUserTradeReport::getReportDate, start)
|
||||
.lt(LbDailyUserTradeReport::getReportDate, end)
|
||||
.orderByDesc(LbDailyUserTradeReport::getCreatedAt);
|
||||
|
||||
List<LbDailyUserTradeReport> rows = list(queryWrapper);
|
||||
rows.sort(
|
||||
Comparator
|
||||
.comparingInt((LbDailyUserTradeReport o) -> DATA_TYPE_REPORT_SUM.equals(o.getDataType()) ? 1 : 0)
|
||||
.thenComparing((a, b) -> {
|
||||
BigDecimal da = a.getDiffAmt() == null ? BigDecimal.ZERO : a.getDiffAmt();
|
||||
BigDecimal db = b.getDiffAmt() == null ? BigDecimal.ZERO : b.getDiffAmt();
|
||||
return db.compareTo(da);
|
||||
})
|
||||
);
|
||||
return rows;
|
||||
}
|
||||
|
||||
private static final class DetailRepairStat {
|
||||
final boolean repaired;
|
||||
final int updatedCount;
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -429,6 +430,30 @@ public class LbDeductionAmountServiceImpl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, BigDecimal> sumDikouAmtByUserNameForReportDate(String tenantId, LocalDate reportDate) {
|
||||
Map<String, BigDecimal> byUserName = new HashMap<>();
|
||||
if (tenantId == null || tenantId.trim().isEmpty() || reportDate == null) {
|
||||
return byUserName;
|
||||
}
|
||||
LocalDateTime start = reportDate.atStartOfDay();
|
||||
LocalDateTime end = reportDate.plusDays(1).atStartOfDay();
|
||||
LambdaQueryWrapper<LbDeductionAmount> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(LbDeductionAmount::getTenantId, tenantId.trim())
|
||||
.ge(LbDeductionAmount::getCreateTime, start)
|
||||
.lt(LbDeductionAmount::getCreateTime, end);
|
||||
List<LbDeductionAmount> records = list(queryWrapper);
|
||||
for (LbDeductionAmount record : records) {
|
||||
if (record.getUserName() == null || record.getUserName().trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String key = record.getUserName().trim();
|
||||
BigDecimal amt = record.getDikouAmt() == null ? BigDecimal.ZERO : record.getDikouAmt();
|
||||
byUserName.merge(key, amt, BigDecimal::add);
|
||||
}
|
||||
return byUserName;
|
||||
}
|
||||
|
||||
private static LocalDateTime parseDateTime(String text) {
|
||||
if (text == null || text.trim().isEmpty()) {
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,450 @@
|
||||
package com.rj.service.support;
|
||||
|
||||
import com.rj.entity.LbDailyUserTradeReport;
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.ComparisonOperator;
|
||||
import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
|
||||
import org.apache.poi.ss.usermodel.DataFormat;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.FontFormatting;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
|
||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
||||
import org.apache.poi.xssf.usermodel.XSSFColor;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 当日用户交易报表 Excel 导出(POI 样式与写入逻辑)。
|
||||
*/
|
||||
public final class LbDailyUserTradeReportExportSupport {
|
||||
|
||||
/** 导出工作簿固定 7 个 sheet(顺序与业务模板一致)。 */
|
||||
private static final String[] EXPORT_SHEET_NAMES = {
|
||||
"总表", "抵扣表", "支付表", "11点表", "断货表", "临时表2", "结果表"
|
||||
};
|
||||
|
||||
private static final int SUMMARY_SHEET_INDEX = 0;
|
||||
private static final int DEDUCTION_SHEET_INDEX = 1;
|
||||
private static final int ELEVEN_CLOCK_SHEET_INDEX = 3;
|
||||
|
||||
private static final int COL_NICKNAME = 0;
|
||||
private static final int COL_YESTODAY_BUY = 1;
|
||||
private static final int COL_DAILY_SELL = 2;
|
||||
private static final int COL_DAILY_BUY = 3;
|
||||
private static final int COL_SERVICE = 4;
|
||||
private static final int COL_DIFF = 5;
|
||||
private static final int COL_ACTUAL = 6;
|
||||
private static final int COL_DIKOU = 7;
|
||||
|
||||
private static final int SUMMARY_LAST_COL = COL_DIKOU;
|
||||
/** 11点表:最左侧序号列,其余列右移一列 */
|
||||
private static final int ELEVEN_CLOCK_LAST_COL = COL_DIKOU + 1;
|
||||
private static final int COL_SEQUENCE_LEFT = 0;
|
||||
|
||||
private static final String DATA_TYPE_REPORT_SUM = "report_sum";
|
||||
|
||||
private LbDailyUserTradeReportExportSupport() {
|
||||
}
|
||||
|
||||
public static void writeExcel(
|
||||
LocalDate reportDate,
|
||||
List<LbDailyUserTradeReport> rows,
|
||||
Map<String, BigDecimal> deductionByUserName,
|
||||
HttpServletResponse response) throws IOException {
|
||||
try (Workbook workbook = new XSSFWorkbook()) {
|
||||
SheetStyles styles = SheetStyles.create(workbook);
|
||||
for (String sheetName : EXPORT_SHEET_NAMES) {
|
||||
Sheet sheet = workbook.createSheet(sheetName);
|
||||
sheet.setDefaultRowHeightInPoints(sheet.getDefaultRowHeightInPoints() * styles.rowHeightFactor);
|
||||
}
|
||||
|
||||
DateHeaderLabels labels = DateHeaderLabels.of(reportDate);
|
||||
fillSummarySheet(workbook.getSheetAt(SUMMARY_SHEET_INDEX), labels, rows, styles);
|
||||
Map<String, BigDecimal> deductionMap = deductionByUserName == null ? Map.of() : deductionByUserName;
|
||||
fillDeductionSheet(workbook.getSheetAt(DEDUCTION_SHEET_INDEX), labels, rows, styles, deductionMap, false, true);
|
||||
// 11点表:与抵扣表相同的数据与计算逻辑,最左侧序号列,不含最后一行汇总
|
||||
fillDeductionSheet(workbook.getSheetAt(ELEVEN_CLOCK_SHEET_INDEX), labels, rows, styles, deductionMap, true, false);
|
||||
|
||||
String filename = "当日汇总报表" + reportDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + ".xlsx";
|
||||
String encoded = URLEncoder.encode(filename, StandardCharsets.UTF_8).replaceAll("\\+", "%20");
|
||||
|
||||
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encoded);
|
||||
|
||||
try (ServletOutputStream os = response.getOutputStream()) {
|
||||
workbook.write(os);
|
||||
os.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void fillSummarySheet(
|
||||
Sheet sheet,
|
||||
DateHeaderLabels labels,
|
||||
List<LbDailyUserTradeReport> rows,
|
||||
SheetStyles styles) {
|
||||
int r = writeHeaderRow(sheet, labels, styles, false);
|
||||
sheet.createFreezePane(0, 1);
|
||||
sheet.setAutoFilter(new CellRangeAddress(0, 0, 0, SUMMARY_LAST_COL));
|
||||
|
||||
for (LbDailyUserTradeReport item : rows) {
|
||||
Row row = sheet.createRow(r++);
|
||||
applyRowHeight(row, styles);
|
||||
RowStylePair rowStyles = rowStyles(item, r, styles);
|
||||
writeBaseDataCells(row, item, rowStyles, roundedInt(item.getDikouAmt()), false);
|
||||
}
|
||||
|
||||
applyDiffNegativeFormatting(sheet, r, false);
|
||||
autoSizeColumns(sheet, SUMMARY_LAST_COL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 抵扣表 / 11点表:先按总表写入各行;抵扣金额列改为 lb_deduction_amount 匹配值;
|
||||
* 「实际收付」= 抵扣金额 + 原实际收付;明细按实际收付倒序。
|
||||
* 抵扣表最后一行汇总行的抵扣金额、实际收付为本列明细之和;11点表不输出汇总行,最左侧为序号列。
|
||||
*/
|
||||
private static void fillDeductionSheet(
|
||||
Sheet sheet,
|
||||
DateHeaderLabels labels,
|
||||
List<LbDailyUserTradeReport> rows,
|
||||
SheetStyles styles,
|
||||
Map<String, BigDecimal> deductionByUserName,
|
||||
boolean sequenceOnLeft,
|
||||
boolean includeSummaryRow) {
|
||||
int lastCol = sequenceOnLeft ? ELEVEN_CLOCK_LAST_COL : SUMMARY_LAST_COL;
|
||||
int r = writeHeaderRow(sheet, labels, styles, sequenceOnLeft);
|
||||
sheet.createFreezePane(0, 1);
|
||||
sheet.setAutoFilter(new CellRangeAddress(0, 0, 0, lastCol));
|
||||
|
||||
long totalDikou = 0;
|
||||
long totalActual = 0;
|
||||
int sequence = 0;
|
||||
|
||||
for (LbDailyUserTradeReport item : orderRowsForDeductionSheet(rows, deductionByUserName)) {
|
||||
boolean isSummaryRow = DATA_TYPE_REPORT_SUM.equals(item.getDataType());
|
||||
if (!includeSummaryRow && isSummaryRow) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Row row = sheet.createRow(r++);
|
||||
applyRowHeight(row, styles);
|
||||
RowStylePair rowStyles = rowStyles(item, r, styles);
|
||||
|
||||
// 第1步:与总表一致(其它列含汇总行均沿用报表原值)
|
||||
long dikouFromReport = roundedInt(item.getDikouAmt());
|
||||
long actualReceiptsPayments = roundedInt(item.getActualReceiptsPayments());
|
||||
writeBaseDataCells(row, item, rowStyles, dikouFromReport, sequenceOnLeft);
|
||||
|
||||
if (isSummaryRow) {
|
||||
// 汇总行:抵扣金额、实际收付 = 上方明细行之和
|
||||
createIntCell(row, dataCol(COL_DIKOU, sequenceOnLeft), totalDikou, rowStyles.numberStyle);
|
||||
createIntCell(row, dataCol(COL_ACTUAL, sequenceOnLeft), totalActual, rowStyles.numberStyle);
|
||||
} else {
|
||||
if (sequenceOnLeft) {
|
||||
sequence++;
|
||||
createIntCell(row, COL_SEQUENCE_LEFT, sequence, rowStyles.numberStyle);
|
||||
}
|
||||
|
||||
// 第2步:按昵称 + 报表日匹配 lb_deduction_amount,覆盖抵扣金额列
|
||||
long dikouFromDb = roundedInt(lookupDeductionAmt(item.getNickname(), deductionByUserName));
|
||||
createIntCell(row, dataCol(COL_DIKOU, sequenceOnLeft), dikouFromDb, rowStyles.numberStyle);
|
||||
|
||||
// 第3步:抵扣金额 + 原实际收付,覆盖「实际收付」列
|
||||
long dikouPlusActual = computeActualReceiptsForDeduction(item, deductionByUserName);
|
||||
createIntCell(row, dataCol(COL_ACTUAL, sequenceOnLeft), dikouPlusActual, rowStyles.numberStyle);
|
||||
|
||||
totalDikou += dikouFromDb;
|
||||
totalActual += dikouPlusActual;
|
||||
}
|
||||
}
|
||||
|
||||
applyDiffNegativeFormatting(sheet, r, sequenceOnLeft);
|
||||
autoSizeColumns(sheet, lastCol);
|
||||
}
|
||||
|
||||
/** 抵扣表:明细按计算后的实际收付倒序,汇总行保持在最后。 */
|
||||
private static List<LbDailyUserTradeReport> orderRowsForDeductionSheet(
|
||||
List<LbDailyUserTradeReport> rows,
|
||||
Map<String, BigDecimal> deductionByUserName) {
|
||||
List<LbDailyUserTradeReport> details = new ArrayList<>();
|
||||
List<LbDailyUserTradeReport> summaries = new ArrayList<>();
|
||||
for (LbDailyUserTradeReport row : rows) {
|
||||
if (DATA_TYPE_REPORT_SUM.equals(row.getDataType())) {
|
||||
summaries.add(row);
|
||||
} else {
|
||||
details.add(row);
|
||||
}
|
||||
}
|
||||
details.sort((a, b) -> Long.compare(
|
||||
computeActualReceiptsForDeduction(b, deductionByUserName),
|
||||
computeActualReceiptsForDeduction(a, deductionByUserName)));
|
||||
List<LbDailyUserTradeReport> ordered = new ArrayList<>(details.size() + summaries.size());
|
||||
ordered.addAll(details);
|
||||
ordered.addAll(summaries);
|
||||
return ordered;
|
||||
}
|
||||
|
||||
private static long computeActualReceiptsForDeduction(
|
||||
LbDailyUserTradeReport item,
|
||||
Map<String, BigDecimal> deductionByUserName) {
|
||||
long dikouFromDb = roundedInt(lookupDeductionAmt(item.getNickname(), deductionByUserName));
|
||||
long actualReceiptsPayments = roundedInt(item.getActualReceiptsPayments());
|
||||
return dikouFromDb + actualReceiptsPayments;
|
||||
}
|
||||
|
||||
private static int dataCol(int col, boolean sequenceOnLeft) {
|
||||
return sequenceOnLeft ? col + 1 : col;
|
||||
}
|
||||
|
||||
private static int writeHeaderRow(
|
||||
Sheet sheet,
|
||||
DateHeaderLabels labels,
|
||||
SheetStyles styles,
|
||||
boolean sequenceOnLeft) {
|
||||
int r = 0;
|
||||
Row header = sheet.createRow(r++);
|
||||
header.setHeightInPoints(20 * styles.rowHeightFactor);
|
||||
if (sequenceOnLeft) {
|
||||
createHeaderCell(header, COL_SEQUENCE_LEFT, "序号", styles.headerStyle);
|
||||
}
|
||||
createHeaderCell(header, dataCol(COL_NICKNAME, sequenceOnLeft), "昵称", styles.headerStyle);
|
||||
createHeaderCell(header, dataCol(COL_YESTODAY_BUY, sequenceOnLeft), labels.yestodayBuyLabel, styles.headerStyle);
|
||||
createHeaderCell(header, dataCol(COL_DAILY_SELL, sequenceOnLeft), labels.dailySellLabel, styles.headerStyle);
|
||||
createHeaderCell(header, dataCol(COL_DAILY_BUY, sequenceOnLeft), labels.dailyBuyLabel, styles.headerStyle);
|
||||
createHeaderCell(header, dataCol(COL_SERVICE, sequenceOnLeft), "服务费", styles.headerStyle);
|
||||
createHeaderCell(header, dataCol(COL_DIFF, sequenceOnLeft), "差额", styles.headerStyle);
|
||||
createHeaderCell(header, dataCol(COL_ACTUAL, sequenceOnLeft), "实际收付", styles.headerStyle);
|
||||
createHeaderCell(header, dataCol(COL_DIKOU, sequenceOnLeft), "抵扣金额", styles.headerStyle);
|
||||
return r;
|
||||
}
|
||||
|
||||
private static void writeBaseDataCells(
|
||||
Row row,
|
||||
LbDailyUserTradeReport item,
|
||||
RowStylePair rowStyles,
|
||||
long dikouAmt,
|
||||
boolean sequenceOnLeft) {
|
||||
createTextCell(
|
||||
row,
|
||||
dataCol(COL_NICKNAME, sequenceOnLeft),
|
||||
item.getNickname() == null ? "" : item.getNickname(),
|
||||
rowStyles.textStyle);
|
||||
createIntCell(row, dataCol(COL_YESTODAY_BUY, sequenceOnLeft), roundedInt(item.getYestodayBuyAmt()), rowStyles.numberStyle);
|
||||
createIntCell(row, dataCol(COL_DAILY_SELL, sequenceOnLeft), roundedInt(item.getDailySellAmt()), rowStyles.numberStyle);
|
||||
createIntCell(row, dataCol(COL_DAILY_BUY, sequenceOnLeft), roundedInt(item.getDailyBuyAmt()), rowStyles.numberStyle);
|
||||
createIntCell(row, dataCol(COL_SERVICE, sequenceOnLeft), roundedInt(item.getServiceAmt()), rowStyles.numberStyle);
|
||||
createIntCell(row, dataCol(COL_DIFF, sequenceOnLeft), roundedInt(item.getDiffAmt()), rowStyles.numberStyle);
|
||||
createIntCell(row, dataCol(COL_ACTUAL, sequenceOnLeft), roundedInt(item.getActualReceiptsPayments()), rowStyles.numberStyle);
|
||||
createIntCell(row, dataCol(COL_DIKOU, sequenceOnLeft), dikouAmt, rowStyles.numberStyle);
|
||||
}
|
||||
|
||||
private static RowStylePair rowStyles(LbDailyUserTradeReport item, int rowIndex, SheetStyles styles) {
|
||||
boolean isSummary = DATA_TYPE_REPORT_SUM.equals(item.getDataType());
|
||||
boolean zebra = (rowIndex % 2 == 0);
|
||||
CellStyle textStyle = isSummary ? styles.summaryTextStyle : (zebra ? styles.zebraTextStyle : styles.textStyle);
|
||||
CellStyle numberStyle = isSummary ? styles.summaryIntStyle : (zebra ? styles.zebraIntStyle : styles.intStyle);
|
||||
return new RowStylePair(textStyle, numberStyle);
|
||||
}
|
||||
|
||||
private static BigDecimal lookupDeductionAmt(String nickname, Map<String, BigDecimal> deductionByUserName) {
|
||||
if (nickname == null || nickname.trim().isEmpty()) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return deductionByUserName.getOrDefault(nickname.trim(), BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
private static void applyRowHeight(Row row, SheetStyles styles) {
|
||||
row.setHeightInPoints(row.getHeightInPoints() * styles.rowHeightFactor);
|
||||
}
|
||||
|
||||
private static void applyDiffNegativeFormatting(Sheet sheet, int nextRowIndex, boolean sequenceOnLeft) {
|
||||
if (nextRowIndex > 1) {
|
||||
int diffCol = dataCol(COL_DIFF, sequenceOnLeft);
|
||||
SheetConditionalFormatting scf = sheet.getSheetConditionalFormatting();
|
||||
ConditionalFormattingRule negative = scf.createConditionalFormattingRule(ComparisonOperator.LT, "0");
|
||||
FontFormatting ff = negative.createFontFormatting();
|
||||
ff.setFontColorIndex(IndexedColors.DARK_RED.getIndex());
|
||||
ff.setFontStyle(false, false);
|
||||
scf.addConditionalFormatting(
|
||||
new CellRangeAddress[]{new CellRangeAddress(1, nextRowIndex - 1, diffCol, diffCol)}, negative);
|
||||
}
|
||||
}
|
||||
|
||||
private static void autoSizeColumns(Sheet sheet, int lastCol) {
|
||||
for (int i = 0; i <= lastCol; i++) {
|
||||
sheet.autoSizeColumn(i);
|
||||
int currentWidth = sheet.getColumnWidth(i);
|
||||
int widened = (int) Math.min(255 * 256, Math.round(currentWidth * 1.5));
|
||||
sheet.setColumnWidth(i, widened);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeExportError(HttpServletResponse response, Exception e) {
|
||||
try {
|
||||
response.reset();
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
response.setContentType("text/plain;charset=UTF-8");
|
||||
response.getWriter().write("导出异常:" + e.getMessage());
|
||||
} catch (Exception ignored) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
private static long roundedInt(BigDecimal value) {
|
||||
if (value == null) {
|
||||
return 0L;
|
||||
}
|
||||
return value.setScale(0, RoundingMode.HALF_UP).longValue();
|
||||
}
|
||||
|
||||
private static void createHeaderCell(Row row, int col, String text, CellStyle style) {
|
||||
Cell cell = row.createCell(col);
|
||||
cell.setCellValue(text);
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
|
||||
private static void createTextCell(Row row, int col, String text, CellStyle style) {
|
||||
Cell cell = row.createCell(col);
|
||||
cell.setCellValue(text);
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
|
||||
private static void createIntCell(Row row, int col, long value, CellStyle style) {
|
||||
Cell cell = row.createCell(col);
|
||||
cell.setCellValue((double) value);
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
|
||||
private record DateHeaderLabels(String yestodayBuyLabel, String dailySellLabel, String dailyBuyLabel) {
|
||||
static DateHeaderLabels of(LocalDate reportDate) {
|
||||
DateTimeFormatter mmdd = DateTimeFormatter.ofPattern("MM-dd");
|
||||
String d0 = reportDate.format(mmdd);
|
||||
String d1 = reportDate.minusDays(1).format(mmdd);
|
||||
return new DateHeaderLabels(d1 + "买货", d0 + "卖货", d0 + "买货");
|
||||
}
|
||||
}
|
||||
|
||||
private record RowStylePair(CellStyle textStyle, CellStyle numberStyle) {
|
||||
}
|
||||
|
||||
private static final class SheetStyles {
|
||||
final float rowHeightFactor = 1.3f;
|
||||
final CellStyle headerStyle;
|
||||
final CellStyle textStyle;
|
||||
final CellStyle zebraTextStyle;
|
||||
final CellStyle intStyle;
|
||||
final CellStyle zebraIntStyle;
|
||||
final CellStyle summaryTextStyle;
|
||||
final CellStyle summaryIntStyle;
|
||||
|
||||
private SheetStyles(
|
||||
CellStyle headerStyle,
|
||||
CellStyle textStyle,
|
||||
CellStyle zebraTextStyle,
|
||||
CellStyle intStyle,
|
||||
CellStyle zebraIntStyle,
|
||||
CellStyle summaryTextStyle,
|
||||
CellStyle summaryIntStyle) {
|
||||
this.headerStyle = headerStyle;
|
||||
this.textStyle = textStyle;
|
||||
this.zebraTextStyle = zebraTextStyle;
|
||||
this.intStyle = intStyle;
|
||||
this.zebraIntStyle = zebraIntStyle;
|
||||
this.summaryTextStyle = summaryTextStyle;
|
||||
this.summaryIntStyle = summaryIntStyle;
|
||||
}
|
||||
|
||||
static SheetStyles create(Workbook workbook) {
|
||||
DataFormat dataFormat = workbook.createDataFormat();
|
||||
|
||||
CellStyle headerStyle = workbook.createCellStyle();
|
||||
Font headerFont = workbook.createFont();
|
||||
headerFont.setBold(true);
|
||||
headerFont.setColor(IndexedColors.DARK_BLUE.getIndex());
|
||||
headerStyle.setFont(headerFont);
|
||||
headerStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
headerStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
|
||||
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
headerStyle.setBorderTop(BorderStyle.THIN);
|
||||
headerStyle.setBorderBottom(BorderStyle.THIN);
|
||||
headerStyle.setBorderLeft(BorderStyle.THIN);
|
||||
headerStyle.setBorderRight(BorderStyle.THIN);
|
||||
|
||||
CellStyle textStyle = workbook.createCellStyle();
|
||||
textStyle.setAlignment(HorizontalAlignment.LEFT);
|
||||
textStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
textStyle.setBorderTop(BorderStyle.THIN);
|
||||
textStyle.setBorderBottom(BorderStyle.THIN);
|
||||
textStyle.setBorderLeft(BorderStyle.THIN);
|
||||
textStyle.setBorderRight(BorderStyle.THIN);
|
||||
|
||||
CellStyle zebraTextStyle = workbook.createCellStyle();
|
||||
zebraTextStyle.cloneStyleFrom(textStyle);
|
||||
zebraTextStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
CellStyle intStyle = workbook.createCellStyle();
|
||||
intStyle.setAlignment(HorizontalAlignment.RIGHT);
|
||||
intStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
intStyle.setDataFormat(dataFormat.getFormat("#,##0"));
|
||||
intStyle.setBorderTop(BorderStyle.THIN);
|
||||
intStyle.setBorderBottom(BorderStyle.THIN);
|
||||
intStyle.setBorderLeft(BorderStyle.THIN);
|
||||
intStyle.setBorderRight(BorderStyle.THIN);
|
||||
|
||||
CellStyle zebraIntStyle = workbook.createCellStyle();
|
||||
zebraIntStyle.cloneStyleFrom(intStyle);
|
||||
zebraIntStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
XSSFColor zebraFill = new XSSFColor(new Color(242, 244, 248), null);
|
||||
((XSSFCellStyle) zebraTextStyle).setFillForegroundColor(zebraFill);
|
||||
((XSSFCellStyle) zebraIntStyle).setFillForegroundColor(zebraFill);
|
||||
|
||||
CellStyle summaryTextStyle = workbook.createCellStyle();
|
||||
summaryTextStyle.cloneStyleFrom(textStyle);
|
||||
summaryTextStyle.setFillForegroundColor(IndexedColors.LEMON_CHIFFON.getIndex());
|
||||
summaryTextStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
Font summaryFont = workbook.createFont();
|
||||
summaryFont.setBold(true);
|
||||
summaryTextStyle.setFont(summaryFont);
|
||||
summaryTextStyle.setBorderTop(BorderStyle.THIN);
|
||||
|
||||
CellStyle summaryIntStyle = workbook.createCellStyle();
|
||||
summaryIntStyle.cloneStyleFrom(intStyle);
|
||||
summaryIntStyle.setFillForegroundColor(IndexedColors.LEMON_CHIFFON.getIndex());
|
||||
summaryIntStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
summaryIntStyle.setFont(summaryFont);
|
||||
summaryIntStyle.setBorderTop(BorderStyle.THIN);
|
||||
|
||||
return new SheetStyles(
|
||||
headerStyle, textStyle, zebraTextStyle, intStyle, zebraIntStyle, summaryTextStyle, summaryIntStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user