Browse Source

公式通用计算,写入

yangyj 1 year ago
parent
commit
8d2544b9bf

+ 16 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/ElementData.java

@@ -24,6 +24,7 @@ public class ElementData implements Serializable {
      * 数据组Id,一道工序可能会在不同时间或者空间测量多组数据
      */
     private Integer groupId;
+    /**内容*/
     private Object value;
 
     private Integer x;
@@ -90,6 +91,21 @@ public class ElementData implements Serializable {
         this.x = x;
         this.y = y;
     }
+    public ElementData(Integer index, Object value, Integer x, Integer y) {
+        this.index = index;
+        this.groupId = 0;
+        this.value = value;
+        this.x = x;
+        this.y = y;
+    }
+
+    public ElementData( Integer x, Integer y) {
+        this.index = 0;
+        this.groupId = 0;
+        this.value = StringPool.EMPTY;
+        this.x = x;
+        this.y = y;
+    }
 
     public double doubleValue() {
         return Double.parseDouble(this.value.toString());

+ 1 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SubInterimMeterPaySummary.java

@@ -31,7 +31,7 @@ public class SubInterimMeterPaySummary {
     @JSONField(name = "key_2",label="计量单位",ordinal = 2)
     private String unit;
     /**单价*/
-    @JSONField(name = "key_12",label="单价",ordinal = 2)
+    @JSONField(name = "key_15",label="单价",ordinal = 2)
     private String price;
     /**合同数量*/
     @JSONField(name = "key_3",label="合同数量",ordinal = 3)

+ 12 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/ElementWriter.java

@@ -0,0 +1,12 @@
+package org.springblade.manager.formula;
+
+import org.springblade.manager.dto.FormData;
+/**
+ * @Description  元素内容写入
+ * @Author yangyj
+ * @Date 2024.02.04 17:15
+ **/
+public interface ElementWriter {
+    void write(FormData fd, Object data);
+    void write(FormData fd, Object data,Boolean nullOrBlank);
+}

+ 446 - 57
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorCalc.java

@@ -1,119 +1,508 @@
 package org.springblade.manager.formula.impl;
 
+import cn.hutool.core.util.HashUtil;
 import com.jfireel.expression.Expression;
+import com.mixsmart.utils.CustomFunction;
 import com.mixsmart.utils.FormulaUtils;
+import com.mixsmart.utils.RegexUtils;
 import com.mixsmart.utils.StringUtils;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.apache.poi.ss.usermodel.*;
+import org.springblade.common.utils.BaseUtils;
+import org.springblade.common.utils.CommonUtil;
 import org.springblade.core.tool.utils.CollectionUtil;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.StringPool;
+import org.springblade.manager.dto.Coords;
+import org.springblade.manager.dto.ElementData;
 import org.springblade.manager.dto.FormData;
 import org.springblade.manager.dto.LocalVariable;
 import org.springblade.manager.entity.Formula;
+import org.springblade.manager.formula.ElementWriter;
 import org.springblade.manager.formula.FormulaLog;
+import org.springblade.manager.formula.KeyMapper;
 import org.springblade.manager.formula.NodeTable;
 
 import java.util.*;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.regex.Matcher;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * @author yangyj
  * @Date 2023/12/18 14:01
- * @description TODO
+ * @description 通用计算
  */
 @EqualsAndHashCode(callSuper = true)
 @Data
 public class ExecutorCalc extends FormulaExecutor {
+    public Function<List<String>, List<Map<String,Object>>>  tableExcelInfoFc;
+    public ElementWriter elementWriter;
+    private  String checkTable= StringPool.EMPTY;
+    public static  final String SIMPLE="simple";
+    public static  final String BATCH="batch";
     public ExecutorCalc(TableElementConverter tec) {
         super(tec);
     }
 
-    @Override
-    public void handle() {
-        /*通用计算*/
-        generalCalc(tec);
+    /*判断是否需要批量计算*/
+    private Function<FormData,String> fcDict= fd->{
+        if(fd.getCoordsList().size()>1&&fd.getFormula().getFormula().split("[/+\\-*]").length>1){
+            /*批量计算*/
+            return BATCH;
+        }else{
+            /*默认返回普通计算*/
+             return SIMPLE;
+        }
+    };
+
+    public ExecuteFlow createExecuteFlow(){
+        Optional<NodeTable> op=tec.getTableAll().stream().filter(e->StringUtils.isEquals(1,e.getTableType())).findAny();
+        op.ifPresent(nodeTable -> this.checkTable = nodeTable.getInitTableName());
+        this.elementWriter=new MeterElementWriter();
+        return new ExecuteFlow();
     }
 
-    public void generalCalc(TableElementConverter tec){
-        /*关键内容,常量变量集合,计算时变量集合,依赖元素,公式,输出元素,是否批量运算*/
+    @Override
+    public void handle() {
+        /*关键内容:常量变量集合,计算时变量集合,依赖元素,公式,输出元素,是否批量运算*/
+        /*执行条件:有没有依赖,是否批量执行*/
+        /*写入情况:一对多,一对一,多对一,多对多*/
+        /*并发说明:有依赖关系,需要按顺序执行,否则有可能取不到内容*/
+        ExecuteFlow executeFlow=createExecuteFlow();
         for(FormData fd:tec.formDataList){
             if(fd.verify()){
-                Formula formula =fd.getFormula();
-                String f=formula.getFormula();
-                if(Func.isNotBlank(f)){
-                    try{
-                        Map<String, Object> currentMap = new HashMap<>(tec.constantMap);
-                        List<String>  relyList = fd.getFormula().getRelyList();
-                        if(CollectionUtil.isNotEmpty(relyList)){
-                            /*存在依赖*/
-                            List<FormData>  ele = new ArrayList<>();
-                            relyList.forEach(rely->{
-                                FormData formData=  tec.getFormDataMap().get(rely);
-                                if(formData!=null&&!formData.empty()){
-                                    ele.add(formData);
-                                }
-                            });
-                            /*并不是所有依赖都用FormData表示*/
-                            if(ele.size()<relyList.size()){
-                                tec.getLog().put(FormulaLog.RELY,fd.getCode()+"@"+fd.getEName()+"@"+fd.getFormula().getFormula().replaceAll("'", ""));
-                                continue;
-                            }
-                            FormulaUtils.putEle(f,ele,currentMap,fd);
-                            Object data = Expression.parse(formula.getFormula()).calculate(currentMap);
-                            FormulaUtils.write(fd,data);
-                        }else{
-                            Object data =Expression.parse(formula.getFormula()).calculate(currentMap);
-                            FormulaUtils.write(fd,data);
-                        }
-                    }catch (Exception e){
-                        e.printStackTrace();
-                        tec.getLog().put(FormulaLog.CALC,fd.getEName()+"("+formula+")");
-                    }
-
+                try {
+                    /*自定义脚本预处理*/
+                    preCalc(fd);
+                    /*解析器通用脚本*/
+                    executeFlow.start(fd).depend(dependenceHandler).calculate();
+                }catch (Exception e){
+                    e.printStackTrace();
+                    tec.getLog().put(FormulaLog.CALC,fd.getEName()+"("+fd.getFormula().getFormula()+")");
                 }
-                fd.setUpdate(1);
             }
         }
+    }
+
+    @Data
+    class ExecuteFlow{
+        Map<String,Calculation> calculationMap = new HashMap<>();
+        private Function<FormData,String> pickCalculation;
+        Function<FormData,List<FormData>> dependenceHandler;
+        private FormData formData;
+        private Calculation calculation;
+
+        public ExecuteFlow() {
+            calculationMap.put(SIMPLE,new SimpleCalculation());
+            calculationMap.put(BATCH,new BatchCalculation());
+            pickCalculation=fcDict;
+        }
+
+        public ExecuteFlow start(FormData fd){
+            this.formData=fd;
+            this.calculation= calculationMap.get(pickCalculation.apply(fd));
+            return this;
+        }
+
+        public ExecuteFlow depend(Function<FormData,List<FormData>> depend){
+            this.dependenceHandler=depend;
+            return this;
+        }
+
+        public void calculate(){
+            this.calculation.calculate(this.formData,dependenceHandler);
+        }
+
+
 
     }
 
+   /**元素数据写入类*/
+    static class MeterElementWriter implements ElementWriter {
+        public  void write(FormData fd, Object data){
+            write(fd,data,false);
+        }
+        public  void write(FormData fd, Object data,Boolean containsNull){
+            if(checkEmpty(fd)){
+                /*无定位信息不写入*/
+                return;
+            }
+            try {
+                /*写入前清空内容*/
+                clear(fd);
+                List<Object> values = toList(data,containsNull);
+                /*计量写入数据无效考虑是否存在表页实体,也就不存在超页的概念,只管按需自动增页写人,任何元素初始化都是一页*/
+                int capacity=fd.getCoordsList().size();
+                List<ElementData> eds=  IntStream.range(0,values.size()).boxed().map(i->{
+                    Coords coords = fd.getCoordsList().get(i%capacity);
+                    return new ElementData(i/capacity,values.get(i),coords.getX(),coords.getY());
+                }).collect(Collectors.toList());
+                fd.setValues(eds);
+                fd.setUpdate(1);
+            }catch (Exception e){
+                e.printStackTrace();
+            }
+        }
+        /*检查写入目标地址是否未空*/
+        public  boolean  checkEmpty(FormData fd){
+            return Func.isEmpty(fd.getCoordsList());
+        }
+        /*写入前需要清空原内容*/
+        public void clear(FormData fd){
+            fd.getValues().forEach(t->t.setValue(null));
+        }
+
+        /*原素数据一律用List集合表示*/
+        public List<Object> toList(Object raw,boolean containsNull){
+            List<Object> values= Optional.ofNullable(raw)
+                    .filter(List.class::isInstance)
+                    .map(list -> (List<Object>) list)
+                    .orElseGet(() -> Collections.singletonList(raw));
+            if(containsNull){
+                return values.stream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
+            }
+            return values;
+
+        }
 
-    interface Calculation {
-        void calculate(Formula formula, List<FormData> ele, TableElementConverter tec);
     }
 
-    static class SimpleCalculation implements Calculation{
+    interface Calculation {
+        void calculate(FormData fd, Function<FormData,List<FormData>> dependenceHandler );
+    }
 
+    @Data
+    class SimpleCalculation implements Calculation{
         @Override
-        public void calculate(Formula formula, List<FormData> ele, TableElementConverter tec) {
-
+        public void calculate(FormData fd , Function<FormData,List<FormData>> dependenceHandler ) {
+          List<FormData> relyElements= dependenceHandler.apply(fd);
+             if(relyElements==null){
+                 /*null说明存在依赖却没有匹配成功,可能是内容为空或者找不到*/
+                 return;
+             }
+            String formulaStr=fd.getFormula().getFormula();
+            Map<String, Object> currentMap = new HashMap<>(tec.constantMap);
+            if(relyElements.size()>0) {
+                FormulaUtils.putEle(formulaStr,relyElements,currentMap,fd);
+            }
+            Object data = Expression.parse(formulaStr).calculate(currentMap);
+            elementWriter.write(fd, data);
         }
+
+
     }
 
-    static class BatchCalculation implements  Calculation{
 
+    @Data
+     class BatchCalculation implements Calculation{
         @Override
-        public void calculate(Formula formula, List<FormData> ele, TableElementConverter tec) {
+        public void calculate(FormData fd, Function<FormData,List<FormData>> dependenceHandler ) {
+            List<FormData> relyElements= dependenceHandler.apply(fd);
+            if(relyElements==null){
+                /*null说明存在依赖却没有匹配成功,可能是内容为空或者找不到*/
+                return;
+            }
+            String formulaStr=fd.getFormula().getFormula();
+            LinkedHashMap<String,FormData> fdMap=FormulaUtils.step(relyElements);
+            List<LocalVariable>  local= FormulaUtils.slice2Local(formulaStr,fdMap,tec);
+            if(local.size()>0){
+                List<Object> values = FormulaUtils.slice(local,formulaStr);
+                elementWriter.write(fd,values ,!fd.getTableName().equals(checkTable));
+            }
+        }
+
+    }
+
+
+
+
+
+    Function<FormData,List<FormData>> dependenceHandler = fd->{
+        List<String>  relyList = fd.getFormula().getRelyList();
+        List<FormData> ele = new ArrayList<>();
+        if(CollectionUtil.isNotEmpty(relyList)) {
+            /*存在依赖*/
+            relyList.forEach(rely -> {
+                FormData formData = tec.getFormDataMap().get(rely);
+                if (formData != null && !formData.empty()) {
+                    ele.add(formData);
+                }
+            });
+            /*并不是所有依赖都用FormData表示*/
+            if (ele.size() < relyList.size()) {
+                tec.getLog().put(FormulaLog.RELY, fd.getCode() + "@" + fd.getEName() + "@" + fd.getFormula().getFormula().replaceAll("'", ""));
+                return null;
+            }
+        }
+        return ele;
+    };
+
+
+    /**
+     * 先把公式脚本需要聚合部分预处理
+     * */
+    public void  preCalc(FormData fd){
+        try{
+            Formula formula=fd.getFormula();
+            String f=formula.getFormula();
+            if (f.contains("converge")){
+                Matcher m = RegexUtils.matcher(FC_REG+"(converge)\\(([^)]+)\\)",f);
+                while (m.find()){
+                    List<FormData> target = getFormDataByCode(m.group(2));
+                    Object data =target.stream().flatMap(e->e.getValues().stream()).map(ElementData::getValue).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
+                    f=f.replace(m.group(),tec.putDataWithKey(data));
+                }
+            }
+            if(f.contains("compound")){
+                Matcher m = RegexUtils.matcher(FC_REG+"(compound)\\(([^)]+)\\)",f);
+                while (m.find()){
+                    List<FormData> target = getFormDataByCode(m.group(2));
+                    List<List<Object>> values=target.stream().map(e->e.getValues().stream().map(ElementData::getValue).collect(Collectors.toList())).collect(Collectors.toList());
+                    List<String> eNames=target.stream().map(FormData::getEName).collect(Collectors.toList());
+                    Map<String,List<Object>> data = new LinkedHashMap<>();
+                    for(int i=0;i<eNames.size();i++){
+                        data.put(eNames.get(i),values.get(i));
+                    }
+                    f=f.replace(m.group(),tec.putDataWithKey(data));
+                }
+            }
+            if(f.contains(".option")){
+                /*FC.optionC?是无法嵌套的函数*/
+                Matcher m = RegexUtils.matcher(FC_REG+"optionC?\\(([^)(]+),",f);
+                while (m.find()){
+                    /*  String[] args= m.group(2).split(",");*/
+                    String flag=m.group(1);
+                    /*radio控件,结果只有两个0,1 ,结果作为标识位,且为1才会执第二个参数的回调方法*/
+                    if("OPTION".equals(flag)){
+                        Optional<KeyMapper> kOp=tec.getKeyMappers().stream().filter(e->StringUtils.isEquals(e.getCode(),fd.getCode())).findFirst();
+                        if(kOp.isPresent()){
+                            /*表名+合同段+父节点*/
+                            String findStr="OP['"+fd.getTableName()+"']['"+fd.getKey()+"']['TF']";
+                            flag=StringUtils.handleNull(Expression.parse(findStr).calculate(tec.constantMap));
+                        }
+                    }else if(flag.contains("E[")){
+                        List<FormData> target = getFormDataByCode(flag);
+                        if(target.size()>0){
+                            flag= target.get(0).getValues().stream().map(ElementData::stringValue).filter(StringUtils::isNotEmpty).findFirst().orElse("0");
+                        }
+                    }
+                    if(Func.isBlank(flag)||"OPTION".equals(flag)){
+                        /*默认0*/
+                        flag="0";
+                    }
+                    if(StringUtils.isEquals(flag,1)){
+                        f=f.replace(m.group(),"").replaceAll("\\)$","");
+                    }else{
+                        fd.setFinished(Boolean.TRUE);
+                        f="''";
+                    }
+                }
+            }
+            if(f.contains(".ifelse")){
+                int max=0;
+                do{
+                    Matcher m = RegexUtils.matcher(FC_REG+"(ifelse)\\(([^)]+)\\)",f);
+                    while (m.find()){
+                        String el=m.group();
+                        String pstr=el.replaceAll("^"+FC_REG+"ifelse\\(","").replaceAll("\\)$","");
+                        String[] pa =pstr.split(",");
+                        if(pa.length==3){
+                            Object data = Expression.parse(pa[0]+"?"+pa[1]+":"+pa[2]).calculate(createCurrentMap(el));
+                            f=f.replace(el,tec.putDataWithKey(data));
+                        }else{
+                            f=f.replace(el,"参数格式错误");
+                        }
 
+                    }
+                    max++;
+                }while (f.contains("ifelse")&&max<20);
+            }
+            if(f.contains("avg4segment")){
+                Matcher m = RegexUtils.matcher(FC_REG+"(avg4segment)\\(([^)]+)\\)",f);
+                while (m.find()){
+                    String[] args=m.group(2).split(",");
+                    List<FormData> target = getFormDataByCode(args[0]);
+                    if(!target.isEmpty()){
+                        FormData a=target.get(0);
+                        int n=Math.max(1,a.coordsList.size()/fd.getCoordsList().size());
+                        List<Object> data= CustomFunction.avg4segment(a.getValues().stream().map(ElementData::getValue).collect(Collectors.toList()),n);
+                        f=f.replace(m.group(),tec.putDataWithKey(data));
+                    }
+                }
+            }
+            if(f.contains("skip")){
+                Matcher m = RegexUtils.matcher(FC_REG+"(skip)\\(([^)]+)\\)",f);
+                while (m.find()){
+                    String[] args=m.group(2).split(",");
+                    List<FormData> target = getFormDataByCode(args[0]);
+                    if(!target.isEmpty()){
+                        FormData a=target.get(0);
+                        a.setOffset(StringUtils.handleObj2Integer(args[1]));
+                        f=f.replace(m.group(),args[0]);
+                    }
+                }
+            }
+            formula.setFormula(f);
+            if(f.contains("quantity")){
+                quantity(formula,fd,f);
+            }
+        }catch (Exception e){
+            tec.getLog().put(FormulaLog.OTHER,e.getMessage());
+            e.printStackTrace();
+        }
+    }
+    /*合格率预处理*/
+    public void quantity( Formula formula,FormData fd,String f){
+        /*聚合*/
+        Matcher m = RegexUtils.matcher(FC_REG+"(quantity)\\(([^)]+)\\)",f);
+        while (m.find()) {
+            Object data=null;
+            List<String> codeList = FormulaUtils.getCodeList(m.group(2));
+            {
+                FormData dataFd=tec.formDataMap.get(codeList.get(0));
+                String designStr=codeList.get(1);
+                FormData designFd=tec.formDataMap.get(designStr);
+                String devStr=StringUtils.isNotEmpty(formula.getDev())?formula.getDev():fd.getEAllowDeviation();
+                if(StringUtils.isEmpty(devStr)){
+                    /*数据库找不到的情况就读取Excel*/
+                    if(tec.wkbMap.isEmpty()){
+                        /*初始化*/
+                        List<String> tableNames4Excel=  tec.getFormDataList().stream().filter(FormData::executable).filter(e->e.info().contains("quantity")).map(FormData::getTableName).distinct().collect(Collectors.toList());
+                        if(!tableNames4Excel.isEmpty()){
+                            List<String> ids =tec.getTableAll().stream().filter(e->tableNames4Excel.contains(e.getInitTableName())).map(NodeTable::getPKeyId).map(String::valueOf).collect(Collectors.toList());
+                            //List<Map<String,Object>> listMaps=  this.jdbcTemplate.queryForList("select a.p_key_id pkeyId,a.init_table_name tableName,b.file_url url from m_wbs_tree_contract a join m_excel_tab b on a.excel_id=b.id where a.p_key_id in("+String.join(",",ids)+")");
+                            List<Map<String,Object>> listMaps =tableExcelInfoFc.apply(ids);
+                            listMaps.forEach(mp->{
+                                try {
+                                    Workbook wb = WorkbookFactory.create(Objects.requireNonNull(CommonUtil.getOSSInputStream(StringUtils.handleNull(mp.get("url")))));
+                                    tec.wkbMap.put(mp.get("pkeyId").toString(),wb);
+                                } catch (Exception e) {
+                                    e.printStackTrace();
+                                }
+                            });
+                        }
+                    }
+                    Optional<NodeTable> nodeTableOp =tec.getTableAll().stream().filter(e->e.getInitTableName().equals(fd.getTableName())).findFirst();
+                    if(nodeTableOp.isPresent()){
+                        Workbook wb = tec.wkbMap.get(nodeTableOp.get().getPKeyId().toString());
+                        if(wb!=null){
+                            Cell deCell=null;
+                            Sheet sheet = wb.getSheetAt(0);
+                            outerLoop: for(int y=3;y<35;y++){
+                                for(int x=0;x<35;x++){
+                                    Row row = sheet.getRow(y);
+                                    Cell cell=  row.getCell(x);
+                                    String sv=StringUtils.handleNull(FormulaUtils.getValue(cell)).replaceAll("[^\u4e00-\u9fa5]+","");
+                                    if(sv.contains("规定")&&sv.contains("偏差")){
+                                        deCell=cell;
+                                        break outerLoop;
+                                    }
+                                }
+                            }
+                            if(deCell!=null) {
+                                int min = 0;
+                                Optional<Integer> op = fd.getCoordsList().stream().map(Coords::getY).distinct().min(Comparator.comparingInt(e -> e));
+                                if (op.isPresent()) {
+                                    min = op.get();
+                                }
+                                Row row = sheet.getRow(min);
+                                Cell cell = row.getCell(deCell.getColumnIndex());
+                                devStr = FormulaUtils.getValue(cell).toString();
+                            }
+                        }
+                    }
+                }
+                if(CustomFunction.containsZH(devStr)||StringUtils.isEmpty(devStr)||StringUtils.handleNull(devStr).contains("/")){
+                    devStr="±100000";
+                }
+                if(devStr.contains("E[")){
+                    List<String> codes= getCodeByEl(devStr);
+                    Map<String,Object> map = new HashMap<>();
+                    boolean isNull=false;
+                    for (String c:codes){
+                        FormData ffd= tec.getFormDataMap().get(c);
+                        if(ffd.empty()){
+                            isNull=true;
+                            break;
+                        } else{
+                            map.put("E["+c+"]",ffd.getRawValue().stream().filter(StringUtils::isNotEmpty).findFirst().orElse(null)) ;
+                        }
+                    }
+                    if(isNull){
+                        devStr="±100000";
+                    }
+                    devStr= Arrays.stream(devStr.replaceAll("^\\[|\\]$","").split(",")).map(s->map.getOrDefault(s,s)).map(StringUtils::handleNull).collect(Collectors.joining(","));
+                }
+                /*设计值可以是数值类型,或空(等效0)*/
+                if(dataFd!=null){
+                    List<Object> values= dataFd.getRawValue();
+                    boolean nonNumeric=values.stream().filter(StringUtils::isNotEmpty).anyMatch(e->!StringUtils.isNumber(e));
+                    if(nonNumeric){
+                        data=values.stream().filter(StringUtils::isNotEmpty).count();
+                    }else if(designFd!=null){
+                        if(dataFd.getValues().stream().map(ElementData::getValue).anyMatch(StringUtils::isNotEmpty)&&(designFd.getValues().size()>1||designFd.getValues().stream().map(ElementData::getValue).anyMatch(StringUtils::isEmpty))){
+                            /*多少个设计值暂时默认全部合格,满足绝大部分结果*/
+                            data=dataFd.getValues().stream().map(ElementData::getValue).filter(StringUtils::isNotEmpty).count();
+                        }else{
+                            List<Object>  result =  CustomFunction.b445check(dataFd.getValues().stream().map(ElementData::getValue).collect(Collectors.toList()),designFd.getValues().stream().map(ElementData::getValue).collect(Collectors.toList()),devStr,1 );
+                            data=result.get(1);
+                        }
+                    }else if(BaseUtils.isNumber(designStr)) {
+                        List<Object> result = CustomFunction.b445check(dataFd.getValues().stream().map(ElementData::getValue).collect(Collectors.toList()), 0, devStr, 1);
+                        data = result.get(1);
+                    }
+                }
+            }
+            f = f.replace(m.group(),tec.putDataWithKey(BaseUtils.isNumber(data)?Double.parseDouble(data.toString()):data));
         }
+        fd.getFormula().setFormula(f);
+        formula.setScale(1);
     }
 
-    interface DependenceHandler {
-        boolean handle(String rely, TableElementConverter tec);
+    public List<String> getCodeByEl(String el){
+        List<String> l = new ArrayList<>();
+        if(Func.isNotBlank(el)){
+            Matcher m = FormulaUtils.P.matcher(el);
+            while (m.find()){
+                String tmp =m.group().replaceAll("'","");
+                l.add(tmp);
+            }
+        }
+        return l;
     }
 
-    static class FormDataDependenceHandler implements DependenceHandler {
-        @Override
-        public boolean handle(String rely, TableElementConverter tec) {
-            return false;
+
+    /*根据参数获取所有的元素*/
+    public  List<FormData> getFormDataByCode(String codes){
+        List<FormData> target = new ArrayList<>();
+        String[] tfa=codes.split(",");
+        for(String code:tfa){
+            code=code.replace("E['","").replace("']","");
+            FormData fdt=tec.formDataMap.get(code);
+            if(fdt!=null){
+                target.add(fdt);
+            }
         }
+        return target;
     }
 
-    static class OtherDependenceHandler implements DependenceHandler {
-        @Override
-        public boolean handle(String rely, TableElementConverter tec) {
-            return false;
+    public Map<String,Object> createCurrentMap(String el){
+        Map<String,Object> currentMap= new HashMap<>(tec.constantMap);
+        List<FormData> fds= getFormDataByCode(String.join(",", getCodeByEl(el)));
+        if(Func.isNotEmpty(fds)){
+            Map<String,Object> Em= (Map<String, Object>) currentMap.computeIfAbsent(E, k->new HashMap<String,Object>());
+            fds.forEach(e->{
+                Em.put(e.getCode(),e.getValues().stream().map(ElementData::getValue).collect(Collectors.toList()));
+            });
         }
+        return currentMap;
     }
+
     public void generalCalcOld(TableElementConverter tec){
         String checkTable ="";
         Optional<NodeTable> op=tec.getTableAll().stream().filter(e->StringUtils.isEquals(1,e.getTableType())).findAny();

+ 1 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/FormulaExecutor.java

@@ -16,6 +16,7 @@ public abstract  class   FormulaExecutor implements FormulaHandleChain {
     public final static String WP="WP";
     public final static String CHAIN="trees";
     public final static String FC="FC.";
+    public final static String E="E";
     public final static String TABLE_LIST="TBL";
     public final static String CHECK_ITEMS="CKI";
     public static final Pattern AP=Pattern.compile("(E|WP)\\[([^]']+)]");

+ 12 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java

@@ -1,6 +1,7 @@
 package org.springblade.manager.formula.impl;
 
 
+import cn.hutool.core.util.HashUtil;
 import cn.hutool.log.StaticLog;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
@@ -129,7 +130,14 @@ public class TableElementConverter implements ITableElementConverter {
        }
        return list;
     }
+    /**把计算结果放入固定常量集,创建key来引用*/
+    public String putDataWithKey(Object data){
+        String key ="HA"+ HashUtil.identityHashCode(data);
+        this.constantMap.put(key,data);
+        return key;
+    }
 
+    /**筛选符合条件的元素*/
     public List<FormData> pick(Predicate<FormData> filter){
          return formDataMap.values().stream().filter(filter).collect(Collectors.toList());
     }
@@ -360,11 +368,12 @@ public class TableElementConverter implements ITableElementConverter {
                          String coords =keyMap.get(fd.getKey());
                          if(Func.isNotBlank(coords)){
                              fd.flushCoords(coords);
-                             List<Coords> coordsList = fd.getCoordsList();
+                           /*  List<Coords> coordsList = fd.getCoordsList();
                              List<ElementData> eds = fd.getValues();
                              for(Coords c:coordsList){
-                                 eds.add(new ElementData(0,0,"",c.getX(),c.getY()));
-                             }
+                                 *//*预先初始化一页*//*
+                                 eds.add(new ElementData(c.getX(),c.getY()));
+                             }*/
                          }
                      }
               }

+ 2 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IFormulaDao.java

@@ -26,4 +26,6 @@ public interface IFormulaDao {
     /**获取中间计量申请*/
     Function<Long,List<MeterApply>>  getMeterApplyFc();
 
+
+
 }

+ 7 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaDaoImpl.java

@@ -116,6 +116,13 @@ public class FormulaDaoImpl implements IFormulaDao {
         };
     }
 
+    public Function<List<String>, List<Map<String,Object>>>  getTableExcelInfoFc(){
+        return ids->{
+            String sql="select a.p_key_id pkeyId,a.init_table_name tableName,b.file_url url from m_wbs_tree_contract a join m_excel_tab b on a.excel_id=b.id where a.p_key_id in("+String.join(",",ids)+")";
+            return this.jdbcTemplate.queryForList(sql);
+        };
+    }
+
     public <T> List<T> getEntityList(String sql, Class<T> entityClass) {
         return  jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(entityClass));
     }