|
|
|
@ -5,16 +5,25 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|
|
|
import com.zdxt.enforcementcode.domain.bo.EnforcementRegistrationBo; |
|
|
|
import com.zdxt.enforcementcode.domain.vo.report.RegistrationAnalysisVo; |
|
|
|
import com.zdxt.enforcementcode.domain.vo.report.RegistrationStatisticsAnalysisDetailVo; |
|
|
|
import com.zdxt.enforcementcode.domain.vo.report.RegistrationStatisticsAnalysisExportVo; |
|
|
|
import com.zdxt.enforcementcode.mapper.EnforcementRegistrationMapper; |
|
|
|
import com.zdxt.enforcementcode.report.IEnforcementRegistrationStatisticsService; |
|
|
|
import jakarta.servlet.http.HttpServletResponse; |
|
|
|
import lombok.RequiredArgsConstructor; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.apache.poi.ss.usermodel.*; |
|
|
|
import org.apache.poi.ss.util.CellRangeAddress; |
|
|
|
import org.apache.poi.ss.util.RegionUtil; |
|
|
|
import org.apache.poi.xssf.usermodel.XSSFFont; |
|
|
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
|
|
|
import org.dromara.common.mybatis.core.page.PageQuery; |
|
|
|
import org.dromara.common.mybatis.core.page.TableDataInfo; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
|
|
|
|
import java.util.List; |
|
|
|
import java.io.OutputStream; |
|
|
|
import java.net.URLEncoder; |
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
import java.util.*; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
/** |
|
|
|
@ -42,32 +51,347 @@ public class EnforcementRegistrationStatisticsServiceImpl implements IEnforcemen |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public List<RegistrationStatisticsAnalysisExportVo> exportList(EnforcementRegistrationBo bo) { |
|
|
|
// 全量加载(不分页)
|
|
|
|
Page<RegistrationAnalysisVo> page = new Page<>(1, Integer.MAX_VALUE, false); |
|
|
|
IPage<RegistrationAnalysisVo> result = registrationMapper.selectAnalysisPageV2(page, bo, null); |
|
|
|
List<RegistrationAnalysisVo> records = result.getRecords(); |
|
|
|
|
|
|
|
// 转换为导出VO(含颜色分级列)
|
|
|
|
return records.stream().map(vo -> { |
|
|
|
RegistrationStatisticsAnalysisExportVo exportVo = new RegistrationStatisticsAnalysisExportVo(); |
|
|
|
exportVo.setDistrict(vo.getDistrict()); |
|
|
|
exportVo.setStreet(vo.getStreet()); |
|
|
|
exportVo.setEnterpriseName(vo.getEnterpriseName()); |
|
|
|
exportVo.setBureauDeptName(vo.getBureauDeptName()); |
|
|
|
exportVo.setLawEnforcer(vo.getLawEnforcer()); |
|
|
|
exportVo.setLawEnforcementItemText(vo.getLawEnforcementItemText()); |
|
|
|
exportVo.setEnforcementTime(vo.getEnforcementTime()); |
|
|
|
exportVo.setTotalCount(vo.getTotalCount()); |
|
|
|
|
|
|
|
// 颜色分级列
|
|
|
|
int count = vo.getTotalCount() != null ? vo.getTotalCount() : 0; |
|
|
|
exportVo.setLevel2(count <= 2 ? String.valueOf(count) : "-"); |
|
|
|
exportVo.setLevel34(count >= 3 && count <= 4 ? String.valueOf(count) : "-"); |
|
|
|
exportVo.setLevel56(count >= 5 && count <= 6 ? String.valueOf(count) : "-"); |
|
|
|
exportVo.setLevel7plus(count >= 7 ? String.valueOf(count) : "-"); |
|
|
|
|
|
|
|
return exportVo; |
|
|
|
}).collect(Collectors.toList()); |
|
|
|
public void exportExcel(EnforcementRegistrationBo bo, HttpServletResponse response) { |
|
|
|
// 1. 加载全部个体记录(SQL按enterprise_name排序)
|
|
|
|
List<RegistrationAnalysisVo> allRecords = registrationMapper.selectAnalysisExportV2(bo, null); |
|
|
|
|
|
|
|
// 2. 按旧系统方式分组:先按区域分组,区域顺序用字典dict_sort
|
|
|
|
// SQL已联查dict_sort但未返回,这里用LinkedHashMap保持第一次出现的顺序即可
|
|
|
|
// (SQL返回的数据已经按enterprise_name排序,但区域顺序需要在Java层处理)
|
|
|
|
// 获取区域字典排序列表
|
|
|
|
List<String> districtOrder = getDistrictOrder(); |
|
|
|
|
|
|
|
// 按区域分组
|
|
|
|
Map<String, List<RegistrationAnalysisVo>> districtMap = allRecords.stream() |
|
|
|
.collect(Collectors.groupingBy( |
|
|
|
vo -> vo.getDistrict() != null ? vo.getDistrict() : "", |
|
|
|
LinkedHashMap::new, |
|
|
|
Collectors.toList() |
|
|
|
)); |
|
|
|
|
|
|
|
// 按字典顺序重新排列区域
|
|
|
|
List<String> orderedDistricts = new ArrayList<>(); |
|
|
|
for (String d : districtOrder) { |
|
|
|
if (districtMap.containsKey(d)) { |
|
|
|
orderedDistricts.add(d); |
|
|
|
} |
|
|
|
} |
|
|
|
// 加上字典中不存在的区域
|
|
|
|
for (String d : districtMap.keySet()) { |
|
|
|
if (!orderedDistricts.contains(d)) { |
|
|
|
orderedDistricts.add(d); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
try (XSSFWorkbook wb = new XSSFWorkbook()) { |
|
|
|
Sheet sheet = wb.createSheet("行政执法统计"); |
|
|
|
sheet.setColumnWidth(0, 1442); // 序号
|
|
|
|
sheet.setColumnWidth(1, 2256); // 区域
|
|
|
|
sheet.setColumnWidth(2, 10970); // 企业
|
|
|
|
sheet.setColumnWidth(3, 7288); // 执法主体
|
|
|
|
sheet.setColumnWidth(4, 4000); // 执法人员
|
|
|
|
sheet.setColumnWidth(5, 26906); // 执法事项
|
|
|
|
sheet.setColumnWidth(6, 3727); // 执法时间
|
|
|
|
sheet.setColumnWidth(7, 2586); // 执法次数
|
|
|
|
sheet.setColumnWidth(8, 2586); // 2次及以下
|
|
|
|
sheet.setColumnWidth(9, 2586); // 3至4次
|
|
|
|
sheet.setColumnWidth(10, 2586); // 5至6次
|
|
|
|
sheet.setColumnWidth(11, 2586); // 7次及以上
|
|
|
|
sheet.setColumnWidth(12, 2586); // 备注
|
|
|
|
|
|
|
|
// ========== 字体 ==========
|
|
|
|
XSSFFont font1 = wb.createFont(); |
|
|
|
font1.setFontName("微软雅黑"); |
|
|
|
font1.setBold(true); |
|
|
|
font1.setFontHeightInPoints((short) 16); |
|
|
|
|
|
|
|
XSSFFont font2 = wb.createFont(); |
|
|
|
font2.setFontName("微软雅黑"); |
|
|
|
font2.setBold(true); |
|
|
|
font2.setFontHeightInPoints((short) 11); |
|
|
|
|
|
|
|
XSSFFont font3 = wb.createFont(); |
|
|
|
font3.setFontName("微软雅黑"); |
|
|
|
font3.setFontHeightInPoints((short) 11); |
|
|
|
|
|
|
|
// ========== 样式 ==========
|
|
|
|
CellStyle titleStyle = wb.createCellStyle(); |
|
|
|
titleStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); |
|
|
|
titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); |
|
|
|
titleStyle.setWrapText(true); |
|
|
|
titleStyle.setAlignment(HorizontalAlignment.CENTER); |
|
|
|
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER); |
|
|
|
titleStyle.setBorderTop(BorderStyle.THIN); |
|
|
|
titleStyle.setBorderRight(BorderStyle.THIN); |
|
|
|
titleStyle.setBorderBottom(BorderStyle.THIN); |
|
|
|
titleStyle.setBorderLeft(BorderStyle.THIN); |
|
|
|
titleStyle.setFont(font1); |
|
|
|
|
|
|
|
CellStyle headerStyle = wb.createCellStyle(); |
|
|
|
headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); |
|
|
|
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); |
|
|
|
headerStyle.setWrapText(true); |
|
|
|
headerStyle.setAlignment(HorizontalAlignment.CENTER); |
|
|
|
headerStyle.setVerticalAlignment(VerticalAlignment.CENTER); |
|
|
|
headerStyle.setBorderTop(BorderStyle.THIN); |
|
|
|
headerStyle.setBorderRight(BorderStyle.THIN); |
|
|
|
headerStyle.setBorderBottom(BorderStyle.THIN); |
|
|
|
headerStyle.setBorderLeft(BorderStyle.THIN); |
|
|
|
headerStyle.setFont(font2); |
|
|
|
|
|
|
|
CellStyle contentStyle = wb.createCellStyle(); |
|
|
|
contentStyle.setWrapText(true); |
|
|
|
contentStyle.setAlignment(HorizontalAlignment.CENTER); |
|
|
|
contentStyle.setVerticalAlignment(VerticalAlignment.CENTER); |
|
|
|
contentStyle.setBorderTop(BorderStyle.THIN); |
|
|
|
contentStyle.setBorderRight(BorderStyle.THIN); |
|
|
|
contentStyle.setBorderBottom(BorderStyle.THIN); |
|
|
|
contentStyle.setBorderLeft(BorderStyle.THIN); |
|
|
|
contentStyle.setFont(font3); |
|
|
|
|
|
|
|
// ========== 第一行:标题 ==========
|
|
|
|
Row row0 = sheet.createRow(0); |
|
|
|
row0.setHeightInPoints(60); |
|
|
|
Cell titleCell = row0.createCell(0); |
|
|
|
String beginDate = formatDateCN(bo.getBeginTime()); |
|
|
|
String endDate = formatDateCN(bo.getEndTime()); |
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 H时mm分"); |
|
|
|
String nowStr = sdf.format(new Date()); |
|
|
|
String titleText = "深圳市涉企行政登记情况\n(统计范围:" + beginDate + "至" + endDate + " 统计时间:" + nowStr + ")"; |
|
|
|
titleCell.setCellValue(titleText); |
|
|
|
titleCell.setCellStyle(titleStyle); |
|
|
|
for (int i = 1; i <= 12; i++) { |
|
|
|
Cell c = row0.createCell(i); |
|
|
|
c.setCellStyle(titleStyle); |
|
|
|
} |
|
|
|
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 12)); |
|
|
|
|
|
|
|
// ========== 第二行:表头 ==========
|
|
|
|
Row row1 = sheet.createRow(1); |
|
|
|
String[] headers = {"序号", "区域", "企业", "执法主体", "执法人员", "执法事项", "执法时间", "执法次数", |
|
|
|
"2次及以下", "3至4次", "5至6次", "7次及以上", "备注"}; |
|
|
|
for (int i = 0; i < headers.length; i++) { |
|
|
|
Cell cell = row1.createCell(i); |
|
|
|
cell.setCellValue(headers[i]); |
|
|
|
cell.setCellStyle(headerStyle); |
|
|
|
} |
|
|
|
|
|
|
|
// ========== 数据行:按旧系统层级分组写入 ==========
|
|
|
|
int rowNum = 1; |
|
|
|
|
|
|
|
for (int distIdx = 0; distIdx < orderedDistricts.size(); distIdx++) { |
|
|
|
String area = orderedDistricts.get(distIdx); |
|
|
|
List<RegistrationAnalysisVo> distRecords = districtMap.get(area); |
|
|
|
if (distRecords == null || distRecords.isEmpty()) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
int districtStartRow = rowNum + 1; |
|
|
|
|
|
|
|
// 按企业分组(HashMap,哈希顺序)
|
|
|
|
Map<String, List<RegistrationAnalysisVo>> qyGroup = new HashMap<>(); |
|
|
|
for (RegistrationAnalysisVo vo : distRecords) { |
|
|
|
String key = vo.getEnterpriseNumber() != null ? vo.getEnterpriseNumber() : ""; |
|
|
|
qyGroup.computeIfAbsent(key, k -> new ArrayList<>()).add(vo); |
|
|
|
} |
|
|
|
|
|
|
|
for (String enterpriseNum : qyGroup.keySet()) { |
|
|
|
List<RegistrationAnalysisVo> qyRecords = qyGroup.get(enterpriseNum); |
|
|
|
long qyCount = qyRecords.size(); // 企业总执法次数
|
|
|
|
int qyStartRow = rowNum + 1; |
|
|
|
|
|
|
|
// 按执法主体分组(HashMap)
|
|
|
|
Map<String, List<RegistrationAnalysisVo>> zfGroup = new HashMap<>(); |
|
|
|
for (RegistrationAnalysisVo vo : qyRecords) { |
|
|
|
String key = vo.getBureauDeptId() != null ? vo.getBureauDeptId() : ""; |
|
|
|
zfGroup.computeIfAbsent(key, k -> new ArrayList<>()).add(vo); |
|
|
|
} |
|
|
|
|
|
|
|
for (String bureauId : zfGroup.keySet()) { |
|
|
|
List<RegistrationAnalysisVo> zfRecords = zfGroup.get(bureauId); |
|
|
|
int zfStartRow = rowNum + 1; |
|
|
|
|
|
|
|
// 按执法人员分组(HashMap)
|
|
|
|
Map<String, List<RegistrationAnalysisVo>> ryGroup = new HashMap<>(); |
|
|
|
for (RegistrationAnalysisVo vo : zfRecords) { |
|
|
|
String key = vo.getLawEnforcer() != null ? vo.getLawEnforcer() : ""; |
|
|
|
ryGroup.computeIfAbsent(key, k -> new ArrayList<>()).add(vo); |
|
|
|
} |
|
|
|
|
|
|
|
for (String enforcer : ryGroup.keySet()) { |
|
|
|
List<RegistrationAnalysisVo> ryRecords = ryGroup.get(enforcer); |
|
|
|
int ryStartRow = rowNum + 1; |
|
|
|
|
|
|
|
// 按执法事项分组(HashMap)
|
|
|
|
Map<String, List<RegistrationAnalysisVo>> sxGroup = new HashMap<>(); |
|
|
|
for (RegistrationAnalysisVo vo : ryRecords) { |
|
|
|
String key = vo.getLawEnforcementItemText() != null ? vo.getLawEnforcementItemText() : ""; |
|
|
|
sxGroup.computeIfAbsent(key, k -> new ArrayList<>()).add(vo); |
|
|
|
} |
|
|
|
|
|
|
|
for (String item : sxGroup.keySet()) { |
|
|
|
List<RegistrationAnalysisVo> sxRecords = sxGroup.get(item); |
|
|
|
int sxStartRow = rowNum + 1; |
|
|
|
|
|
|
|
// 写入每条记录
|
|
|
|
for (int s = 0; s < sxRecords.size(); s++) { |
|
|
|
RegistrationAnalysisVo vo = sxRecords.get(s); |
|
|
|
rowNum++; |
|
|
|
Row dataRow = sheet.createRow(rowNum); |
|
|
|
setCellValue(dataRow, 0, String.valueOf(distIdx + 1), contentStyle); |
|
|
|
setCellValue(dataRow, 1, area, contentStyle); |
|
|
|
setCellValue(dataRow, 2, vo.getEnterpriseName(), contentStyle); |
|
|
|
setCellValue(dataRow, 3, vo.getBureauDeptName(), contentStyle); |
|
|
|
setCellValue(dataRow, 4, vo.getLawEnforcer(), contentStyle); |
|
|
|
setCellValue(dataRow, 5, vo.getLawEnforcementItemText(), contentStyle); |
|
|
|
setCellValue(dataRow, 6, vo.getEnforcementTime(), contentStyle); |
|
|
|
// 执法次数:第一行写sxCount,其他行留空(后续合并)
|
|
|
|
if (s == 0) { |
|
|
|
setCellNumericValue(dataRow, 7, (int) sxRecords.size(), contentStyle); |
|
|
|
} else { |
|
|
|
setCellValue(dataRow, 7, "", contentStyle); |
|
|
|
} |
|
|
|
// 颜色分级列:仅第一行写企业总数(后续在企业层合并)
|
|
|
|
if (s == 0 && sxStartRow == qyStartRow) { |
|
|
|
writeColorColumns(dataRow, qyCount, contentStyle); |
|
|
|
} else { |
|
|
|
setCellValue(dataRow, 8, "", contentStyle); |
|
|
|
setCellValue(dataRow, 9, "", contentStyle); |
|
|
|
setCellValue(dataRow, 10, "", contentStyle); |
|
|
|
setCellValue(dataRow, 11, "", contentStyle); |
|
|
|
} |
|
|
|
setCellValue(dataRow, 12, vo.getRemark() != null ? vo.getRemark() : "", contentStyle); |
|
|
|
} |
|
|
|
|
|
|
|
// 合并执法事项列(col5)和执法次数列(col7)
|
|
|
|
if (sxRecords.size() > 1) { |
|
|
|
mergeAndSetBorder(sheet, sxStartRow, rowNum, 5, 5); |
|
|
|
mergeAndSetBorder(sheet, sxStartRow, rowNum, 7, 7); |
|
|
|
} |
|
|
|
} |
|
|
|
// 合并执法人员列(col4)
|
|
|
|
if (rowNum >= ryStartRow && ryRecords.size() > 1) { |
|
|
|
mergeAndSetBorder(sheet, ryStartRow, rowNum, 4, 4); |
|
|
|
} |
|
|
|
} |
|
|
|
// 合并执法主体列(col3)
|
|
|
|
if (rowNum >= zfStartRow && zfRecords.size() > 1) { |
|
|
|
mergeAndSetBorder(sheet, zfStartRow, rowNum, 3, 3); |
|
|
|
} |
|
|
|
} |
|
|
|
// 合并企业列(col2)和颜色分级列(col8-11)
|
|
|
|
if (rowNum >= qyStartRow && qyCount > 1) { |
|
|
|
mergeAndSetBorder(sheet, qyStartRow, rowNum, 2, 2); |
|
|
|
mergeAndSetBorder(sheet, qyStartRow, rowNum, 8, 8); |
|
|
|
mergeAndSetBorder(sheet, qyStartRow, rowNum, 9, 9); |
|
|
|
mergeAndSetBorder(sheet, qyStartRow, rowNum, 10, 10); |
|
|
|
mergeAndSetBorder(sheet, qyStartRow, rowNum, 11, 11); |
|
|
|
} |
|
|
|
} |
|
|
|
// 合并序号列(col0)和区域列(col1)
|
|
|
|
if (rowNum >= districtStartRow && rowNum > districtStartRow) { |
|
|
|
mergeAndSetBorder(sheet, districtStartRow, rowNum, 0, 0); |
|
|
|
mergeAndSetBorder(sheet, districtStartRow, rowNum, 1, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// ========== 输出响应 ==========
|
|
|
|
String fileName = "深圳市涉企行政登记情况(" + beginDate + "至" + endDate + ").xlsx"; |
|
|
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"); |
|
|
|
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8)); |
|
|
|
OutputStream os = response.getOutputStream(); |
|
|
|
wb.write(os); |
|
|
|
os.flush(); |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("导出执法分析Excel异常", e); |
|
|
|
throw new RuntimeException("导出Excel失败: " + e.getMessage()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取区域字典排序列表(按dict_sort升序) |
|
|
|
*/ |
|
|
|
private List<String> getDistrictOrder() { |
|
|
|
// 旧系统固定顺序,与 address_type 字典 dict_sort 一致
|
|
|
|
return Arrays.asList("福田区", "罗湖区", "盐田区", "南山区", "宝安区", "龙岗区", "龙华区", |
|
|
|
"坪山区", "光明区", "大鹏新区", "深汕特别合作区"); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 写入颜色分级列(col8-11) |
|
|
|
*/ |
|
|
|
private void writeColorColumns(Row row, long qyCount, CellStyle style) { |
|
|
|
if (qyCount <= 2) { |
|
|
|
setCellNumericValue(row, 8, (int) qyCount, style); |
|
|
|
setCellValue(row, 9, "", style); |
|
|
|
setCellValue(row, 10, "", style); |
|
|
|
setCellValue(row, 11, "", style); |
|
|
|
} else if (qyCount <= 4) { |
|
|
|
setCellValue(row, 8, "", style); |
|
|
|
setCellNumericValue(row, 9, (int) qyCount, style); |
|
|
|
setCellValue(row, 10, "", style); |
|
|
|
setCellValue(row, 11, "", style); |
|
|
|
} else if (qyCount <= 6) { |
|
|
|
setCellValue(row, 8, "", style); |
|
|
|
setCellValue(row, 9, "", style); |
|
|
|
setCellNumericValue(row, 10, (int) qyCount, style); |
|
|
|
setCellValue(row, 11, "", style); |
|
|
|
} else { |
|
|
|
setCellValue(row, 8, "", style); |
|
|
|
setCellValue(row, 9, "", style); |
|
|
|
setCellValue(row, 10, "", style); |
|
|
|
setCellNumericValue(row, 11, (int) qyCount, style); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// ========== 工具方法 ==========
|
|
|
|
|
|
|
|
/** |
|
|
|
* 格式化日期为中文(如 2026-01-01 → 1月1日) |
|
|
|
*/ |
|
|
|
private String formatDateCN(String dateStr) { |
|
|
|
if (dateStr == null || dateStr.isEmpty()) { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
String[] parts = dateStr.split("-"); |
|
|
|
if (parts.length == 3) { |
|
|
|
return Integer.parseInt(parts[1]) + "月" + Integer.parseInt(parts[2]) + "日"; |
|
|
|
} |
|
|
|
return dateStr; |
|
|
|
} |
|
|
|
|
|
|
|
private void setCellValue(Row row, int col, String value, CellStyle style) { |
|
|
|
Cell cell = row.createCell(col); |
|
|
|
cell.setCellValue(value != null ? value : ""); |
|
|
|
cell.setCellStyle(style); |
|
|
|
} |
|
|
|
|
|
|
|
private void setCellValue(Row row, int col, int value, CellStyle style) { |
|
|
|
Cell cell = row.createCell(col); |
|
|
|
cell.setCellValue(value); |
|
|
|
cell.setCellStyle(style); |
|
|
|
} |
|
|
|
|
|
|
|
private void setCellNumericValue(Row row, int col, int value, CellStyle style) { |
|
|
|
Cell cell = row.createCell(col); |
|
|
|
if (value > 0) { |
|
|
|
cell.setCellValue(value); |
|
|
|
} |
|
|
|
cell.setCellStyle(style); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 合并单元格并修正边框样式 |
|
|
|
*/ |
|
|
|
private void mergeAndSetBorder(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) { |
|
|
|
if (firstRow >= lastRow) { |
|
|
|
return; |
|
|
|
} |
|
|
|
CellRangeAddress region = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol); |
|
|
|
sheet.addMergedRegion(region); |
|
|
|
RegionUtil.setBorderTop(BorderStyle.THIN, region, sheet); |
|
|
|
RegionUtil.setBorderBottom(BorderStyle.THIN, region, sheet); |
|
|
|
RegionUtil.setBorderLeft(BorderStyle.THIN, region, sheet); |
|
|
|
RegionUtil.setBorderRight(BorderStyle.THIN, region, sheet); |
|
|
|
} |
|
|
|
} |
|
|
|
|