导出纳新
This commit is contained in:
@@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -154,6 +155,19 @@ public class LbPurchaseApplyController {
|
|||||||
return ResponseEntity.badRequest().body(result);
|
return ResponseEntity.badRequest().body(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/export")
|
||||||
|
@Operation(summary = "导出进货申请Excel", description = "按租户ID与申请日期范围导出,按申请日分组并合并首列")
|
||||||
|
public void export(
|
||||||
|
@Parameter(description = "申请开始日期(yyyy-MM-dd)", required = true)
|
||||||
|
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate applyDateStart,
|
||||||
|
@Parameter(description = "申请结束日期(yyyy-MM-dd)", required = true)
|
||||||
|
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate applyDateEnd,
|
||||||
|
@Parameter(description = "租户ID", required = true)
|
||||||
|
@RequestParam String tenantId,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
lbPurchaseApplyService.exportExcel(applyDateStart, applyDateEnd, tenantId, response);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/needPrivilegeRecommenders")
|
@GetMapping("/needPrivilegeRecommenders")
|
||||||
@Operation(summary = "按日期范围查询需要添加特权的推荐人")
|
@Operation(summary = "按日期范围查询需要添加特权的推荐人")
|
||||||
public ResponseEntity<Map<String, Object>> needPrivilegeRecommenders(
|
public ResponseEntity<Map<String, Object>> needPrivilegeRecommenders(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.rj.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.rj.entity.LbPurchaseApply;
|
import com.rj.entity.LbPurchaseApply;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -48,4 +49,9 @@ public interface ILbPurchaseApplyService extends IService<LbPurchaseApply> {
|
|||||||
* @param tenantId 当前登录人租户 ID(回填到结果实体,覆盖模型输出)
|
* @param tenantId 当前登录人租户 ID(回填到结果实体,覆盖模型输出)
|
||||||
*/
|
*/
|
||||||
Map<String, Object> parseFromOrderInfoByLlm(String orderInfo, String tenantId);
|
Map<String, Object> parseFromOrderInfoByLlm(String orderInfo, String tenantId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按申请日期区间与租户导出进货申请 Excel(按申请日分组,首列合并单元格)。
|
||||||
|
*/
|
||||||
|
void exportExcel(LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId, HttpServletResponse response);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,23 @@ import com.rj.mapper.LbDailyUserTradeReportMapper;
|
|||||||
import com.rj.mapper.LbPurchaseApplyMapper;
|
import com.rj.mapper.LbPurchaseApplyMapper;
|
||||||
import com.rj.service.HxrAdminUserService;
|
import com.rj.service.HxrAdminUserService;
|
||||||
import com.rj.service.ILbPurchaseApplyService;
|
import com.rj.service.ILbPurchaseApplyService;
|
||||||
|
import jakarta.servlet.ServletOutputStream;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.apache.poi.ss.usermodel.*;
|
||||||
|
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.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -33,6 +45,7 @@ import java.time.LocalDate;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -60,6 +73,8 @@ public class LbPurchaseApplyServiceImpl
|
|||||||
private String dashScopeChatModel;
|
private String dashScopeChatModel;
|
||||||
|
|
||||||
private static final DateTimeFormatter TRY_DATE_MM_DD = DateTimeFormatter.ofPattern("MM.dd");
|
private static final DateTimeFormatter TRY_DATE_MM_DD = DateTimeFormatter.ofPattern("MM.dd");
|
||||||
|
private static final DateTimeFormatter PRIVILEGE_RANGE_FMT = DateTimeFormatter.ofPattern("MM.dd");
|
||||||
|
private static final DateTimeFormatter EXPORT_FILENAME_TS = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
||||||
|
|
||||||
/** 试用期包含的工作日天数(周一至周五),周六日不计入。 */
|
/** 试用期包含的工作日天数(周一至周五),周六日不计入。 */
|
||||||
private static final int TRIAL_WEEKDAY_COUNT = 3;
|
private static final int TRIAL_WEEKDAY_COUNT = 3;
|
||||||
@@ -188,7 +203,7 @@ public class LbPurchaseApplyServiceImpl
|
|||||||
}
|
}
|
||||||
String existingTryDate = entity.getTryDate();
|
String existingTryDate = entity.getTryDate();
|
||||||
LocalDate trialFirstWeekday = firstWeekdayOnOrAfter(applyDate);
|
LocalDate trialFirstWeekday = firstWeekdayOnOrAfter(applyDate);
|
||||||
LocalDate endDate = endOfInclusiveWeekdaySpan(trialFirstWeekday, TRIAL_WEEKDAY_COUNT);
|
LocalDate endDate = endOfInclusiveWeekdaySpan(trialFirstWeekday, TRIAL_WEEKDAY_COUNT, log);
|
||||||
|
|
||||||
String computed =
|
String computed =
|
||||||
applyDate.format(TRY_DATE_MM_DD) + " 到 " + endDate.format(TRY_DATE_MM_DD);
|
applyDate.format(TRY_DATE_MM_DD) + " 到 " + endDate.format(TRY_DATE_MM_DD);
|
||||||
@@ -209,14 +224,14 @@ public class LbPurchaseApplyServiceImpl
|
|||||||
* 从 {@code firstWeekday} 起连续 {@code inclusiveWeekdays} 个工作日(仅周一至周五,含起点当日),返回该段最后一天。
|
* 从 {@code firstWeekday} 起连续 {@code inclusiveWeekdays} 个工作日(仅周一至周五,含起点当日),返回该段最后一天。
|
||||||
* 若起点落在周六日,会先顺延到下一工作日再计数,且返回值保证不为周六日。
|
* 若起点落在周六日,会先顺延到下一工作日再计数,且返回值保证不为周六日。
|
||||||
*/
|
*/
|
||||||
private LocalDate endOfInclusiveWeekdaySpan(LocalDate firstWeekday, int inclusiveWeekdays) {
|
private static LocalDate endOfInclusiveWeekdaySpan(LocalDate firstWeekday, int inclusiveWeekdays, Logger logger) {
|
||||||
if (inclusiveWeekdays < 1) {
|
if (inclusiveWeekdays < 1) {
|
||||||
throw new IllegalArgumentException("inclusiveWeekdays must be >= 1");
|
throw new IllegalArgumentException("inclusiveWeekdays must be >= 1");
|
||||||
}
|
}
|
||||||
LocalDate d = firstWeekday;
|
LocalDate d = firstWeekday;
|
||||||
while (IsoWorkdayUtils.isWeekend(d)) {
|
while (IsoWorkdayUtils.isWeekend(d)) {
|
||||||
if (log.isDebugEnabled()) {
|
if (logger != null && logger.isDebugEnabled()) {
|
||||||
log.debug(
|
logger.debug(
|
||||||
"trialSpan:起点为周末,顺延 cursor={} dow={} isoDow={}",
|
"trialSpan:起点为周末,顺延 cursor={} dow={} isoDow={}",
|
||||||
d,
|
d,
|
||||||
d.getDayOfWeek(),
|
d.getDayOfWeek(),
|
||||||
@@ -228,8 +243,8 @@ public class LbPurchaseApplyServiceImpl
|
|||||||
int guard = 0;
|
int guard = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
boolean weekend = IsoWorkdayUtils.isWeekend(d);
|
boolean weekend = IsoWorkdayUtils.isWeekend(d);
|
||||||
if (log.isDebugEnabled()) {
|
if (logger != null && logger.isDebugEnabled()) {
|
||||||
log.debug(
|
logger.debug(
|
||||||
"trialSpan:cursor={} dow={} isoDow={} weekend={} weekdaysRemaining={}",
|
"trialSpan:cursor={} dow={} isoDow={} weekend={} weekdaysRemaining={}",
|
||||||
d,
|
d,
|
||||||
d.getDayOfWeek(),
|
d.getDayOfWeek(),
|
||||||
@@ -787,4 +802,256 @@ public class LbPurchaseApplyServiceImpl
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exportExcel(LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId, HttpServletResponse response) {
|
||||||
|
try {
|
||||||
|
if (tenantId == null || tenantId.trim().isEmpty()) {
|
||||||
|
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "tenantId不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (applyDateStart == null || applyDateEnd == null) {
|
||||||
|
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "申请开始日期与结束日期不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (applyDateEnd.isBefore(applyDateStart)) {
|
||||||
|
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "结束日期不能早于开始日期");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaQueryWrapper<LbPurchaseApply> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(LbPurchaseApply::getTenantId, tenantId.trim())
|
||||||
|
.ge(LbPurchaseApply::getApplyDate, applyDateStart)
|
||||||
|
.le(LbPurchaseApply::getApplyDate, applyDateEnd)
|
||||||
|
.orderByAsc(LbPurchaseApply::getApplyDate)
|
||||||
|
.orderByAsc(LbPurchaseApply::getId);
|
||||||
|
List<LbPurchaseApply> rows = this.list(queryWrapper);
|
||||||
|
Map<String, Integer> maxOrderByColleaguePhone = loadColleagueMaxOrderCache(rows);
|
||||||
|
|
||||||
|
LinkedHashMap<LocalDate, List<LbPurchaseApply>> grouped = new LinkedHashMap<>();
|
||||||
|
for (LbPurchaseApply row : rows) {
|
||||||
|
LocalDate key = row.getApplyDate();
|
||||||
|
if (key == null) {
|
||||||
|
key = LocalDate.MIN;
|
||||||
|
}
|
||||||
|
grouped.computeIfAbsent(key, k -> new ArrayList<>()).add(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Workbook workbook = new XSSFWorkbook()) {
|
||||||
|
Sheet sheet = workbook.createSheet("进货申请");
|
||||||
|
|
||||||
|
CellStyle headerStyle = createHeaderStyle(workbook);
|
||||||
|
CellStyle groupStyle = createGroupStyle(workbook);
|
||||||
|
CellStyle dataStyle = createDataStyle(workbook);
|
||||||
|
|
||||||
|
String[] headers = {
|
||||||
|
"日期和人数", "序号", "昵称", "手机号", "特权开通日期",
|
||||||
|
"推荐人", "手机号", "领导人", "开通日期"
|
||||||
|
};
|
||||||
|
Row headerRow = sheet.createRow(0);
|
||||||
|
headerRow.setHeightInPoints(22);
|
||||||
|
for (int i = 0; i < headers.length; i++) {
|
||||||
|
createExportCell(headerRow, i, headers[i], headerStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rowIndex = 1;
|
||||||
|
for (Map.Entry<LocalDate, List<LbPurchaseApply>> entry : grouped.entrySet()) {
|
||||||
|
LocalDate applyDate = entry.getKey();
|
||||||
|
List<LbPurchaseApply> groupRows = entry.getValue();
|
||||||
|
int groupStartRow = rowIndex;
|
||||||
|
String groupLabel = formatDatePeopleLabel(applyDate, groupRows.size());
|
||||||
|
|
||||||
|
int serial = 1;
|
||||||
|
for (LbPurchaseApply item : groupRows) {
|
||||||
|
Row row = sheet.createRow(rowIndex);
|
||||||
|
row.setHeightInPoints(20);
|
||||||
|
createExportCell(row, 1, String.valueOf(serial), dataStyle);
|
||||||
|
createExportCell(row, 2, nullToEmpty(item.getApplyUser()), dataStyle);
|
||||||
|
createExportCell(row, 3, nullToEmpty(item.getApplyPhone()), dataStyle);
|
||||||
|
createExportCell(row, 4, formatPrivilegeRange(item), dataStyle);
|
||||||
|
createExportCell(row, 5, formatRecommender(item, maxOrderByColleaguePhone), dataStyle);
|
||||||
|
createExportCell(row, 6, nullToEmpty(item.getColleaguePhone()), dataStyle);
|
||||||
|
createExportCell(row, 7, nullToEmpty(item.getTeamLeader()), dataStyle);
|
||||||
|
createExportCell(row, 8, formatActivationDate(item.getApplyDate()), dataStyle);
|
||||||
|
serial++;
|
||||||
|
rowIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int groupEndRow = rowIndex - 1;
|
||||||
|
Row firstRow = sheet.getRow(groupStartRow);
|
||||||
|
createExportCell(firstRow, 0, groupLabel, groupStyle);
|
||||||
|
if (groupEndRow > groupStartRow) {
|
||||||
|
sheet.addMergedRegion(new CellRangeAddress(groupStartRow, groupEndRow, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adjustExportColumnWidths(sheet, headers);
|
||||||
|
|
||||||
|
String filename = "进货申请_" + LocalDateTime.now().format(EXPORT_FILENAME_TS) + ".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) {
|
||||||
|
log.error("进货申请导出异常", 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 Map<String, Integer> loadColleagueMaxOrderCache(List<LbPurchaseApply> rows) {
|
||||||
|
Map<String, Integer> cache = new HashMap<>();
|
||||||
|
Set<String> phones = new HashSet<>();
|
||||||
|
for (LbPurchaseApply row : rows) {
|
||||||
|
if (row.getColleaguePhone() != null && !row.getColleaguePhone().trim().isEmpty()) {
|
||||||
|
phones.add(row.getColleaguePhone().trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String phone : phones) {
|
||||||
|
try {
|
||||||
|
Optional<HxrUserRow> userOpt = hxrAdminUserService.fetchFirstUserByMobile(phone);
|
||||||
|
userOpt.map(HxrUserRow::maxOrder).ifPresent(maxOrder -> cache.put(phone, maxOrder));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.debug("导出时查询推荐人 max_order 失败,phone={}", phone, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatDatePeopleLabel(LocalDate applyDate, int count) {
|
||||||
|
if (applyDate == null || applyDate.equals(LocalDate.MIN)) {
|
||||||
|
return "未知日期招商" + count + "人";
|
||||||
|
}
|
||||||
|
return applyDate.getMonthValue() + "." + applyDate.getDayOfMonth() + "招商" + count + "人";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatPrivilegeRange(LbPurchaseApply item) {
|
||||||
|
LocalDate applyDate = item.getApplyDate();
|
||||||
|
if (applyDate == null) {
|
||||||
|
return item.getTryDate() != null ? item.getTryDate().trim() : "";
|
||||||
|
}
|
||||||
|
LocalDate start = firstWeekdayOnOrAfter(applyDate);
|
||||||
|
LocalDate endDate = endOfInclusiveWeekdaySpan(start, TRIAL_WEEKDAY_COUNT, null);
|
||||||
|
return start.format(PRIVILEGE_RANGE_FMT) + " 到 " + endDate.format(PRIVILEGE_RANGE_FMT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatRecommender(LbPurchaseApply item, Map<String, Integer> maxOrderByPhone) {
|
||||||
|
String name = item.getColleagueName();
|
||||||
|
if (name == null || name.trim().isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String trimmedName = name.trim();
|
||||||
|
String phone = item.getColleaguePhone() == null ? "" : item.getColleaguePhone().trim();
|
||||||
|
if (!phone.isEmpty()) {
|
||||||
|
Integer maxOrder = maxOrderByPhone.get(phone);
|
||||||
|
if (maxOrder != null) {
|
||||||
|
return trimmedName + " " + maxOrder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return trimmedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatActivationDate(LocalDate applyDate) {
|
||||||
|
if (applyDate == null || applyDate.equals(LocalDate.MIN)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
LocalDate activation = firstWeekdayOnOrAfter(applyDate);
|
||||||
|
return activation.getYear() + "/" + activation.getMonthValue() + "/" + activation.getDayOfMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CellStyle createHeaderStyle(Workbook workbook) {
|
||||||
|
CellStyle style = workbook.createCellStyle();
|
||||||
|
Font font = workbook.createFont();
|
||||||
|
font.setBold(true);
|
||||||
|
style.setFont(font);
|
||||||
|
style.setAlignment(HorizontalAlignment.CENTER);
|
||||||
|
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||||
|
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||||
|
((XSSFCellStyle) style).setFillForegroundColor(new XSSFColor(new Color(255, 217, 102), null));
|
||||||
|
setThinBorders(style);
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CellStyle createGroupStyle(Workbook workbook) {
|
||||||
|
CellStyle style = workbook.createCellStyle();
|
||||||
|
style.setAlignment(HorizontalAlignment.CENTER);
|
||||||
|
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||||
|
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||||
|
((XSSFCellStyle) style).setFillForegroundColor(new XSSFColor(new Color(255, 230, 204), null));
|
||||||
|
setThinBorders(style);
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CellStyle createDataStyle(Workbook workbook) {
|
||||||
|
CellStyle style = workbook.createCellStyle();
|
||||||
|
style.setAlignment(HorizontalAlignment.CENTER);
|
||||||
|
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||||
|
setThinBorders(style);
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setThinBorders(CellStyle style) {
|
||||||
|
style.setBorderTop(BorderStyle.THIN);
|
||||||
|
style.setBorderBottom(BorderStyle.THIN);
|
||||||
|
style.setBorderLeft(BorderStyle.THIN);
|
||||||
|
style.setBorderRight(BorderStyle.THIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createExportCell(Row row, int col, String text, CellStyle style) {
|
||||||
|
Cell cell = row.createCell(col);
|
||||||
|
cell.setCellValue(text == null ? "" : text);
|
||||||
|
cell.setCellStyle(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String nullToEmpty(String value) {
|
||||||
|
return value == null ? "" : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void adjustExportColumnWidths(Sheet sheet, String[] headers) {
|
||||||
|
int columnCount = headers.length;
|
||||||
|
int[] maxWidths = new int[columnCount];
|
||||||
|
for (int i = 0; i < columnCount; i++) {
|
||||||
|
maxWidths[i] = calcExportDisplayWidth(headers[i]);
|
||||||
|
}
|
||||||
|
for (int r = 0; r <= sheet.getLastRowNum(); r++) {
|
||||||
|
Row row = sheet.getRow(r);
|
||||||
|
if (row == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int c = 0; c < columnCount; c++) {
|
||||||
|
Cell cell = row.getCell(c);
|
||||||
|
if (cell != null && cell.getCellType() == CellType.STRING) {
|
||||||
|
maxWidths[c] = Math.max(maxWidths[c], calcExportDisplayWidth(cell.getStringCellValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < columnCount; i++) {
|
||||||
|
int width = Math.min(255 * 256, (maxWidths[i] + 3) * 256);
|
||||||
|
sheet.setColumnWidth(i, width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int calcExportDisplayWidth(String text) {
|
||||||
|
if (text == null || text.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int width = 0;
|
||||||
|
for (char ch : text.toCharArray()) {
|
||||||
|
width += ch > 127 ? 2 : 1;
|
||||||
|
}
|
||||||
|
return width;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user