Browse Source

1.机器设备-进口设备测算表生成并合并到主模板
2.机器设备-主表引用进口设备表数据开发

GouGengquan 8 months ago
parent
commit
dde0a1fd7a

+ 100 - 20
common/src/main/java/com/dayou/utils/EasyExcelUtil.java

@@ -5,6 +5,7 @@ import com.alibaba.excel.EasyExcel;
 import com.alibaba.excel.ExcelWriter;
 import com.alibaba.excel.write.metadata.WriteSheet;
 import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellRangeAddressList;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 
@@ -20,10 +21,11 @@ public class EasyExcelUtil {
 
     /**
      * 填充动态数据到Excel
-     * @param inputFilePath 模板文件路径
+     *
+     * @param inputFilePath  模板文件路径
      * @param outputFilePath 输出文件路径
-     * @param dataMap 数据map
-     * @param evaluate 是否计算公式(大文件慎用,可能会导致内存溢出)
+     * @param dataMap        数据map
+     * @param evaluate       是否计算公式(大文件慎用,可能会导致内存溢出)
      */
     public static void fillExcelDataByMap(String inputFilePath, String outputFilePath, Map<String, Object> dataMap, boolean evaluate) {
         // 使用EasyExcel填充数据
@@ -35,7 +37,7 @@ public class EasyExcelUtil {
         excelWriter.fill(dataMap, writeSheet); // 填充数据
 
         // 由于填充后不会自动更新公式值,所以需要手动更新
-        if (evaluate){
+        if (evaluate) {
             Workbook workbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook();
             workbook.getCreationHelper().createFormulaEvaluator().evaluateAll(); // 强制计算公式
         }
@@ -44,10 +46,11 @@ public class EasyExcelUtil {
 
     /**
      * 合并Excel文件
-     * @param sourceExcelPath 源文件路径(段落模板)
-     * @param targetExcelPath 目标文件路径(主模板)
+     *
+     * @param sourceExcelPath  源文件路径(段落模板)
+     * @param targetExcelPath  目标文件路径(主模板)
      * @param targetSheetIndex 目标sheet索引(要插入的sheet)
-     * @param targetRowNum 目标行索引(要插入的行)
+     * @param targetRowNum     目标行索引(要插入的行)
      * @param sourceSheetIndex 源文件被引用的sheet
      * @return Workbook 返回工作簿
      * @throws IOException 抛出IO异常
@@ -63,7 +66,7 @@ public class EasyExcelUtil {
         Sheet targetSheet = targetWorkbook.getSheetAt(targetSheetIndex); // 获取目标sheet
 
         // 复制样式映射
-        Map<Short, Short> styleMap = copyCellStyle(sourceWorkbook, targetWorkbook);
+        Map<Short, Short> styleMap = copyCellStyle(sourceWorkbook, targetWorkbook, targetSheetIndex, sourceSheetIndex);
 
         // 复制行和单元格
         for (Row sourceRow : sourceSheet) {
@@ -84,28 +87,103 @@ public class EasyExcelUtil {
     }
 
     /**
+     * 合并Excel文件-目标文件为WorkBook方式
+     *
+     * @param sourceExcelPath  源文件路径(段落模板)
+     * @param targetWorkbook   目标工作表(主模板)
+     * @param targetSheetIndex 目标sheet索引(要插入的sheet)
+     * @param targetRowNum     目标行索引(要插入的行)
+     * @param sourceSheetIndex 源文件被引用的sheet
+     * @throws IOException 抛出IO异常
+     */
+    public static void mergeExcel(String sourceExcelPath, Workbook targetWorkbook, int targetSheetIndex, int targetRowNum, int sourceSheetIndex) throws IOException {
+        // 获取源Excel
+        InputStream inputStream = Files.newInputStream(Paths.get(sourceExcelPath));
+        Workbook sourceWorkbook = new XSSFWorkbook(inputStream);
+        Sheet sourceSheet = sourceWorkbook.getSheetAt(sourceSheetIndex);
+
+        // 打开已存在的Excel工作簿
+        Sheet targetSheet = targetWorkbook.getSheetAt(targetSheetIndex); // 获取目标sheet
+
+        // 复制样式映射
+        Map<Short, Short> styleMap = copyCellStyle(sourceWorkbook, targetWorkbook, targetSheetIndex, sourceSheetIndex);
+
+        // 复制行和单元格
+        for (Row sourceRow : sourceSheet) {
+            Row targetRow = targetSheet.createRow(targetRowNum + sourceRow.getRowNum());
+            for (Cell sourceCell : sourceRow) {
+                Cell targetCell = targetRow.createCell(sourceCell.getColumnIndex());
+                copyCell(sourceCell, targetCell, targetWorkbook, styleMap);
+            }
+        }
+
+        // 复制数据验证
+        copyDataValidations(sourceSheet, targetSheet);
+
+        sourceWorkbook.close();
+        inputStream.close();
+
+    }
+
+    /**
      * 复制单元格样式
-     * @param srcBook 源工作簿
-     * @param desBook 目标工作簿
+     *
+     * @param srcBook          源工作簿
+     * @param desBook          目标工作簿
+     * @param targetSheetIndex 目标sheet索引
+     * @param sourceSheetIndex 源文件被引用的sheet
      * @return Map<Short, Short> 样式
      */
-    private static Map<Short, Short> copyCellStyle(Workbook srcBook, Workbook desBook) {
+    private static Map<Short, Short> copyCellStyle(Workbook srcBook, Workbook desBook, int targetSheetIndex, int sourceSheetIndex) {
         Map<Short, Short> styleMap = new HashMap<>();
+        // 复制样式
         for (short i = 0; i < srcBook.getNumCellStyles(); i++) {
             CellStyle srcStyle = srcBook.getCellStyleAt(i);
             CellStyle desStyle = desBook.createCellStyle();
             desStyle.cloneStyleFrom(srcStyle);
             styleMap.put(srcStyle.getIndex(), desStyle.getIndex());
         }
+
+        // 复制合并单元格并应用样式
+        Sheet srcSheet = srcBook.getSheetAt(sourceSheetIndex);
+        Sheet destSheet = desBook.getSheetAt(targetSheetIndex);
+
+        // 合并单元格
+        for (int mergeIndex = 0; mergeIndex < srcSheet.getNumMergedRegions(); mergeIndex++) {
+            CellRangeAddress srcRange = srcSheet.getMergedRegion(mergeIndex);
+            // 创建新的合并单元格区域
+            CellRangeAddress newRange = new CellRangeAddress(
+                    srcRange.getFirstRow(),
+                    srcRange.getLastRow(),
+                    srcRange.getFirstColumn(),
+                    srcRange.getLastColumn()
+            );
+            destSheet.addMergedRegion(newRange);
+
+            // 获取原合并单元格的样式索引
+            short srcStyleIndex = srcSheet.getRow(srcRange.getFirstRow()).getCell(srcRange.getFirstColumn()).getCellStyle().getIndex();
+            // 应用样式到新合并单元格的左上角单元格
+            short destStyleIndex = styleMap.get(srcStyleIndex);
+            Row destRow = destSheet.getRow(srcRange.getFirstRow());
+            if (destRow == null) {
+                destRow = destSheet.createRow(srcRange.getFirstRow());
+            }
+            Cell destCell = destRow.getCell(srcRange.getFirstColumn());
+            if (destCell == null) {
+                destCell = destRow.createCell(srcRange.getFirstColumn());
+            }
+            destCell.setCellStyle(desBook.getCellStyleAt(destStyleIndex));
+        }
         return styleMap;
     }
 
     /**
      * 复制单元格
-     * @param srcCell 源单元格
-     * @param desCell 目标单元格
+     *
+     * @param srcCell        源单元格
+     * @param desCell        目标单元格
      * @param targetWorkbook 目标工作簿
-     * @param styleMap 样式
+     * @param styleMap       样式
      */
     private static void copyCell(Cell srcCell, Cell desCell, Workbook targetWorkbook, Map<Short, Short> styleMap) {
         // 判断单元格值类型
@@ -127,6 +205,7 @@ public class EasyExcelUtil {
 
     /**
      * 复制数据验证(下拉框)
+     *
      * @param sourceSheet 源Sheet
      * @param targetSheet 目标Sheet
      */
@@ -149,29 +228,30 @@ public class EasyExcelUtil {
 
     /**
      * 房地产基本信息sheet表单 固定解析函数
+     *
      * @param wb
      * @param sheetName
      * @return
      */
-    public static Map<String ,String> getExcelCellValue(Workbook wb, String sheetName) {
-        Map<String,String> valueMap = new HashMap<>();
+    public static Map<String, String> getExcelCellValue(Workbook wb, String sheetName) {
+        Map<String, String> valueMap = new HashMap<>();
         Sheet sheet = wb.getSheet(sheetName);// 获取指定名称Sheet的内容
         int lastRowNum = sheet.getLastRowNum();
         Row rowKey = null;
         Row rowValue = null;
         Cell cellKey = null;
         Cell cellValue = null;
-        for (int rowNum = sheet.getFirstRowNum(); rowNum <= lastRowNum/2; rowNum+=2) {
+        for (int rowNum = sheet.getFirstRowNum(); rowNum <= lastRowNum / 2; rowNum += 2) {
             rowKey = sheet.getRow(rowNum);
-            rowValue = sheet.getRow(rowNum+1);
+            rowValue = sheet.getRow(rowNum + 1);
             int lastColNum = rowKey.getLastCellNum();
             for (int colNum = 0; colNum <= lastColNum; colNum++) {
                 cellKey = rowKey.getCell(colNum);
                 cellValue = rowValue.getCell(colNum);
                 if (cellKey != null && StrUtil.isNotBlank(cellKey.toString())
-                    && cellValue != null) {
+                        && cellValue != null) {
                     String attr = cellKey.getHyperlink().getAddress();
-                        valueMap.put(attr, cellValue.toString());
+                    valueMap.put(attr, cellValue.toString());
                 }
             }
         }

+ 7 - 0
dao/src/main/java/com/dayou/mapper/AssetsCalculateEqptDataMapper.java

@@ -60,6 +60,13 @@ public interface AssetsCalculateEqptDataMapper extends BaseMapper<AssetsCalculat
     Page<AssetsCalculateEqptImpDataVO> getImpDataPage(@Param("page") Page page, @Param("dto") EqptQueryDTO dto);
 
     /**
+     * 查询进口设备信息集合
+     * @param calculateId 测算表id
+     * @return Page<AssetsCalculateEqptImpData>
+     */
+    List<AssetsCalculateEqptImpDataVO> getImpDataList(@Param("calculateId") Long calculateId);
+
+    /**
      * 根据id更新机器设备测算数据单价
      * @param id id
      * @param price 单价

+ 39 - 0
dao/src/main/resources/mapper/AssetsCalculateEqptDataMapper.xml

@@ -55,6 +55,7 @@
         <if test="equipmentType != null and equipmentType != ''">
             AND equipment_type = #{equipmentType}
         </if>
+        ORDER BY sort_id
     </select>
 
     <!--分页查询导入的机器设备测算数据-->
@@ -76,6 +77,7 @@
         <if test="dto != null and dto.equipmentName">
             AND equipment_name LIKE CONCAT('%', #{dto.equipmentName}, '%')
         </if>
+        ORDER BY sort_id
     </select>
 
     <!--根据测算表id删除-->
@@ -125,6 +127,43 @@
         <if test="dto != null and dto.equipmentName">
             AND equipment_name LIKE CONCAT('%', #{dto.equipmentName}, '%')
         </if>
+        ORDER BY data.sort_id
+    </select>
+
+    <!--查询进口设备信息集合-->
+    <select id="getImpDataList" resultType="com.dayou.vo.AssetsCalculateEqptImpDataVO">
+        SELECT data.sort_id,
+               data.equipment_name,
+               data.model,
+               data.purchase_date,
+               data.activation_date,
+               data.quantity,
+               data.unit_of_measurement,
+               data.book_original_value,
+               data.manufacturer,
+               impData.id,
+               data.id AS eqptDataId,
+               impData.ppi,
+               impData.pricing_basis,
+               impData.central_parity_rate,
+               impData.tariff_rate,
+               impData.import_vat_rate,
+               impData.bank_charges_rate,
+               impData.foreign_transaction_rate,
+               impData.product_code,
+               impData.currency,
+               impData.address,
+               impData.transaction_method,
+               impData.contract_amount,
+               impData.contract_signing_date,
+               impData.destination_port,
+               impData.original_price
+        FROM assets_calculate_eqpt_data AS data
+                 LEFT JOIN assets_calculate_eqpt_imp_data AS impData ON impData.eqpt_data_id = data.id AND impData.delete_status = 0
+        WHERE data.delete_status = 0
+          AND data.equipment_type = '进口设备'
+          AND assets_calculate_id = #{calculateId}
+        ORDER BY data.sort_id
     </select>
 
     <!--根据id更新机器设备测算数据单价-->

+ 54 - 1
domain/src/main/java/com/dayou/common/CalculateFormula.java

@@ -6,11 +6,19 @@ package com.dayou.common;
 public class CalculateFormula {
 
     /**
-     * 机器设备公式,占位符{0}是行号
+     * 机器设备主模板公式,占位符{0}是行号
      * AT列 1~4 行是固定的
      */
     public static final EquipmentMainFormula[] EQUIPMENT_MAIN_FORMULA = EquipmentMainFormula.values();
 
+    /**
+     * 机器设备进口设备模板公式,占位符{0}是行号
+     */
+    public static final EquipmentImportedFormula[] EQUIPMENT_IMPORTED_FORMULA = EquipmentImportedFormula.values();
+
+    /**
+     * 机器设备主模板公式
+     */
     public enum EquipmentMainFormula {
         不含税单价("L{0}/(1+M{0})",14),
         原值("AP{0}",16),
@@ -60,4 +68,49 @@ public class CalculateFormula {
 
     }
 
+    /**
+     * 机器设备进口设备模板公式
+     */
+    public enum EquipmentImportedFormula {
+        购置价CIF到岸价("J{0}*AD{0}",12),
+        CIF到岸价折人民币("ROUND(M{0}*L{0},0)",14),
+        关税("N{0}*O{0}",16),
+        进口增值税("(N{0}+P{0})*Q{0}",18),
+        设备价格("SUM(N{0},P{0},R{0})",19),
+        银行财务费("N{0}*T{0}",21),
+        外贸手续费("N{0}*V{0}",23),
+        费用小计("SUM(U{0},W{0})",24),
+        设备原价("S{0}+X{0}",25);
+
+        /**
+         * 公式
+         */
+        private String formula;
+
+        /**
+         * 列下标
+         */
+        private Integer column;
+
+        EquipmentImportedFormula(String formula, Integer column) {
+            this.formula = formula;
+            this.column = column;
+        }
+
+        public String getFormula() {
+            return formula;
+        }
+
+        public Integer getColumn() {
+            return column;
+        }
+
+        @Override
+        public String toString() {
+            return column + ":" + formula;
+        }
+
+
+    }
+
 }

+ 2 - 2
domain/src/main/java/com/dayou/enums/EquipmentTmplCode.java

@@ -4,8 +4,8 @@ public enum EquipmentTmplCode {
 
     MAIN("MAIN", "机器设备-主模板"),
     MAIN_DETAIL("MAIN_DETAIL", "机器设备-主模板-设备信息-段落模板"),
-    IMPORTED_CALCULATE("IMPORTED_CALCULATE", "机器设备-进口设备-段落模板"),
-    IMPORTED_CALCULATE_DETAIL("IMPORTED_CALCULATE_DETAIL", "机器设备-进口设备-设备信息-段落模板"),
+    IMPORTED_CALCULATE("IMPORTED", "机器设备-进口设备-段落模板"),
+//    IMPORTED_CALCULATE_DETAIL("IMPORTED_CALCULATE_DETAIL", "机器设备-进口设备-设备信息-段落模板"),
     NONSTANDARD_CALCULATE("NONSTANDARD_CALCULATE", "机器设备-非标设备-段落模板"),
     NONSTANDARD_CALCULATE_DETAIL("NONSTANDARD_CALCULATE_DETAIL", "机器设备-非标设备测算-设备信息-段落模板");
 

+ 15 - 0
domain/src/main/java/com/dayou/vo/AssetsCalculateEqptImpDataVO.java

@@ -1,5 +1,6 @@
 package com.dayou.vo;
 
+import com.alibaba.excel.annotation.ExcelIgnore;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -146,41 +147,55 @@ public class AssetsCalculateEqptImpDataVO {
     /**
      * 购置价(CIF到岸价)
      */
+    @ExcelIgnore
     private BigDecimal purchasePrice;
 
     /**
      * (CIF到岸价)折人民币
      */
+    @ExcelIgnore
     private BigDecimal CIFLandedPrice;
 
     /**
      * 关税
      */
+    @ExcelIgnore
     private BigDecimal tariff;
 
     /**
      * 进口增值税
      */
+    @ExcelIgnore
     private BigDecimal importVAT;
 
     /**
      * 设备价格
      */
+    @ExcelIgnore
     private BigDecimal eqptPrice;
 
     /**
      * 银行财务费
      */
+    @ExcelIgnore
     private BigDecimal bankCharges;
 
     /**
      * 外贸手续费
      */
+    @ExcelIgnore
     private BigDecimal foreignTransaction;
 
     /**
      * 费用小计
      */
+    @ExcelIgnore
     private BigDecimal totalFees;
 
+    /**
+     * 空单元格占位(对应模板上的设置)
+     * 不设置占位的话,导入数据时空单元格不会创建单元格会导致模板样式丢失
+     */
+    private Integer placeholder;
+
 }

+ 7 - 0
service/src/main/java/com/dayou/service/AssetsCalculateEqptDataService.java

@@ -65,6 +65,13 @@ public interface AssetsCalculateEqptDataService extends IService<AssetsCalculate
     Page<AssetsCalculateEqptImpDataVO> getImpDataPage(Page page, EqptQueryDTO dto);
 
     /**
+     * 查询进口设备信息集合
+     * @param calculateId 测算表id
+     * @return Page<AssetsCalculateEqptImpData>
+     */
+    List<AssetsCalculateEqptImpDataVO> getImpDataList(Long calculateId);
+
+    /**
      * 更新机器设备进口设备数据
      * @param assetsCalculateEqptImpData 进口设备信息
      * @return Boolean

+ 10 - 0
service/src/main/java/com/dayou/service/impl/AssetsCalculateEqptDataServiceImpl.java

@@ -93,6 +93,16 @@ public class AssetsCalculateEqptDataServiceImpl extends ServiceImpl<AssetsCalcul
     }
 
     /**
+     * 查询进口设备信息集合
+     * @param calculateId 测算表id
+     * @return Page<AssetsCalculateEqptImpData>
+     */
+    @Override
+    public List<AssetsCalculateEqptImpDataVO> getImpDataList(Long calculateId) {
+        return dataMapper.getImpDataList(calculateId);
+    }
+
+    /**
      * 更新机器设备进口设备数据
      * @param assetsCalculateEqptImpData 进口设备信息
      * @return Boolean

+ 55 - 9
service/src/main/java/com/dayou/service/impl/AssetsCalculateServiceImpl.java

@@ -1,6 +1,7 @@
 package com.dayou.service.impl;
 
 import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.excel.EasyExcel;
 import com.alibaba.excel.read.listener.PageReadListener;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -19,6 +20,7 @@ import com.dayou.service.AssetsCalculateEqptDataService;
 import com.dayou.service.AssetsCalculateService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.dayou.utils.EasyExcelUtil;
+import com.dayou.vo.AssetsCalculateEqptImpDataVO;
 import com.dayou.vo.AssetsCalculateVO;
 import com.dayou.vo.calculate.AssetsCalculateProgressVO;
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -38,8 +40,10 @@ import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.text.MessageFormat;
 import java.time.LocalDate;
+import java.util.ArrayList;
 import java.util.List;
 
+import static com.dayou.common.CalculateFormula.EQUIPMENT_IMPORTED_FORMULA;
 import static com.dayou.common.CalculateFormula.EQUIPMENT_MAIN_FORMULA;
 
 /**
@@ -57,7 +61,7 @@ public class AssetsCalculateServiceImpl extends ServiceImpl<AssetsCalculateMappe
     private AssetsCalculateMapper assetsCalculateMapper;
 
     @Autowired
-    private AssetsCalculateEqptDataService assetsCalculateEqptDataService;
+    private AssetsCalculateEqptDataService dataService;
 
     @Autowired
     private TmplAssetCalculateMapper tmplAssetCalculateMapper;
@@ -120,14 +124,14 @@ public class AssetsCalculateServiceImpl extends ServiceImpl<AssetsCalculateMappe
     @Transactional(rollbackFor = Exception.class)
     public void importEqptExcelData(MultipartFile multipartFile, Long calculateId) throws IOException {
         // 删除已上传的数据
-        assetsCalculateEqptDataService.deleteDataByCalculateId(calculateId);
+        dataService.deleteDataByCalculateId(calculateId);
         // 读取excel内容并批量保存到数据库
         InputStream inputStream = multipartFile.getInputStream();
         EasyExcel.read(inputStream, AssetsCalculateEqptData.class, new PageReadListener<AssetsCalculateEqptData>(dataList -> {
             // 设置数据的测算表id
             dataList.forEach(data -> data.setAssetsCalculateId(calculateId));
             // 批量保存
-            assetsCalculateEqptDataService.saveBatch(dataList);
+            dataService.saveBatch(dataList);
         }, 1000)).sheet().doRead();
     }
 
@@ -164,7 +168,7 @@ public class AssetsCalculateServiceImpl extends ServiceImpl<AssetsCalculateMappe
         EasyExcel.write(mainDetailPath)
                 .withTemplate(mainDetailTMplPath)
                 .sheet()
-                .doFill(assetsCalculateEqptDataService.getAllByAssetsCalculateId(calculateId, null));
+                .doFill(dataService.getAllByAssetsCalculateId(calculateId, null));
 
         // 第二步:写入数据到 机器设备-主模板
         // 获取模板
@@ -211,14 +215,56 @@ public class AssetsCalculateServiceImpl extends ServiceImpl<AssetsCalculateMappe
         }
 
         // 第五步:设置进口设备的测算表
-        List<AssetsCalculateEqptData> importedEqptData = assetsCalculateEqptDataService.getAllByAssetsCalculateId(calculateId, "进口设备");
-        if (!importedEqptData.isEmpty()) {
+        List<AssetsCalculateEqptImpDataVO> impEqptData = dataService.getImpDataList(calculateId);
+        if (ObjectUtil.isNotNull(impEqptData)) {
             // 获取模板
-            TmplAssetCalculate imported = tmplAssetCalculateMapper.getCalculateTmplByCode("IMPORTED");
+            TmplAssetCalculateSection imported = calculateSectionMapper.getByTmplCode("IMPORTED");
             // 生成后文件的位置
-            String importedPath = fileNetConfig.getBaseDir() + fileNetConfig.getAssetOutputCalculatePath() + System.currentTimeMillis() + "_MAIN.xlsx";
+            String importedPath = fileNetConfig.getBaseDir() + fileNetConfig.getAssetOutputCalculatePath() + System.currentTimeMillis() + "_IMPORTED.xlsx";
             // 模板文件的位置
-            String importedTmplPath = fileNetConfig.getBaseDir() + main.getFileUrl() + main.getFileName();
+            String importedTmplPath = fileNetConfig.getBaseDir() + imported.getSectionFileUrl() + imported.getSectionFileName();
+            // 写入
+            EasyExcel.write(importedPath)
+                    .withTemplate(importedTmplPath)
+                    .sheet()
+                    .doFill(impEqptData);
+            // 将进口设备excel合并到主excel
+            workbook.createSheet("进口设备");
+            EasyExcelUtil.mergeExcel(importedPath, workbook, workbook.getSheetIndex("进口设备"), 0, 0);
+            // 设置公式
+            Sheet importedSheet = workbook.getSheet("进口设备");
+            for (int i = 2; i <= importedSheet.getLastRowNum(); i++) { // 跳过前两行
+                Row row = importedSheet.getRow(i);
+                // 循环设置公式
+                for (CalculateFormula.EquipmentImportedFormula formula: EQUIPMENT_IMPORTED_FORMULA) {
+                    Cell cell = row.getCell(formula.getColumn() - 1);
+                    // 如果该单元格不存在,则创建一个
+                    if (cell == null) {
+                        cell = row.createCell(formula.getColumn() - 1);
+                    }
+                    // 设置公式
+                    cell.setCellFormula(MessageFormat.format(formula.getFormula(),(row.getRowNum() + 1)));
+                }
+            }
+
+            // 将主表sheet中进口设备数据的单价改为引用对应的进口设备表的设备原价
+            for (Row row : sheet) {
+                Cell cell = row.getCell(25); // Z列(设备类型)的索引是25(从0开始计数)
+                if (cell != null && cell.getStringCellValue().equals("进口设备")) {
+                    Cell priceCell = row.getCell(29); // 单价单元格
+                    int importedRowNum;
+                    // 循环进口设备sheet
+                    for (int i = 2; i <= importedSheet.getLastRowNum(); i++) { // 跳过前两行
+                        Cell importedCell = importedSheet.getRow(i).getCell(0); // 获取进口设备的序号
+                        // 判断主表的序号和进口设备的序号是否相等
+                        if (importedCell != null && row.getCell(0).getNumericCellValue() == importedCell.getNumericCellValue()) {
+                            importedRowNum = importedCell.getRowIndex() + 1; // +1是因为代码中下标从0开始,但是excel是从1开始
+                            priceCell.setCellFormula(MessageFormat.format("进口设备!Y{0}",importedRowNum));
+                            break;
+                        }
+                    }
+                }
+            }
         }
 
         // 强制计算公式