@ -7,7 +7,6 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.PhoneUtil ;
import cn.hutool.core.util.RandomUtil ;
import cn.hutool.json.JSONUtil ;
import com.alibaba.excel.ExcelWriter ;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper ;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper ;
import com.baomidou.mybatisplus.core.toolkit.Wrappers ;
@ -17,9 +16,6 @@ import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine ;
import jakarta.annotation.Resource ;
import lombok.extern.slf4j.Slf4j ;
import org.apache.poi.ss.usermodel.* ;
import org.apache.poi.ss.util.CellRangeAddress ;
import org.apache.poi.xssf.usermodel.XSSFWorkbook ;
import org.dromara.bigscreen.domain.dto.ProjectUpdateDto ;
import org.dromara.bigscreen.domain.dto.TanchuangInfoReq ;
import org.dromara.bigscreen.domain.vo.MilestoneVo ;
@ -78,9 +74,6 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service ;
import org.springframework.transaction.annotation.Transactional ;
import java.io.File ;
import java.io.FileOutputStream ;
import java.io.IOException ;
import java.math.BigDecimal ;
import java.time.LocalDate ;
import java.util.* ;
@ -176,6 +169,7 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
@Resource
private IPgsConstructionSchedulePlanService constructionSchedulePlanService ;
private final Cache < String , String > WEATHER_CACHE =
Caffeine . newBuilder ( ) . initialCapacity ( 1024 )
. maximumSize ( 10000L )
@ -1686,925 +1680,6 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
return vo ;
}
/**
* 测试生成Excel模板
*/
public String testExcel ( ) {
// 生成Excel模板文件
String outputFilePath = " C: \\ Users \\ Administrator \\ Desktop \\ 周报模板.xlsx " ;
try {
generateWeeklyReportTemplate ( outputFilePath ) ;
System . out . println ( " Excel模板生成完成! 文件路径: " + outputFilePath ) ;
} catch ( Exception e ) {
System . err . println ( " Excel模板生成失败: " + e . getMessage ( ) ) ;
e . printStackTrace ( ) ;
}
return outputFilePath ;
}
/**
* 生成项目周报Excel模板( 完整实现, 匹配示例Excel结构)
* @param outputFilePath 输出文件路径
* @throws Exception 异常抛出
*/
public static void generateWeeklyReportTemplate ( String outputFilePath ) throws Exception {
ExcelWriter excelWriter = null ;
FileOutputStream outputStream = null ;
try {
// 1. 预处理:删除已存在的文件
File targetFile = new File ( outputFilePath ) ;
if ( targetFile . exists ( ) ) {
if ( ! targetFile . delete ( ) ) {
throw new IOException ( " 无法删除旧文件,请检查文件权限: " + outputFilePath ) ;
}
}
// 2. 使用POI直接创建复杂格式( 不再使用EasyExcel混合模式)
Workbook workbook = new XSSFWorkbook ( ) ;
Sheet sheet = workbook . createSheet ( " 9.13 " ) ;
// 3. 构建完整模板结构
setupSheetBasicStyle ( sheet ) ; // 设置基础样式
buildTemplateFullStructure ( sheet , workbook ) ; // 创建所有内容
setKeyRowHeights ( sheet ) ; // 设置行高
// 4. 写入最终文件
outputStream = new FileOutputStream ( targetFile ) ;
workbook . write ( outputStream ) ;
outputStream . flush ( ) ;
// 5. 关闭资源
workbook . close ( ) ;
System . out . println ( " 项目周报模板生成完成: " + outputFilePath ) ;
} catch ( Exception e ) {
// 异常恢复:删除可能损坏的文件
File targetFile = new File ( outputFilePath ) ;
if ( targetFile . exists ( ) ) {
targetFile . delete ( ) ;
System . err . println ( " 异常时已清理损坏文件 " ) ;
}
throw new Exception ( " 模板生成流程失败: " + e . getMessage ( ) , e ) ;
} finally {
if ( outputStream ! = null ) {
try {
outputStream . close ( ) ;
} catch ( IOException e ) {
System . err . println ( " 输出流关闭异常: " + e . getMessage ( ) ) ;
}
}
}
}
/**
* 设置工作表基础样式
*/
private static void setupSheetBasicStyle ( Sheet sheet ) {
// 设置列宽( 根据示例Excel调整)
int [ ] columnWidths = { 8 , 18 , 35 , 15 , 8 , 12 , 12 , 12 , 12 , 12 , 12 , 20 } ;
for ( int i = 0 ; i < columnWidths . length ; i + + ) {
sheet . setColumnWidth ( i , columnWidths [ i ] * 256 ) ;
}
sheet . setDefaultRowHeightInPoints ( 20f ) ;
}
/**
* 构建模板完整结构(添加自动调整行高)
*/
private static void buildTemplateFullStructure ( Sheet sheet , Workbook workbook ) {
// 创建所有需要的样式
CellStyle titleStyle = createTitleCellStyle ( workbook ) ;
CellStyle headerStyle = createHeaderCellStyle ( workbook ) ;
CellStyle contentStyle = createContentCellStyle ( workbook ) ;
CellStyle tableHeaderStyle = createTableHeaderCellStyle ( workbook ) ;
// 1. 标题行( 第1行) - 合并第1-2行
createTitleRow ( sheet , titleStyle ) ;
// 2. 关键修复:在创建任何内容之前,先设置所有小范围的合并区域
setupAllSmallMergeRegions ( sheet ) ;
// 3. 项目信息行( 第3行) - A,B列合并
createProjectInfoRow ( sheet , headerStyle , contentStyle ) ;
// 4. 主表头行( 第4行)
createMainHeaderRow ( sheet , headerStyle , contentStyle ) ;
// 5. 项目基本信息模块( 第5-6行) - 修正合并区域
createProjectBasicInfoModule ( sheet , workbook , 4 , headerStyle , contentStyle ) ;
// 6. 本周进度模块( 第7行) - 调整行高
createWeeklyProgressModule ( sheet , workbook , 6 , headerStyle , contentStyle ) ;
// 7. 下周计划模块( 第8行)
createNextWeekPlanModule ( sheet , workbook , 7 , headerStyle , contentStyle ) ;
// 8. 质量情况模块( 第9行) - 调整行高
createQualityStatusModule ( sheet , workbook , 8 , headerStyle , contentStyle ) ;
// 9. 人员设备模块( 第10行) - 合并F-L列
createPersonnelEquipmentModule ( sheet , workbook , 9 , headerStyle , contentStyle ) ;
// 10. 施工进度统计表( 第11-18行) - 修正为7行数据
createConstructionProgressTable ( sheet , workbook , 10 , headerStyle , contentStyle , tableHeaderStyle ) ;
// 11. 设备材料表格( 第19-23行) - 修正表头结构
createEquipmentMaterialTable ( sheet , workbook , 18 , headerStyle , contentStyle , tableHeaderStyle ) ;
// 12. 存在问题模块( 第24行)
createProblemsModule ( sheet , workbook , 23 , headerStyle , contentStyle ) ;
// 13. 照片模块( 第25行)
createPhotoModule ( sheet , workbook , 24 , headerStyle , contentStyle ) ;
// 14. 填报审核模块( 第26行)
createApprovalModule ( sheet , workbook , 25 , headerStyle , contentStyle ) ;
// 15. 确保所有单元格都有边框
ensureAllCellsHaveBorders ( sheet , workbook ) ;
// 16. 自动调整行高以适应内容
autoAdjustRowHeights ( sheet ) ;
}
/**
* 创建标题行( 第1行) - 合并第1-2行
*/
private static void createTitleRow ( Sheet sheet , CellStyle titleStyle ) {
// 第1行
Row titleRow1 = sheet . createRow ( 0 ) ;
titleRow1 . setHeightInPoints ( 25 ) ;
Cell titleCell1 = titleRow1 . createCell ( 0 ) ;
titleCell1 . setCellValue ( " 田东县乡村振兴分布式光伏发电项目周报 " ) ;
titleCell1 . setCellStyle ( titleStyle ) ;
// 第2行( 空行, 但需要边框)
Row titleRow2 = sheet . createRow ( 1 ) ;
titleRow2 . setHeightInPoints ( 15 ) ;
for ( int i = 0 ; i < 12 ; i + + ) {
Cell cell = titleRow2 . createCell ( i ) ;
cell . setCellStyle ( createEmptyCellStyle ( sheet . getWorkbook ( ) ) ) ;
}
// 合并第1-2行
addMergedRegionSafe ( sheet , 0 , 1 , 0 , 11 ) ;
}
/**
* 项目信息行( 第3行) - 修正合并区域
*/
private static void createProjectInfoRow ( Sheet sheet , CellStyle headerStyle , CellStyle contentStyle ) {
Row infoRow = sheet . getRow ( 2 ) ;
// A3:B3合并( 项目名称标签)
Cell nameLabelCell = infoRow . createCell ( 0 ) ;
nameLabelCell . setCellValue ( " 项目名称: " ) ;
nameLabelCell . setCellStyle ( headerStyle ) ;
// 项目名称内容
Cell projectNameCell = infoRow . createCell ( 2 ) ;
projectNameCell . setCellValue ( " 田东县乡村振兴分布式光伏发电项目(一、二期) " ) ;
projectNameCell . setCellStyle ( contentStyle ) ;
// 周报期数
Cell reportNoLabel = infoRow . createCell ( 7 ) ;
reportNoLabel . setCellValue ( " 周报期数 " ) ;
reportNoLabel . setCellStyle ( headerStyle ) ;
Cell reportNoValue = infoRow . createCell ( 8 ) ;
reportNoValue . setCellValue ( " 34 " ) ;
reportNoValue . setCellStyle ( contentStyle ) ;
// 日期 - K3:L4合并
Cell dateLabel = infoRow . createCell ( 9 ) ;
dateLabel . setCellValue ( " 日期: " ) ;
dateLabel . setCellStyle ( headerStyle ) ;
Cell dateValue = infoRow . createCell ( 10 ) ;
dateValue . setCellValue ( " 45955 " ) ;
dateValue . setCellStyle ( contentStyle ) ;
}
/**
* 创建主表头行( 第4行) - 修复重叠问题
*/
private static void createMainHeaderRow ( Sheet sheet , CellStyle headerStyle , CellStyle contentStyle ) {
Row headerRow = sheet . createRow ( 3 ) ;
Cell seqHeader = headerRow . createCell ( 0 ) ;
seqHeader . setCellValue ( " 序号 " ) ;
seqHeader . setCellStyle ( headerStyle ) ;
Cell contentHeader = headerRow . createCell ( 1 ) ;
contentHeader . setCellValue ( " 工程实施主要情况 " ) ;
contentHeader . setCellStyle ( headerStyle ) ;
// 关键修复: B4:I4合并已经在setupAllSmallMergeRegions中设置, 这里不再重复设置
// 只设置单元格内容,不设置合并区域
// J4和K4单独设置( 不合并)
Cell emptyJ4 = headerRow . createCell ( 9 ) ;
emptyJ4 . setCellValue ( " " ) ; // 设置空值
emptyJ4 . setCellStyle ( contentStyle ) ;
Cell emptyK4 = headerRow . createCell ( 10 ) ;
emptyK4 . setCellValue ( " " ) ; // 设置空值
emptyK4 . setCellStyle ( contentStyle ) ;
// L4单元格
Cell emptyL4 = headerRow . createCell ( 11 ) ;
emptyL4 . setCellStyle ( contentStyle ) ;
}
/**
* 项目基本信息模块( 第5-6行) - 修正合并区域
*/
private static void createProjectBasicInfoModule ( Sheet sheet , Workbook workbook , int startRow ,
CellStyle headerStyle , CellStyle contentStyle ) {
Row row1 = sheet . createRow ( startRow ) ;
Row row2 = sheet . createRow ( startRow + 1 ) ;
// A5:A6合并( 序号1)
Cell seqCell = row1 . createCell ( 0 ) ;
seqCell . setCellValue ( " 1 " ) ;
seqCell . setCellStyle ( headerStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow + 1 , 0 , 0 ) ;
// B5:B6合并( 项目基本信息)
Cell titleCell = row1 . createCell ( 1 ) ;
titleCell . setCellValue ( " 项目基本信息 " ) ;
titleCell . setCellStyle ( headerStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow + 1 , 1 , 1 ) ;
// C5:C6合并( 备案容量/设计容量)
Cell capacityCell = row1 . createCell ( 2 ) ;
capacityCell . setCellValue ( " 备案容量: \ n设计容量: " ) ;
capacityCell . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow + 1 , 2 , 2 ) ;
// D5:E6合并( 开工日期)
Cell startDateCell = row1 . createCell ( 3 ) ;
startDateCell . setCellValue ( " 开工日期: 2025.3.19 " ) ;
startDateCell . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow + 1 , 3 , 4 ) ;
// F5:H6合并( 计划并网日期) - 修正: 第5-6行F-H列合并
Cell gridDateCell = row1 . createCell ( 5 ) ;
gridDateCell . setCellValue ( " 计划并网日期: 2025.12.30 " ) ;
gridDateCell . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow + 1 , 5 , 7 ) ;
// I5:I6合并( 总进度完成)
Cell progressCell = row1 . createCell ( 8 ) ;
progressCell . setCellValue ( " 总进度完成: " ) ;
progressCell . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow + 1 , 8 , 8 ) ;
// J5:L6合并( 空) - 修正: J5-L6合并
Cell emptyJK = row1 . createCell ( 9 ) ;
emptyJK . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow + 1 , 9 , 11 ) ;
}
/**
* 本周进度模块( 第7行)
*/
private static void createWeeklyProgressModule ( Sheet sheet , Workbook workbook , int startRow ,
CellStyle headerStyle , CellStyle contentStyle ) {
Row progressRow = sheet . createRow ( startRow ) ;
progressRow . setHeightInPoints ( 60 ) ;
Cell seqCell = progressRow . createCell ( 0 ) ;
seqCell . setCellValue ( " 2 " ) ;
seqCell . setCellStyle ( headerStyle ) ;
Cell titleCell = progressRow . createCell ( 1 ) ;
titleCell . setCellValue ( " 本周完成主要形象进度 " ) ;
titleCell . setCellStyle ( headerStyle ) ;
Cell contentCell = progressRow . createCell ( 2 ) ;
contentCell . setCellValue ( " 本周有1天因下雨全部停工; \ n " +
" 本周完成量: 清表0亩, 累计完成4104亩; 钻孔4875个, 累计完成119985个, 灌注桩浇筑3955个, 累计完成104434个桩, 安装支架644组, 累计完成6412组, 安装光伏组件409组, 累计完成4902组; \ n " +
" 直流电缆电池至逆变器电缆 H1Z2Z2-k-1× 4mm2约10km, 累计完成55km; 1× 6mm2约10km, 累计完成32km; 接地扁钢40*4约2km, 累计完成7km; 50*5约1km, 累计完成4km; 接地角钢100根, 累计完成250根; 场区道路改扩建10%, 累计30%。 " ) ;
contentCell . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow , 2 , 11 ) ;
}
/**
* 修正其他模块的行号(去掉空行后)
*/
private static void createNextWeekPlanModule ( Sheet sheet , Workbook workbook , int startRow ,
CellStyle headerStyle , CellStyle contentStyle ) {
Row planRow = sheet . createRow ( startRow ) ;
Cell seqCell = planRow . createCell ( 0 ) ;
seqCell . setCellValue ( " 3 " ) ;
seqCell . setCellStyle ( headerStyle ) ;
Cell titleCell = planRow . createCell ( 1 ) ;
titleCell . setCellValue ( " 下周计划主要形象进度 " ) ;
titleCell . setCellStyle ( headerStyle ) ;
Cell contentCell = planRow . createCell ( 2 ) ;
contentCell . setCellValue ( " 继续钻孔、安装钢筋笼、浇筑混凝土、支架安装、光伏组件安装、接地扁铁安装、电缆沟开挖等工作。 " ) ;
contentCell . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow , 2 , 11 ) ;
}
private static void createQualityStatusModule ( Sheet sheet , Workbook workbook , int startRow ,
CellStyle headerStyle , CellStyle contentStyle ) {
Row qualityRow = sheet . createRow ( startRow ) ;
Cell seqCell = qualityRow . createCell ( 0 ) ;
seqCell . setCellValue ( " 4 " ) ;
seqCell . setCellStyle ( headerStyle ) ;
Cell titleCell = qualityRow . createCell ( 1 ) ;
titleCell . setCellValue ( " 质量(施工质量、设备材料到货验收)情况 " ) ;
titleCell . setCellStyle ( headerStyle ) ;
Cell contentCell = qualityRow . createCell ( 2 ) ;
contentCell . setCellValue ( " 1、三工区基础浇筑时未严格按照技术交底施工, 造成部分基础拆模后有蜂窝麻面产生; \ n " +
" 2、四工区部分接地电缆沟开挖深度未达到设计值; \ n " +
" 3、二工区部分支架安装区域柱间拉条未按设计长度使用; \ n " +
" 以上问题已经现场对班组提出整改意见,班组已经按照要求全部整改完成并经过项目部管理人员复核。 " ) ;
contentCell . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow , 2 , 11 ) ;
}
/**
* 人员设备模块( 第10行) - 恢复原来的合并范围
*/
private static void createPersonnelEquipmentModule ( Sheet sheet , Workbook workbook , int startRow ,
CellStyle headerStyle , CellStyle contentStyle ) {
Row personnelRow = sheet . createRow ( startRow ) ;
personnelRow . setHeightInPoints ( 25 ) ;
Cell seqCell = personnelRow . createCell ( 0 ) ;
seqCell . setCellValue ( " 5 " ) ;
seqCell . setCellStyle ( headerStyle ) ;
Cell titleCell = personnelRow . createCell ( 1 ) ;
titleCell . setCellValue ( " 人员到位情况及施工器具 " ) ;
titleCell . setCellStyle ( headerStyle ) ;
Cell contentCell = personnelRow . createCell ( 2 ) ;
contentCell . setCellValue ( " 本周施工人员633人, 共投入光伏钻机21台, 小蜜蜂钻机6台, 履带式潜孔钻机4台, 柴油发动空压机6台, 无人机18台, 汽油发动振捣棒20台, 小型电动工具一批。 " ) ;
contentCell . setCellStyle ( contentStyle ) ;
// 恢复原来的合并范围: C-L列
addMergedRegionSafe ( sheet , startRow , startRow , 2 , 11 ) ;
}
/**
* 施工进度统计表( 第11-18行) - 修正数据赋值问题
*/
private static void createConstructionProgressTable ( Sheet sheet , Workbook workbook , int startRow ,
CellStyle headerStyle , CellStyle contentStyle ,
CellStyle tableHeaderStyle ) {
// 表头行( 第11行)
Row headerRow = sheet . createRow ( startRow ) ;
// A11与A12:A18合并, 内容为6
Cell a11Cell = headerRow . createCell ( 0 ) ;
a11Cell . setCellValue ( " 6 " ) ;
a11Cell . setCellStyle ( headerStyle ) ;
// B11与B12:B18合并
Cell b11Cell = headerRow . createCell ( 1 ) ;
b11Cell . setCellValue ( " 施工进度(根据项目类型及进度情况自行分项,不用太细,能体现整体进度即可) " ) ;
b11Cell . setCellStyle ( headerStyle ) ;
// C11内容为: 名称
Cell c11Cell = headerRow . createCell ( 2 ) ;
c11Cell . setCellValue ( " 名称 " ) ;
c11Cell . setCellStyle ( tableHeaderStyle ) ;
// 其他表头 - 从D列开始
String [ ] headers = { " 位置 " , " 单位 " , " 设计数量 " , " 本周完成量 " , " 累计完成量 " , " 累计完成率 " } ;
for ( int i = 0 ; i < headers . length ; i + + ) {
Cell cell = headerRow . createCell ( i + 3 ) ; // D列开始
cell . setCellValue ( headers [ i ] ) ;
cell . setCellStyle ( tableHeaderStyle ) ;
}
// J11:K11合并, 内容为: 下周计划完成
Cell j11Cell = headerRow . createCell ( 9 ) ;
j11Cell . setCellValue ( " 下周计划完成 " ) ;
j11Cell . setCellStyle ( tableHeaderStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow , 9 , 10 ) ;
// L11内容为: 备注, 背景颜色与左边保持一致
Cell l11Cell = headerRow . createCell ( 11 ) ;
l11Cell . setCellValue ( " 备注 " ) ;
l11Cell . setCellStyle ( tableHeaderStyle ) ;
// 数据行( 第12-18行, 共7行) - 修正数据位置和赋值
String [ ] [ ] progressData = {
{ " 基础 " , " 光伏区 " , " 个 " , " 164728 " , " 3955 " , " 104434 " , " 63.4% " , " 6000 " , " 设计值为根据7.18日最新电子版图纸统计, 包含未开工的五工区, 总设计容量约为357.5Mpw。 " } ,
{ " 支架 " , " " , " 组 " , " 20591 " , " 644 " , " 6412 " , " 31.1% " , " 1050 " , " " } ,
{ " 组件 " , " " , " 组 " , " 20591 " , " 409 " , " 4902 " , " 23.8% " , " 850 " , " " } ,
{ " 清表 " , " " , " 亩 " , " 4517 " , " 0 " , " 4104 " , " 90.8% " , " 100 " , " " } ,
{ " 塔基 " , " 线路工程 " , " " , " " , " " , " " , " " , " " , " " } ,
{ " 组塔 " , " " , " " , " " , " " , " " , " " , " " , " " } ,
{ " 放线 " , " " , " " , " " , " " , " " , " " , " " , " " }
} ;
for ( int i = 0 ; i < progressData . length ; i + + ) {
Row row = sheet . createRow ( startRow + 1 + i ) ;
row . setHeightInPoints ( 20 ) ;
// A列和B列不设置内容( 在合并区域中)
// 从C列开始设置数据( C-I列)
for ( int j = 0 ; j < 7 ; j + + ) { // 只设置前7列数据( C-I列)
Cell cell = row . createCell ( j + 2 ) ; // C列开始
if ( j < progressData [ i ] . length ) {
cell . setCellValue ( progressData [ i ] [ j ] ) ;
}
cell . setCellStyle ( contentStyle ) ;
}
// 设置J,K列( 下周计划完成) - 使用数据数组的第8个元素
Cell jkCell = row . createCell ( 9 ) ; // J列
if ( progressData [ i ] . length > 7 ) {
jkCell . setCellValue ( progressData [ i ] [ 7 ] ) ; // 第8个元素是下周计划完成数据
}
jkCell . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow + 1 + i , startRow + 1 + i , 9 , 10 ) ;
// 设置L列( 备注) - 使用数据数组的第9个元素
Cell lCell = row . createCell ( 11 ) ; // L列
if ( progressData [ i ] . length > 8 ) {
lCell . setCellValue ( progressData [ i ] [ 8 ] ) ; // 第9个元素是备注数据
}
lCell . setCellStyle ( contentStyle ) ;
}
// 设置合并区域
try {
// A11:A18合并( 序号6)
sheet . addMergedRegion ( new CellRangeAddress ( startRow , startRow + 7 , 0 , 0 ) ) ;
// B11:B18合并( 标题)
sheet . addMergedRegion ( new CellRangeAddress ( startRow , startRow + 7 , 1 , 1 ) ) ;
// D12:D15合并( 光伏区)
sheet . addMergedRegion ( new CellRangeAddress ( startRow + 1 , startRow + 4 , 3 , 3 ) ) ;
// D16:D18合并( 线路工程)
sheet . addMergedRegion ( new CellRangeAddress ( startRow + 5 , startRow + 7 , 3 , 3 ) ) ;
// L12:L18合并( 备注)
sheet . addMergedRegion ( new CellRangeAddress ( startRow + 1 , startRow + 7 , 11 , 11 ) ) ;
} catch ( IllegalStateException e ) {
System . err . println ( " 施工进度表合并区域设置失败: " + e . getMessage ( ) ) ;
}
}
/**
* 设备材料表格( 第19-23行) - 修正数据赋值问题
*/
private static void createEquipmentMaterialTable ( Sheet sheet , Workbook workbook , int startRow ,
CellStyle headerStyle , CellStyle contentStyle ,
CellStyle tableHeaderStyle ) {
// 表头行( 第19行)
Row headerRow = sheet . createRow ( startRow ) ;
// A19与A20:A23合并, 内容为7
Cell a19Cell = headerRow . createCell ( 0 ) ;
a19Cell . setCellValue ( " 7 " ) ;
a19Cell . setCellStyle ( headerStyle ) ;
// B19与B20:B23合并, 内容为: 主要设备材料到货情况( 列出主要材料即可)
Cell b19Cell = headerRow . createCell ( 1 ) ;
b19Cell . setCellValue ( " 主要设备材料到货情况(列出主要材料即可) " ) ;
b19Cell . setCellStyle ( headerStyle ) ;
// C19内容为: 设备材料名称
Cell c19Cell = headerRow . createCell ( 2 ) ;
c19Cell . setCellValue ( " 设备材料名称 " ) ;
c19Cell . setCellStyle ( tableHeaderStyle ) ;
// 其他表头 - 从D列开始
String [ ] headers = { " " , " 单位 " , " 设计数量 " , " 本周到货量 " , " 累计到货量 " , " 累计到货率 " } ;
for ( int i = 0 ; i < headers . length ; i + + ) {
Cell cell = headerRow . createCell ( i + 3 ) ; // D列开始
cell . setCellValue ( headers [ i ] ) ;
cell . setCellStyle ( tableHeaderStyle ) ;
}
// J19:K19合并, 内容为: 计划到货日期
Cell j19Cell = headerRow . createCell ( 9 ) ;
j19Cell . setCellValue ( " 计划到货日期 " ) ;
j19Cell . setCellStyle ( tableHeaderStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow , 9 , 10 ) ;
// L19内容为: 备注, 背景颜色与左边保持一致
Cell l19Cell = headerRow . createCell ( 11 ) ;
l19Cell . setCellValue ( " 备注 " ) ;
l19Cell . setCellStyle ( tableHeaderStyle ) ;
// 数据行 - 从第20行开始( 共4行数据) - 修正数据位置和赋值
String [ ] [ ] materialData = {
{ " 檩条、斜撑 " , " " , " 根 " , " 131728 " , " 3752 " , " 106745 " , " 81.0% " , " " , " " } ,
{ " 立杆 " , " " , " 根 " , " 133841 " , " 5549 " , " 53372 " , " 39.9% " , " " , " " } ,
{ " 光伏组件 " , " " , " 块 " , " 576548 " , " 25880 " , " 177360 " , " 30.8% " , " " , " " } ,
{ " 预埋件 " , " " , " 套 " , " 164728 " , " 0 " , " 113000 " , " 68.6% " , " " , " " }
} ;
for ( int i = 0 ; i < materialData . length ; i + + ) {
Row row = sheet . createRow ( startRow + 1 + i ) ;
row . setHeightInPoints ( 20 ) ;
// A列和B列不设置内容( 在合并区域中)
// 从C列开始设置数据( C-I列)
for ( int j = 0 ; j < 7 ; j + + ) { // 只设置前7列数据( C-I列)
Cell cell = row . createCell ( j + 2 ) ; // C列开始
if ( j < materialData [ i ] . length ) {
cell . setCellValue ( materialData [ i ] [ j ] ) ;
}
cell . setCellStyle ( contentStyle ) ;
}
// 设置J,K列( 计划到货日期) - 使用数据数组的第8个元素
Cell jkCell = row . createCell ( 9 ) ; // J列
if ( materialData [ i ] . length > 7 ) {
jkCell . setCellValue ( materialData [ i ] [ 7 ] ) ; // 第8个元素是计划到货日期数据
}
jkCell . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow + 1 + i , startRow + 1 + i , 9 , 10 ) ;
// 设置L列( 备注) - 使用数据数组的第9个元素
Cell lCell = row . createCell ( 11 ) ; // L列
if ( materialData [ i ] . length > 8 ) {
lCell . setCellValue ( materialData [ i ] [ 8 ] ) ; // 第9个元素是备注数据
}
lCell . setCellStyle ( contentStyle ) ;
}
// 设置合并区域
try {
// A19:A23合并( 序号7)
sheet . addMergedRegion ( new CellRangeAddress ( startRow , startRow + 4 , 0 , 0 ) ) ;
// B19:B23合并( 标题)
sheet . addMergedRegion ( new CellRangeAddress ( startRow , startRow + 4 , 1 , 1 ) ) ;
// L20:L23合并( 备注)
sheet . addMergedRegion ( new CellRangeAddress ( startRow + 1 , startRow + 4 , 11 , 11 ) ) ;
} catch ( IllegalStateException e ) {
System . err . println ( " 设备材料表合并区域设置失败: " + e . getMessage ( ) ) ;
}
}
/**
* 修正其他相关模块的行号引用
*/
private static void createProblemsModule ( Sheet sheet , Workbook workbook , int startRow ,
CellStyle headerStyle , CellStyle contentStyle ) {
Row problemsRow = sheet . createRow ( startRow ) ;
Cell seqCell = problemsRow . createCell ( 0 ) ;
seqCell . setCellValue ( " 8 " ) ;
seqCell . setCellStyle ( headerStyle ) ;
Cell titleCell = problemsRow . createCell ( 1 ) ;
titleCell . setCellValue ( " 存在问题及需要协调的事项 " ) ;
titleCell . setCellStyle ( headerStyle ) ;
Cell contentCell = problemsRow . createCell ( 2 ) ;
contentCell . setCellValue ( " 1、场区围栏选型问题一直未能确定, 班组迟迟不能采购; \ n " +
" 2、道路青赔费用本月需支付20万、外苏三户村名青赔增加费用30万需支付; \ n " +
" 3、管理人员工资8、9两月需支付; \ n " +
" 4、班组应付款项未能及时支付, 造成班组材料采购都成问题。 " ) ;
contentCell . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow , 2 , 11 ) ;
}
/**
* 照片模块( 第26行) - 修正序号
*/
private static void createPhotoModule ( Sheet sheet , Workbook workbook , int startRow ,
CellStyle headerStyle , CellStyle contentStyle ) {
Row photoRow = sheet . createRow ( startRow ) ;
Cell seqCell = photoRow . createCell ( 0 ) ;
seqCell . setCellValue ( " 9 " ) ;
seqCell . setCellStyle ( headerStyle ) ;
Cell titleCell = photoRow . createCell ( 1 ) ;
titleCell . setCellValue ( " 照片 " ) ;
titleCell . setCellStyle ( headerStyle ) ;
Cell contentCell = photoRow . createCell ( 2 ) ;
contentCell . setCellStyle ( contentStyle ) ;
addMergedRegionSafe ( sheet , startRow , startRow , 2 , 11 ) ;
}
/**
* 填报审核模块( 第26行) - 合并F-L列
*/
private static void createApprovalModule ( Sheet sheet , Workbook workbook , int startRow ,
CellStyle headerStyle , CellStyle contentStyle ) {
Row approvalRow = sheet . createRow ( startRow ) ;
Cell seqCell = approvalRow . createCell ( 0 ) ;
seqCell . setCellValue ( " 10 " ) ;
seqCell . setCellStyle ( headerStyle ) ;
Cell fillLabel = approvalRow . createCell ( 1 ) ;
fillLabel . setCellValue ( " 填报: " ) ;
fillLabel . setCellStyle ( headerStyle ) ;
Cell fillerCell = approvalRow . createCell ( 2 ) ;
fillerCell . setCellValue ( " 伍雪飞 " ) ;
fillerCell . setCellStyle ( contentStyle ) ;
Cell checkLabel = approvalRow . createCell ( 4 ) ;
checkLabel . setCellValue ( " 审核: " ) ;
checkLabel . setCellStyle ( headerStyle ) ;
Cell checkerCell = approvalRow . createCell ( 5 ) ;
checkerCell . setCellValue ( " 张等红 " ) ;
checkerCell . setCellStyle ( contentStyle ) ;
// 合并F-L列
addMergedRegionSafe ( sheet , startRow , startRow , 5 , 11 ) ;
// 为F-L列设置空单元格和边框
for ( int i = 5 ; i < = 11 ; i + + ) {
Cell cell = approvalRow . getCell ( i ) ;
if ( cell = = null ) {
cell = approvalRow . createCell ( i ) ;
cell . setCellStyle ( contentStyle ) ;
}
}
}
/**
* 创建标题样式(支持自动换行)
*/
private static CellStyle createTitleCellStyle ( Workbook workbook ) {
CellStyle style = workbook . createCellStyle ( ) ;
Font font = workbook . createFont ( ) ;
font . setFontName ( " 宋体 " ) ;
font . setFontHeightInPoints ( ( short ) 16 ) ;
font . setBold ( true ) ;
style . setFont ( font ) ;
style . setAlignment ( HorizontalAlignment . CENTER ) ;
style . setVerticalAlignment ( VerticalAlignment . CENTER ) ;
style . setBorderTop ( BorderStyle . THIN ) ;
style . setBorderBottom ( BorderStyle . THIN ) ;
style . setBorderLeft ( BorderStyle . THIN ) ;
style . setBorderRight ( BorderStyle . THIN ) ;
style . setWrapText ( true ) ; // 启用自动换行
return style ;
}
/**
* 创建表头样式(支持自动换行)
*/
private static CellStyle createHeaderCellStyle ( Workbook workbook ) {
CellStyle style = workbook . createCellStyle ( ) ;
Font font = workbook . createFont ( ) ;
font . setFontName ( " 宋体 " ) ;
font . setFontHeightInPoints ( ( short ) 11 ) ;
font . setBold ( true ) ;
style . setFont ( font ) ;
style . setAlignment ( HorizontalAlignment . CENTER ) ;
style . setVerticalAlignment ( VerticalAlignment . CENTER ) ;
style . setBorderTop ( BorderStyle . THIN ) ;
style . setBorderBottom ( BorderStyle . THIN ) ;
style . setBorderLeft ( BorderStyle . THIN ) ;
style . setBorderRight ( BorderStyle . THIN ) ;
style . setFillForegroundColor ( IndexedColors . GREY_25_PERCENT . getIndex ( ) ) ;
style . setFillPattern ( FillPatternType . SOLID_FOREGROUND ) ;
style . setWrapText ( true ) ; // 启用自动换行
return style ;
}
/**
* 创建内容样式(支持自动换行和自动调整行高)
*/
private static CellStyle createContentCellStyle ( Workbook workbook ) {
CellStyle style = workbook . createCellStyle ( ) ;
Font font = workbook . createFont ( ) ;
font . setFontName ( " 宋体 " ) ;
font . setFontHeightInPoints ( ( short ) 10 ) ;
style . setFont ( font ) ;
style . setAlignment ( HorizontalAlignment . LEFT ) ;
style . setVerticalAlignment ( VerticalAlignment . TOP ) ; // 改为顶部对齐,便于自动换行
style . setBorderTop ( BorderStyle . THIN ) ;
style . setBorderBottom ( BorderStyle . THIN ) ;
style . setBorderLeft ( BorderStyle . THIN ) ;
style . setBorderRight ( BorderStyle . THIN ) ;
style . setWrapText ( true ) ; // 启用自动换行
return style ;
}
/**
* 创建表头样式(支持自动换行)
*/
private static CellStyle createTableHeaderCellStyle ( Workbook workbook ) {
CellStyle style = workbook . createCellStyle ( ) ;
Font font = workbook . createFont ( ) ;
font . setFontName ( " 宋体 " ) ;
font . setFontHeightInPoints ( ( short ) 10 ) ;
font . setBold ( true ) ;
style . setFont ( font ) ;
style . setAlignment ( HorizontalAlignment . CENTER ) ;
style . setVerticalAlignment ( VerticalAlignment . CENTER ) ;
style . setBorderTop ( BorderStyle . THIN ) ;
style . setBorderBottom ( BorderStyle . THIN ) ;
style . setBorderLeft ( BorderStyle . THIN ) ;
style . setBorderRight ( BorderStyle . THIN ) ;
style . setFillForegroundColor ( IndexedColors . LIGHT_GREEN . getIndex ( ) ) ;
style . setFillPattern ( FillPatternType . SOLID_FOREGROUND ) ;
style . setWrapText ( true ) ; // 启用自动换行
return style ;
}
/**
* 安全添加合并区域(修复重叠检测逻辑)
*/
private static void addMergedRegionSafe ( Sheet sheet , int firstRow , int lastRow , int firstCol , int lastCol ) {
if ( firstRow = = lastRow & & firstCol = = lastCol ) {
return ;
}
CellRangeAddress newRegion = new CellRangeAddress ( firstRow , lastRow , firstCol , lastCol ) ;
// 检查是否与现有合并区域重叠
List < CellRangeAddress > mergedRegions = sheet . getMergedRegions ( ) ;
boolean hasOverlap = false ;
for ( CellRangeAddress existingRegion : mergedRegions ) {
if ( regionsOverlap ( newRegion , existingRegion ) ) {
// 如果是完全相同的区域,跳过(可能是重复设置)
if ( newRegion . equals ( existingRegion ) ) {
System . out . println ( " 跳过重复的合并区域: " + newRegion . formatAsString ( ) ) ;
return ;
}
System . err . println ( " 跳过重叠的合并区域: " + newRegion . formatAsString ( ) +
" 与 " + existingRegion . formatAsString ( ) ) ;
hasOverlap = true ;
break ;
}
}
if ( ! hasOverlap ) {
try {
sheet . addMergedRegion ( newRegion ) ;
System . out . println ( " 成功添加合并区域: " + newRegion . formatAsString ( ) ) ;
} catch ( IllegalStateException e ) {
System . err . println ( " 添加合并区域失败: " + newRegion . formatAsString ( ) + " - " + e . getMessage ( ) ) ;
}
}
}
/**
* 自动调整行高以适应内容
*/
private static void autoAdjustRowHeights ( Sheet sheet ) {
for ( int rowNum = 0 ; rowNum < = sheet . getLastRowNum ( ) ; rowNum + + ) {
Row row = sheet . getRow ( rowNum ) ;
if ( row ! = null ) {
// 计算该行中所有单元格的最大行数
int maxLines = 1 ;
for ( int cellNum = 0 ; cellNum < row . getLastCellNum ( ) ; cellNum + + ) {
Cell cell = row . getCell ( cellNum ) ;
if ( cell ! = null & & cell . getStringCellValue ( ) ! = null ) {
String cellValue = cell . getStringCellValue ( ) ;
// 根据内容长度和列宽估算行数
int estimatedLines = estimateLineCount ( cellValue , sheet . getColumnWidth ( cellNum ) ) ;
maxLines = Math . max ( maxLines , estimatedLines ) ;
}
}
// 设置行高( 每行约15点)
float rowHeight = Math . max ( 20f , maxLines * 15f ) ; // 最小高度20, 根据行数调整
row . setHeightInPoints ( rowHeight ) ;
}
}
}
/**
* 估算文本在指定列宽下的行数
*/
private static int estimateLineCount ( String text , int columnWidth ) {
if ( text = = null | | text . isEmpty ( ) ) {
return 1 ;
}
// 估算每个字符的宽度(近似值)
double charWidth = 256 ; // Excel中字符宽度的近似值
double availableWidth = columnWidth ;
String [ ] lines = text . split ( " \ n " ) ;
int totalLines = 0 ;
for ( String line : lines ) {
if ( line . isEmpty ( ) ) {
totalLines + + ;
continue ;
}
// 估算该行需要的行数
double lineWidth = line . length ( ) * charWidth ;
int linesNeeded = ( int ) Math . ceil ( lineWidth / availableWidth ) ;
totalLines + = Math . max ( 1 , linesNeeded ) ;
}
return Math . max ( 1 , totalLines ) ;
}
/**
* 创建空单元格样式(带边框)
*/
private static CellStyle createEmptyCellStyle ( Workbook workbook ) {
CellStyle style = workbook . createCellStyle ( ) ;
style . setBorderTop ( BorderStyle . THIN ) ;
style . setBorderBottom ( BorderStyle . THIN ) ;
style . setBorderLeft ( BorderStyle . THIN ) ;
style . setBorderRight ( BorderStyle . THIN ) ;
return style ;
}
/**
* 设置关键行的行高(移除固定行高设置,使用自动调整)
*/
private static void setKeyRowHeights ( Sheet sheet ) {
// 不再设置固定行高, 由autoAdjustRowHeights自动调整
// 只设置最小行高确保基本显示
for ( int i = 0 ; i < = sheet . getLastRowNum ( ) ; i + + ) {
Row row = sheet . getRow ( i ) ;
if ( row ! = null & & row . getHeightInPoints ( ) < 20 ) {
row . setHeightInPoints ( 20 ) ; // 设置最小行高
}
}
}
/**
* 检查两个合并区域是否重叠
*/
private static boolean regionsOverlap ( CellRangeAddress region1 , CellRangeAddress region2 ) {
return ! ( region1 . getLastRow ( ) < region2 . getFirstRow ( ) | |
region1 . getFirstRow ( ) > region2 . getLastRow ( ) | |
region1 . getLastColumn ( ) < region2 . getFirstColumn ( ) | |
region1 . getFirstColumn ( ) > region2 . getLastColumn ( ) ) ;
}
/**
* 设置所有小范围的合并区域 - 修正日期合并区域
*/
private static void setupAllSmallMergeRegions ( Sheet sheet ) {
// 创建必要的行
for ( int i = 0 ; i < = 3 ; i + + ) {
if ( sheet . getRow ( i ) = = null ) {
sheet . createRow ( i ) ;
}
}
// 按从小到大的顺序设置合并区域
try {
// 1. 取消J3:J4和K3:L4合并, 改为单独的合并区域
sheet . addMergedRegion ( new CellRangeAddress ( 2 , 3 , 9 , 9 ) ) ; // J3:J4合并
sheet . addMergedRegion ( new CellRangeAddress ( 2 , 3 , 10 , 11 ) ) ; // K3:L4合并
System . out . println ( " 设置小合并区域: J3:J4, K3:L4 " ) ;
// 2. 中等范围的合并区域
sheet . addMergedRegion ( new CellRangeAddress ( 2 , 2 , 0 , 1 ) ) ; // A3:B3
sheet . addMergedRegion ( new CellRangeAddress ( 2 , 2 , 2 , 6 ) ) ; // C3:G3
System . out . println ( " 设置中等合并区域: A3:B3, C3:G3 " ) ;
// 3. 较大范围的合并区域
sheet . addMergedRegion ( new CellRangeAddress ( 3 , 3 , 1 , 8 ) ) ; // B4:I4
System . out . println ( " 设置大合并区域: B4:I4 " ) ;
} catch ( IllegalStateException e ) {
System . err . println ( " 小范围合并区域设置失败: " + e . getMessage ( ) ) ;
}
}
/**
* 确保所有单元格都有边框
*/
private static void ensureAllCellsHaveBorders ( Sheet sheet , Workbook workbook ) {
CellStyle borderStyle = createContentCellStyle ( workbook ) ;
// 遍历所有行和列,确保每个单元格都有边框
for ( int rowNum = 0 ; rowNum < = sheet . getLastRowNum ( ) ; rowNum + + ) {
Row row = sheet . getRow ( rowNum ) ;
if ( row ! = null ) {
for ( int colNum = 0 ; colNum < 12 ; colNum + + ) {
Cell cell = row . getCell ( colNum ) ;
if ( cell = = null ) {
cell = row . createCell ( colNum ) ;
cell . setCellStyle ( borderStyle ) ;
} else if ( cell . getCellStyle ( ) = = null ) {
cell . setCellStyle ( borderStyle ) ;
}
}
}
}
}
}