From c10a034108c21dc9466b52b534ba94bb5ee9a75f Mon Sep 17 00:00:00 2001 From: xuezhou Date: Tue, 4 Mar 2025 22:16:23 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=B7=BB=E5=8A=A0=E8=A7=84=E5=88=99=E5=88=A4?= =?UTF-8?q?=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sq/customization/bean/CustRuleBean.java | 55 ++ .../sq/customization/bean/DesignPartBean.java | 39 ++ .../dialogs/AutoTransToolDialog.java | 631 ++++++++++++++++-- .../customization/handlers/SampleHandler.java | 2 +- .../customization/util/ConditionChecker.java | 201 ++++++ .../util/StringConditionChecker.java | 122 ++++ 特殊工艺规则配置2.xlsx | Bin 0 -> 17145 bytes 7 files changed, 985 insertions(+), 65 deletions(-) create mode 100644 com.sq.customization/src/com/sq/customization/bean/CustRuleBean.java create mode 100644 com.sq.customization/src/com/sq/customization/bean/DesignPartBean.java create mode 100644 com.sq.customization/src/com/sq/customization/util/ConditionChecker.java create mode 100644 com.sq.customization/src/com/sq/customization/util/StringConditionChecker.java create mode 100644 特殊工艺规则配置2.xlsx diff --git a/com.sq.customization/src/com/sq/customization/bean/CustRuleBean.java b/com.sq.customization/src/com/sq/customization/bean/CustRuleBean.java new file mode 100644 index 0000000..9a4a852 --- /dev/null +++ b/com.sq.customization/src/com/sq/customization/bean/CustRuleBean.java @@ -0,0 +1,55 @@ +package com.sq.customization.bean; + +public class CustRuleBean { + private String SVPPS; + private String FCC; + private String dongtai; + private String FCCDES; + private String KCDS; + private String resourceName; + + private String resourceType; + + public String getSVPPS() { + return SVPPS; + } + public void setSVPPS(String sVPPS) { + SVPPS = sVPPS; + } + public String getFCC() { + return FCC; + } + public void setFCC(String fCC) { + FCC = fCC; + } + public String getDongtai() { + return dongtai; + } + public void setDongtai(String dongtai) { + this.dongtai = dongtai; + } + public String getFCCDES() { + return FCCDES; + } + public void setFCCDES(String fCCDES) { + FCCDES = fCCDES; + } + public String getKCDS() { + return KCDS; + } + public void setKCDS(String kCDS) { + KCDS = kCDS; + } + public String getResourceName() { + return resourceName; + } + public void setResourceName(String resourceName) { + this.resourceName = resourceName; + } + public String getResourceType() { + return resourceType; + } + public void setResourceType(String resourceType) { + this.resourceType = resourceType; + } +} diff --git a/com.sq.customization/src/com/sq/customization/bean/DesignPartBean.java b/com.sq.customization/src/com/sq/customization/bean/DesignPartBean.java new file mode 100644 index 0000000..7740983 --- /dev/null +++ b/com.sq.customization/src/com/sq/customization/bean/DesignPartBean.java @@ -0,0 +1,39 @@ +package com.sq.customization.bean; + +public class DesignPartBean { + private String SVPPS; + private String FCC; + private String dongtai; + private String FCCDES; + private String KCDS; + public String getSVPPS() { + return SVPPS; + } + public void setSVPPS(String sVPPS) { + SVPPS = sVPPS; + } + public String getFCC() { + return FCC; + } + public void setFCC(String fCC) { + FCC = fCC; + } + public String getDongtai() { + return dongtai; + } + public void setDongtai(String dongtai) { + this.dongtai = dongtai; + } + public String getFCCDES() { + return FCCDES; + } + public void setFCCDES(String fCCDES) { + FCCDES = fCCDES; + } + public String getKCDS() { + return KCDS; + } + public void setKCDS(String kCDS) { + KCDS = kCDS; + } +} diff --git a/com.sq.customization/src/com/sq/customization/dialogs/AutoTransToolDialog.java b/com.sq.customization/src/com/sq/customization/dialogs/AutoTransToolDialog.java index f035151..d1cfbfe 100644 --- a/com.sq.customization/src/com/sq/customization/dialogs/AutoTransToolDialog.java +++ b/com.sq.customization/src/com/sq/customization/dialogs/AutoTransToolDialog.java @@ -10,7 +10,9 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; @@ -26,8 +28,12 @@ import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import com.sq.customization.bean.CustRuleBean; +import com.sq.customization.bean.DesignPartBean; +import com.sq.customization.util.ConditionChecker; import com.sq.customization.util.ExcelUtil; import com.sq.customization.util.ProgressCustomDialog; +import com.sq.customization.util.StringConditionChecker; import com.teamcenter.rac.aif.AbstractAIFDialog; import com.teamcenter.rac.aif.kernel.AIFComponentContext; import com.teamcenter.rac.aif.kernel.InterfaceAIFComponent; @@ -36,7 +42,11 @@ import com.teamcenter.rac.cme.kernel.bvr.TCComponentMfgBvrPart; import com.teamcenter.rac.cme.kernel.bvr.TCComponentMfgBvrPlantBOP; import com.teamcenter.rac.cme.kernel.bvr.TCComponentMfgBvrProcessLine; import com.teamcenter.rac.cme.kernel.bvr.TCComponentMfgBvrProcessStation; +import com.teamcenter.rac.kernel.TCComponent; import com.teamcenter.rac.kernel.TCComponentBOMLine; +import com.teamcenter.rac.kernel.TCComponentDataset; +import com.teamcenter.rac.kernel.TCException; +import com.teamcenter.rac.kernel.TCPreferenceService; import com.teamcenter.rac.kernel.TCSession; import com.teamcenter.rac.stylesheet.PropertyTextField; import com.teamcenter.rac.util.ButtonLayout; @@ -57,16 +67,33 @@ public class AutoTransToolDialog extends AbstractAIFDialog { private JButton cancel; private JButton directory; - private Registry registry = Registry.getRegistry(AutoTransToolDialog.class); +// private Registry registry = Registry.getRegistry(AutoTransToolDialog.class); private TCSession session; private InterfaceAIFComponent target; - Map no_load = new HashMap<>(); - Map op_nodesignmap = new HashMap<>(); - public AutoTransToolDialog(Frame fm,InterfaceAIFComponent target) { + private Map no_load = new HashMap<>(); + private Map op_nodesignmap = new HashMap<>(); + private Map DesignPartBeanMap = new HashMap<>(); + private List processrules = new ArrayList<>(); + private List autotoolrules = new ArrayList<>(); + private List Tightenrules = new ArrayList<>(); + private List KCDSrules = new ArrayList<>(); + private List TightenMethodrules = new ArrayList<>(); + private List Torquerules = new ArrayList<>(); + private int times = 0; + public AutoTransToolDialog(Frame fm,InterfaceAIFComponent target,TCSession session) { super(fm); this.target = target; + this.session = session; op_nodesignmap.clear(); no_load.clear(); + DesignPartBeanMap.clear(); + processrules.clear(); + autotoolrules.clear(); + Tightenrules.clear(); + TightenMethodrules.clear(); + KCDSrules.clear(); + Torquerules.clear(); + times = 0; init(); } private void init() { @@ -177,69 +204,95 @@ public class AutoTransToolDialog extends AbstractAIFDialog { MessageBox.post(AutoTransToolDialog.this,"文件路径不存在", "Message", MessageBox.INFORMATION); return; } - if(isValidExcelColumn(idcol) && isValidExcelColumn(svppscol) && isValidExcelColumn(fcccol) - && isValidExcelColumn(fccdescol) && isValidExcelColumn(dongtaicol) && isValidExcelColumn(kcdscol)) { - op_nodesignmap.clear(); - no_load.clear(); - int idcol2 = columnToNumber(idcol.toUpperCase()); - int svppscol2 = columnToNumber(svppscol.toUpperCase()); - int fcccol2 = columnToNumber(fcccol.toUpperCase()); - int fccdescol2 = columnToNumber(fccdescol.toUpperCase()); - int dongtaicol2 = columnToNumber(dongtaicol.toUpperCase()); - int kcdscol2 = columnToNumber(kcdscol.toUpperCase()); - try { - //读取EXCEL - - //先处理选中对象层级有design的工序,获取没有design的工序 - opBOMLineData(target); - if(op_nodesignmap.size() > 0) { - TCComponentBOMLine parent = null; - - if(target instanceof TCComponentMfgBvrProcessStation) { - TCComponentMfgBvrProcessStation station = (TCComponentMfgBvrProcessStation) target; - String id = station.getProperty("bl_item_item_id"); - no_load.put(id, id); - parent = station.parent(); - } - else if(target instanceof TCComponentMfgBvrPlantBOP) { - TCComponentMfgBvrPlantBOP plant = (TCComponentMfgBvrPlantBOP) target; - String id = plant.getProperty("bl_item_item_id"); - no_load.put(id, id); - parent = plant.parent(); - } - else if(target instanceof TCComponentMfgBvrProcessLine) { - TCComponentMfgBvrProcessLine line = (TCComponentMfgBvrProcessLine) target; - String id = line.getProperty("bl_item_item_id"); - no_load.put(id, id); - parent = line.parent(); - } - if(parent != null) { - System.out.println(parent.getClass()+parent.getProperty("bl_indented_title")); - getparent(parent); - } - if(op_nodesignmap.size() > 0) { - System.out.println("整个结构没有匹配的紧固件"); + String[] rule_pref = session.getPreferenceService().getStringArray(TCPreferenceService.TC_preference_site, "cust_rule_excel"); + if(rule_pref == null || rule_pref.length == 0) { + MessageBox.post(AutoTransToolDialog.this,"请检查自定义首选项cust_rule_excel", "Message", MessageBox.INFORMATION); + return; + } + try { + TCComponentDataset dataset = (TCComponentDataset) session.stringToComponent(rule_pref[0]); + File[] files = dataset.getFiles("excel"); + if(files != null || files.length == 0 || !files[0].exists()) { + MessageBox.post(AutoTransToolDialog.this,"请检查自定义首选项cust_rule_excel对应的规则数据集中的文件", "Message", MessageBox.INFORMATION); + return; + } + File excelfile = files[0]; + if(isValidExcelColumn(idcol) && isValidExcelColumn(svppscol) && isValidExcelColumn(fcccol) + && isValidExcelColumn(fccdescol) && isValidExcelColumn(dongtaicol) && isValidExcelColumn(kcdscol)) { + op_nodesignmap.clear(); + no_load.clear(); + DesignPartBeanMap.clear(); + int idcol2 = columnToNumber(idcol.toUpperCase()); + int svppscol2 = columnToNumber(svppscol.toUpperCase()); + int fcccol2 = columnToNumber(fcccol.toUpperCase()); + int fccdescol2 = columnToNumber(fccdescol.toUpperCase()); + int dongtaicol2 = columnToNumber(dongtaicol.toUpperCase()); + int kcdscol2 = columnToNumber(kcdscol.toUpperCase()); + Thread thread = new Thread(){ + public void run(){ + ProgressCustomDialog.lbStatus.setText("正在创建 ...."); + try { + //读取自定义的规则表 + if(times == 0) { + readRuleExcel(excelfile); + times = 1; + } + + //读取EXCEL + readExcel(excel,2,idcol2,svppscol2,fcccol2,fccdescol2,dongtaicol2,kcdscol2); + //先处理选中对象层级有design的工序,获取没有design的工序 + opBOMLineData(target); + if(op_nodesignmap.size() > 0) { + TCComponentBOMLine parent = null; + + if(target instanceof TCComponentMfgBvrProcessStation) { + TCComponentMfgBvrProcessStation station = (TCComponentMfgBvrProcessStation) target; + String id = station.getProperty("bl_item_item_id"); + no_load.put(id, id); + parent = station.parent(); + } + else if(target instanceof TCComponentMfgBvrPlantBOP) { + TCComponentMfgBvrPlantBOP plant = (TCComponentMfgBvrPlantBOP) target; + String id = plant.getProperty("bl_item_item_id"); + no_load.put(id, id); + parent = plant.parent(); + } + else if(target instanceof TCComponentMfgBvrProcessLine) { + TCComponentMfgBvrProcessLine line = (TCComponentMfgBvrProcessLine) target; + String id = line.getProperty("bl_item_item_id"); + no_load.put(id, id); + parent = line.parent(); + } + if(parent != null) { + System.out.println(parent.getClass()+parent.getProperty("bl_indented_title")); + getparent(parent); + } + if(op_nodesignmap.size() > 0) { + System.out.println("整个结构没有匹配的紧固件"); + } + } + + } catch (Exception e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } - } + }; + ProgressCustomDialog.show(thread, "执行中", null, null, null); - } catch (Exception e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); + AutoTransToolDialog.this.dispose(); + } + else { + MessageBox.post(AutoTransToolDialog.this,"请填写正确的列,比如A,B,C..", "Message", MessageBox.INFORMATION); + } - AutoTransToolDialog.this.dispose(); + } catch (TCException e2) { + // TODO Auto-generated catch block + e2.printStackTrace(); } - else { - MessageBox.post(AutoTransToolDialog.this,"请填写正确的列,比如A,B,C..", "Message", MessageBox.INFORMATION); - } - Thread thread = new Thread(){ - public void run(){ - ProgressCustomDialog.lbStatus.setText("正在创建 ...."); - - - } - }; - ProgressCustomDialog.show(thread, "执行中", null, null, null); + //session.queueOperation(operation); } @@ -282,7 +335,279 @@ public class AutoTransToolDialog extends AbstractAIFDialog { if(designchildcom instanceof TCComponentMfgBvrPart) { hasdesign = true; //获取design - + String designid = designchildcom.getProperty("bl_item_item_id"); + String newname = bl_rev_object_name.replaceAll("预紧", "") + .replaceAll("终紧", "") + .replaceAll("紧固", "") + .replaceAll("拧紧", ""); + String key = designid+"|"+newname; + System.out.println("看design是否匹配:"+key); + if(DesignPartBeanMap.containsKey(key)) { + System.out.println("找到匹配的,开始匹配规则"); + DesignPartBean bean = DesignPartBeanMap.get(key); + + //优先执行特殊工艺规则和电动工具新型号规则,若无匹配全量跑后续规则 + boolean processrule = false; + for(int i = 0; i< processrules.size(); i++) { + CustRuleBean rulebean = processrules.get(i); + String rule_svpps = rulebean.getSVPPS(); + boolean is_ok = true; + if(rule_svpps != null && rule_svpps.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_svpps, bean.getSVPPS()); + if(!result) + is_ok = false; + } + String rule_fcc = rulebean.getFCC(); + if(rule_fcc != null && rule_fcc.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_fcc, bean.getFCC()); + if(!result) + is_ok = false; + } + String rule_dongtai = rulebean.getDongtai(); + if(rule_dongtai != null && rule_dongtai.length() > 0) { + String dongtai = bean.getDongtai(); + if(dongtai.length() > 0) { + if(dongtai.contains("N.M")) { + String[] split = dongtai.split("N.M", -1); + if(split!= null && split.length == 2) { + boolean result = ConditionChecker.checkCondition(rule_dongtai, split[1], split[0]); + if(!result) + is_ok = false; + } + } + else { + boolean result = ConditionChecker.checkCondition(rule_dongtai, dongtai,""); + if(!result) + is_ok = false; + } + + + } + else { + is_ok = false; + } + } + + String rule_FCCDESC = rulebean.getFCCDES(); + if(rule_FCCDESC != null && rule_FCCDESC.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_FCCDESC, bl_rev_object_name); + if(!result) + is_ok = false; + } + + if(is_ok) { + //获取资源名称 + processrule = true; + String resourceName = rulebean.getResourceName(); + } + } + boolean autotoolrule = false; + if(!processrule) { + //执行电动工具规则 + for(int i = 0; i< autotoolrules.size(); i++) { + CustRuleBean rulebean = autotoolrules.get(i); + String rule_svpps = rulebean.getSVPPS(); + boolean is_ok = true; + if(rule_svpps != null && rule_svpps.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_svpps, bean.getSVPPS()); + if(!result) + is_ok = false; + } + String rule_fcc = rulebean.getFCC(); + if(rule_fcc != null && rule_fcc.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_fcc, bean.getFCC()); + if(!result) + is_ok = false; + } + + String rule_FCCDESC = rulebean.getFCCDES(); + if(rule_FCCDESC != null && rule_FCCDESC.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_FCCDESC, bl_rev_object_name); + if(!result) + is_ok = false; + } + + if(is_ok) { + //获取资源类型 + autotoolrule = true; + String resourceType = rulebean.getResourceType(); + } + } + } + if(!autotoolrule) { + //拧紧性质规则 + for(int i = 0; i< Tightenrules.size(); i++) { + CustRuleBean rulebean = Tightenrules.get(i); + String rule_svpps = rulebean.getSVPPS(); + boolean is_ok = true; + if(rule_svpps != null && rule_svpps.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_svpps, bean.getSVPPS()); + if(!result) + is_ok = false; + } + + String rule_FCCDESC = rulebean.getFCCDES(); + if(rule_FCCDESC != null && rule_FCCDESC.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_FCCDESC, bl_rev_object_name); + if(!result) + is_ok = false; + } + String rule_dongtai = rulebean.getDongtai(); + if(rule_dongtai != null && rule_dongtai.length() > 0) { + String dongtai = bean.getDongtai(); + if(dongtai.length() > 0) { + if(dongtai.contains("N.M")) { + String[] split = dongtai.split("N.M", -1); + if(split!= null && split.length == 2) { + boolean result = ConditionChecker.checkCondition(rule_dongtai, split[1], split[0]); + if(!result) + is_ok = false; + } + } + else { + boolean result = ConditionChecker.checkCondition(rule_dongtai, dongtai,""); + if(!result) + is_ok = false; + } + + + } + else { + is_ok = false; + } + } + if(is_ok) { + //获取资源名称 + String resourceType = rulebean.getResourceType(); + } + } + //KCDS + for(int i = 0; i< KCDSrules.size(); i++) { + CustRuleBean rulebean = KCDSrules.get(i); + String rule_svpps = rulebean.getSVPPS(); + boolean is_ok = true; + if(rule_svpps != null && rule_svpps.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_svpps, bean.getSVPPS()); + if(!result) + is_ok = false; + } + + String rule_FCCDESC = rulebean.getFCCDES(); + if(rule_FCCDESC != null && rule_FCCDESC.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_FCCDESC, bl_rev_object_name); + if(!result) + is_ok = false; + } + String rule_KCDS = rulebean.getKCDS(); + if(rule_KCDS != null && rule_KCDS.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_KCDS, bean.getKCDS()); + if(!result) + is_ok = false; + } + if(is_ok) { + //获取资源类型 + String resourceType = rulebean.getResourceType(); + } + } + //拧紧方式 + for(int i = 0; i< TightenMethodrules.size(); i++) { + CustRuleBean rulebean = TightenMethodrules.get(i); + String rule_svpps = rulebean.getSVPPS(); + boolean is_ok = true; + if(rule_svpps != null && rule_svpps.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_svpps, bean.getSVPPS()); + if(!result) + is_ok = false; + } + + String rule_FCCDESC = rulebean.getFCCDES(); + if(rule_FCCDESC != null && rule_FCCDESC.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_FCCDESC, bl_rev_object_name); + if(!result) + is_ok = false; + } + String rule_dongtai = rulebean.getDongtai(); + if(rule_dongtai != null && rule_dongtai.length() > 0) { + String dongtai = bean.getDongtai(); + if(dongtai.length() > 0) { + if(dongtai.contains("N.M")) { + String[] split = dongtai.split("N.M", -1); + if(split!= null && split.length == 2) { + boolean result = ConditionChecker.checkCondition(rule_dongtai, split[1], split[0]); + if(!result) + is_ok = false; + } + } + else { + boolean result = ConditionChecker.checkCondition(rule_dongtai, dongtai,""); + if(!result) + is_ok = false; + } + + + } + else { + is_ok = false; + } + } + if(is_ok) { + //获取资源类型 + String resourceType = rulebean.getResourceType(); + } + } + //扭矩值 + + for(int i = 0; i< Torquerules.size(); i++) { + CustRuleBean rulebean = Torquerules.get(i); + String rule_svpps = rulebean.getSVPPS(); + boolean is_ok = true; + if(rule_svpps != null && rule_svpps.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_svpps, bean.getSVPPS()); + if(!result) + is_ok = false; + } + + String rule_FCCDESC = rulebean.getFCCDES(); + if(rule_FCCDESC != null && rule_FCCDESC.length() > 0) { + boolean result = StringConditionChecker.checkCondition(rule_FCCDESC, bl_rev_object_name); + if(!result) + is_ok = false; + } + String rule_dongtai = rulebean.getDongtai(); + if(rule_dongtai != null && rule_dongtai.length() > 0) { + String dongtai = bean.getDongtai(); + if(dongtai.length() > 0) { + if(dongtai.contains("N.M")) { + String[] split = dongtai.split("N.M", -1); + if(split!= null && split.length == 2) { + boolean result = ConditionChecker.checkCondition(rule_dongtai, split[1], split[0]); + if(!result) + is_ok = false; + } + } + else { + boolean result = ConditionChecker.checkCondition(rule_dongtai, dongtai,""); + if(!result) + is_ok = false; + } + + + } + else { + is_ok = false; + } + } + if(is_ok) { + //获取资源类型 + String resourceType = rulebean.getResourceType(); + String resourceName = rulebean.getResourceName(); + } + } + } + } + else { + System.out.println("未找到匹配的"); + } } } if(!hasdesign) { @@ -397,7 +722,185 @@ public class AutoTransToolDialog extends AbstractAIFDialog { String dongtai = ExcelUtil.getStringCellValue(row.getCell(dongtaicol-1)); String kcds = ExcelUtil.getStringCellValue(row.getCell(kcdscol2-1)); System.out.println("id:"+id+" svpps:"+svpps+" fcc:"+fcc+" fccdes:"+fccdes+" dongtai:"+dongtai+" kcds:"+kcds); - + String key = id + "|"+fccdes; + if(!DesignPartBeanMap.containsKey(key)) { + DesignPartBean bean = new DesignPartBean(); + bean.setDongtai(dongtai); + bean.setFCC(fcc); + bean.setFCCDES(fccdes); + bean.setKCDS(kcds); + bean.setSVPPS(svpps); + DesignPartBeanMap.put(key, bean); + } + } + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + private void readRuleExcel(File excelfile) { + Workbook work = null; + try(InputStream is = new FileInputStream(excelfile);){ + if (excelfile.getAbsolutePath().endsWith(".xls")) + work = new HSSFWorkbook(is); + else { + work = new XSSFWorkbook(is); + } + //读取特殊工艺规则sheet + Sheet sheet = work.getSheet("特殊工艺规则"); + System.out.println("特殊工艺规则"); + if(sheet != null) { + int count = sheet.getPhysicalNumberOfRows(); + for(int i = 1; i < count ;i++) { + Row row = sheet.getRow(i); + String svpps = ExcelUtil.getStringCellValue(row.getCell(1)); + String fcc = ExcelUtil.getStringCellValue(row.getCell(2)); + String fccdes = ExcelUtil.getStringCellValue(row.getCell(0)); + String dongtai = ExcelUtil.getStringCellValue(row.getCell(3)); + String resourceName = ExcelUtil.getStringCellValue(row.getCell(4)); + System.out.println("svpps:"+svpps+" fcc:"+fcc+" fccdes:"+fccdes+" dongtai:"+dongtai+" resourceName:"+resourceName); + CustRuleBean bean = new CustRuleBean(); + bean.setDongtai(dongtai); + bean.setFCC(fcc); + bean.setFCCDES(fccdes); + bean.setResourceName(resourceName); + bean.setSVPPS(svpps); + processrules.add(bean); + } + } + else { + System.out.println("没有特殊工艺规则sheet页"); + } + Sheet sheet2 = work.getSheet("电动工具新型号"); + System.out.println("电动工具新型号"); + if(sheet2 != null) { + int count = sheet2.getPhysicalNumberOfRows(); + for(int i = 1; i < count ;i++) { + Row row = sheet2.getRow(i); + String svpps = ExcelUtil.getStringCellValue(row.getCell(1)); + String fcc = ExcelUtil.getStringCellValue(row.getCell(2)); + String fccdes = ExcelUtil.getStringCellValue(row.getCell(0)); + String dongtai = ExcelUtil.getStringCellValue(row.getCell(3)); + String resourceType = ExcelUtil.getStringCellValue(row.getCell(4)); + System.out.println("svpps:"+svpps+" fcc:"+fcc+" fccdes:"+fccdes+" dongtai:"+dongtai+" resourceType:"+resourceType); + CustRuleBean bean = new CustRuleBean(); + bean.setDongtai(dongtai); + bean.setFCC(fcc); + bean.setFCCDES(fccdes); + bean.setResourceType(resourceType); + bean.setSVPPS(svpps); + autotoolrules.add(bean); + } + } + else { + System.out.println("没有电动工具新型号sheet页"); + } + //Tightenrules + Sheet sheet3 = work.getSheet("拧紧性质"); + System.out.println("拧紧性质"); + if(sheet3 != null) { + int count = sheet3.getPhysicalNumberOfRows(); + for(int i = 1; i < count ;i++) { + Row row = sheet3.getRow(i); + String svpps = ExcelUtil.getStringCellValue(row.getCell(1)); +// String fcc = ExcelUtil.getStringCellValue(row.getCell(2)); + String fccdes = ExcelUtil.getStringCellValue(row.getCell(0)); + String dongtai = ExcelUtil.getStringCellValue(row.getCell(3)); + String resourceType = ExcelUtil.getStringCellValue(row.getCell(4)); + System.out.println("svpps:"+svpps+" fccdes:"+fccdes+" dongtai:"+dongtai+" resourceType:"+resourceType); + CustRuleBean bean = new CustRuleBean(); + bean.setDongtai(dongtai); +// bean.setFCC(fcc); + bean.setFCCDES(fccdes); + bean.setResourceType(resourceType); + bean.setSVPPS(svpps); + Tightenrules.add(bean); + } + } + else { + System.out.println("没有拧紧性质sheet页"); + } + + Sheet sheet4 = work.getSheet("KCDS判定"); + System.out.println("KCDS判定"); + if(sheet4 != null) { + int count = sheet4.getPhysicalNumberOfRows(); + for(int i = 1; i < count ;i++) { + Row row = sheet4.getRow(i); + String svpps = ExcelUtil.getStringCellValue(row.getCell(1)); +// String fcc = ExcelUtil.getStringCellValue(row.getCell(2)); + String fccdes = ExcelUtil.getStringCellValue(row.getCell(0)); +// String dongtai = ExcelUtil.getStringCellValue(row.getCell(3)); + String resourceType = ExcelUtil.getStringCellValue(row.getCell(4)); + String KCDS = ExcelUtil.getStringCellValue(row.getCell(6)); + System.out.println("svpps:"+svpps+" fccdes:"+fccdes+" resourceType:"+resourceType+" KCDS:"+KCDS); + CustRuleBean bean = new CustRuleBean(); +// bean.setDongtai(dongtai); +// bean.setFCC(fcc); + bean.setFCCDES(fccdes); + bean.setResourceType(resourceType); + bean.setSVPPS(svpps); + bean.setKCDS(KCDS); + KCDSrules.add(bean); + } + } + else { + System.out.println("没有KCDS判定sheet页"); + } + //TightenMethodrules + Sheet sheet5 = work.getSheet("拧紧方式"); + System.out.println("拧紧方式"); + if(sheet5 != null) { + int count = sheet5.getPhysicalNumberOfRows(); + for(int i = 1; i < count ;i++) { + Row row = sheet5.getRow(i); + String svpps = ExcelUtil.getStringCellValue(row.getCell(1)); +// String fcc = ExcelUtil.getStringCellValue(row.getCell(2)); + String fccdes = ExcelUtil.getStringCellValue(row.getCell(0)); + String dongtai = ExcelUtil.getStringCellValue(row.getCell(3)); + String resourceType = ExcelUtil.getStringCellValue(row.getCell(4)); + System.out.println("svpps:"+svpps+" fccdes:"+fccdes+" dongtai:"+dongtai+" resourceType:"+resourceType); + CustRuleBean bean = new CustRuleBean(); + bean.setDongtai(dongtai); +// bean.setFCC(fcc); + bean.setFCCDES(fccdes); + bean.setResourceType(resourceType); + bean.setSVPPS(svpps); + TightenMethodrules.add(bean); + } + } + else { + System.out.println("没有拧紧方式sheet页"); + } + + Sheet sheet6 = work.getSheet("扭矩值判定"); + System.out.println("扭矩值判定"); + if(sheet6 != null) { + int count = sheet6.getPhysicalNumberOfRows(); + for(int i = 1; i < count ;i++) { + Row row = sheet6.getRow(i); + String svpps = ExcelUtil.getStringCellValue(row.getCell(1)); +// String fcc = ExcelUtil.getStringCellValue(row.getCell(2)); + String fccdes = ExcelUtil.getStringCellValue(row.getCell(0)); + String dongtai = ExcelUtil.getStringCellValue(row.getCell(3)); + String resourceType = ExcelUtil.getStringCellValue(row.getCell(4)); + String resourceName = ExcelUtil.getStringCellValue(row.getCell(5)); + System.out.println("svpps:"+svpps+" fccdes:"+fccdes+" dongtai:"+dongtai+" resourceType:"+resourceType+" resourceName:"+resourceName); + CustRuleBean bean = new CustRuleBean(); + bean.setDongtai(dongtai); +// bean.setFCC(fcc); + bean.setFCCDES(fccdes); + bean.setResourceType(resourceType); + bean.setSVPPS(svpps); + bean.setResourceName(resourceName); + Torquerules.add(bean); + } + } + else { + System.out.println("没有扭矩值判定sheet页"); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block diff --git a/com.sq.customization/src/com/sq/customization/handlers/SampleHandler.java b/com.sq.customization/src/com/sq/customization/handlers/SampleHandler.java index 3efc33e..13364d5 100644 --- a/com.sq.customization/src/com/sq/customization/handlers/SampleHandler.java +++ b/com.sq.customization/src/com/sq/customization/handlers/SampleHandler.java @@ -37,7 +37,7 @@ public class SampleHandler extends AbstractHandler { System.out.println(target[0].getType()); System.out.println(target[0].getClass()); if("Mfg0BvrPlantBOP".equals(target[0].getType()) || "Mfg0BvrProcessLine".equals(target[0].getType()) || "Mfg0BvrProcessStation".equals(target[0].getType())) { - new AutoTransToolDialog(app.getDesktop(),target[0]); + new AutoTransToolDialog(app.getDesktop(),target[0],session); // TCComponentMfgBvrPlantBOP targetline = (TCComponentMfgBvrPlantBOP) target[0]; // try { // AIFComponentContext[] comcontext = targetline.getChildren(); diff --git a/com.sq.customization/src/com/sq/customization/util/ConditionChecker.java b/com.sq.customization/src/com/sq/customization/util/ConditionChecker.java new file mode 100644 index 0000000..7e15344 --- /dev/null +++ b/com.sq.customization/src/com/sq/customization/util/ConditionChecker.java @@ -0,0 +1,201 @@ +package com.sq.customization.util; + +public class ConditionChecker { + + public static void main(String[] args) { + // 示例测试 1 + String condition1 = "%abc & ==5.0 & %xyz"; + String str1 = "This is abc xyz text"; + String range1 = "4.5-6.2"; + boolean result1 = checkCondition(condition1, str1, range1); + System.out.println("条件 1: " + (result1 ? "符合" : "不符合")); + + // 示例测试 2 + String condition2 = "(%text & >5.5 & <=10.0) | %xyz"; + String str2 = "This is text"; + String range2 = "7-8"; // 空字符串 + boolean result2 = checkCondition(condition2, str2, range2); + System.out.println("条件 2: " + (result2 ? "符合" : "不符合")); + + // 示例测试 3 + String condition3 = "<3.0 &=="; + String str3 = ""; + String range3 = ""; + boolean result3 = checkCondition(condition3, str3, range3); + System.out.println("条件 3: " + (result3 ? "符合" : "不符合")); + + // 示例测试 4 + String condition4 = "%abcg|%t"; + String str4 = "abc text"; + String range4 = ""; + boolean result4 = checkCondition(condition4, str4, range4); + System.out.println("条件 4: " + (result4 ? "符合" : "不符合")); + } + + /** + * 检查条件是否符合 + */ + public static boolean checkCondition(String condition, String str, String range) { + condition = condition.trim(); + + // 解析范围 + double[] rangeBounds = parseRange(range); + double min = rangeBounds != null ? rangeBounds[0] : Double.NaN; // 用 NaN 表示无效范围 + double max = rangeBounds != null ? rangeBounds[1] : Double.NaN; + + // 处理括号 + if (condition.startsWith("(")) { + int parenthesesLevel = 1; + int endIndex = -1; + for (int i = 1; i < condition.length(); i++) { + if (condition.charAt(i) == '(') parenthesesLevel++; + else if (condition.charAt(i) == ')') parenthesesLevel--; + if (parenthesesLevel == 0) { + endIndex = i; + break; + } + } + if (endIndex != -1 && endIndex == condition.length() - 1) { + return checkCondition(condition.substring(1, endIndex), str, range); + } + } + + // 处理多个 & 和 | 运算符 + int[] operatorIndices = findAllOuterOperators(condition); + if (operatorIndices.length > 0) { + String[] parts = splitCondition(condition, operatorIndices); + char[] operators = getOperators(condition, operatorIndices); + + boolean result = checkCondition(parts[0], str, range); + int partIndex = 1; + for (int i = 0; i < operators.length; i++) { + boolean nextResult = checkCondition(parts[partIndex++], str, range); + if (operators[i] == '&') { + result = result && nextResult; + } else if (operators[i] == '|') { + result = result || nextResult; + } + } + return result; + } + + // 处理单个条件 + return checkSingleCondition(condition, str, min, max); + } + + /** + * 解析范围字符串,支持小数 + */ + private static double[] parseRange(String range) { + if (range == null || range.isEmpty()) { + return null; // 空字符串返回 null,表示无有效范围 + } + try { + if (range.contains("-")) { + String[] parts = range.split("-"); + double start = Double.parseDouble(parts[0].trim()); + double end = Double.parseDouble(parts[1].trim()); + return new double[]{start, end}; + } else if (range.contains("±")) { + String[] parts = range.split("±"); + double center = Double.parseDouble(parts[0].trim()); + double delta = Double.parseDouble(parts[1].trim()); + return new double[]{center - delta, center + delta}; + } + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { + throw new IllegalArgumentException("无效的范围格式: " + range + ",应为 'x-y' 或 'x±y'"); + } + return null; + } + + /** + * 查找所有最外层的 & 和 | 运算符 + */ + private static int[] findAllOuterOperators(String condition) { + int parenthesesLevel = 0; + java.util.List indices = new java.util.ArrayList<>(); + for (int i = 0; i < condition.length(); i++) { + char c = condition.charAt(i); + if (c == '(') parenthesesLevel++; + else if (c == ')') parenthesesLevel--; + else if (parenthesesLevel == 0 && (c == '&' || c == '|')) indices.add(i); + } + return indices.stream().mapToInt(Integer::intValue).toArray(); + } + + /** + * 根据运算符位置分割条件 + */ + private static String[] splitCondition(String condition, int[] operatorIndices) { + String[] parts = new String[operatorIndices.length + 1]; + int start = 0; + for (int i = 0; i < operatorIndices.length; i++) { + parts[i] = condition.substring(start, operatorIndices[i]).trim(); + start = operatorIndices[i] + 1; + } + parts[operatorIndices.length] = condition.substring(start).trim(); + return parts; + } + + /** + * 获取所有运算符 + */ + private static char[] getOperators(String condition, int[] operatorIndices) { + char[] operators = new char[operatorIndices.length]; + for (int i = 0; i < operatorIndices.length; i++) { + operators[i] = condition.charAt(operatorIndices[i]); + } + return operators; + } + + /** + * 检查单个条件,使用范围的最小值和最大值,支持小数 + */ + private static boolean checkSingleCondition(String condition, String str, double min, double max) { + condition = condition.trim(); + + if (condition.startsWith("!%")) { + String substring = condition.substring(2); + return !str.contains(substring); + } else if (condition.startsWith("%")) { + String substring = condition.substring(1); + return str.contains(substring); + } else if (condition.startsWith(">=")) { + if (Double.isNaN(min)) return false; // 空范围,不符合数字比较 + double value = Double.parseDouble(condition.substring(2)); + return min >= value; + } else if (condition.startsWith("<=")) { + if (Double.isNaN(max)) return false; // 空范围,不符合数字比较 + double value = Double.parseDouble(condition.substring(2)); + return max <= value; + } else if (condition.startsWith(">")) { + if (Double.isNaN(min)) return false; // 空范围,不符合数字比较 + double value = Double.parseDouble(condition.substring(1)); + return min > value; + } else if (condition.startsWith("<")) { + if (Double.isNaN(max)) return false; // 空范围,不符合数字比较 + double value = Double.parseDouble(condition.substring(1)); + return max < value; + } else if (condition.startsWith("==")) { + String operand = condition.substring(2); + try { + if (Double.isNaN(min) || Double.isNaN(max)) return false; // 空范围,不符合数字比较 + double value = Double.parseDouble(operand); + return min == value && max == value; + } catch (NumberFormatException e) { + return str.equals(operand); + } + } else if (condition.startsWith("!=")) { + String operand = condition.substring(2); + try { + if (Double.isNaN(min) || Double.isNaN(max)) return false; // 空范围,不符合数字比较 + double value = Double.parseDouble(operand); + return min != value || max != value; + } catch (NumberFormatException e) { + return !str.equals(operand); + } + } + + return false; + } +} diff --git a/com.sq.customization/src/com/sq/customization/util/StringConditionChecker.java b/com.sq.customization/src/com/sq/customization/util/StringConditionChecker.java new file mode 100644 index 0000000..7e91477 --- /dev/null +++ b/com.sq.customization/src/com/sq/customization/util/StringConditionChecker.java @@ -0,0 +1,122 @@ +package com.sq.customization.util; + +public class StringConditionChecker { + + public static void main(String[] args) { + // 示例测试 + String condition = "%abc & !=def | (%xyz & ==abc)"; // 条件示例 + String str = "This is abc text"; // 目标字符串 + boolean result = checkCondition(condition, str); + System.out.println(result ? "条件符合" : "条件不符合"); + } + + /** + * 检查条件是否符合 + * @param condition 条件字符串 + * @param str 目标字符串 + * @return 是否符合条件 + */ + public static boolean checkCondition(String condition, String str) { + condition = condition.trim(); // 去掉首尾空格 + + // 处理括号 + if (condition.startsWith("(") && condition.endsWith(")")) { + return checkCondition(condition.substring(1, condition.length() - 1), str); + } + + // 处理多个 & 和 | 运算符 + int[] operatorIndices = findAllOuterOperators(condition); + if (operatorIndices.length > 0) { + String[] parts = splitCondition(condition, operatorIndices); + char[] operators = getOperators(condition, operatorIndices); + + boolean result = checkCondition(parts[0], str); + int partIndex = 1; + for (int i = 0; i < operators.length; i++) { + boolean nextResult = checkCondition(parts[partIndex++], str); + if (operators[i] == '&') { + result = result && nextResult; + } else if (operators[i] == '|') { + result = result || nextResult; + } + } + return result; + } + + // 处理单个条件 + return checkSingleCondition(condition, str); + } + + /** + * 查找所有最外层的 & 和 | 运算符 + */ + private static int[] findAllOuterOperators(String condition) { + int parenthesesLevel = 0; + java.util.List indices = new java.util.ArrayList<>(); + for (int i = 0; i < condition.length(); i++) { + char c = condition.charAt(i); + if (c == '(') { + parenthesesLevel++; + } else if (c == ')') { + parenthesesLevel--; + } else if (parenthesesLevel == 0 && (c == '&' || c == '|')) { + indices.add(i); + } + } + int[] result = new int[indices.size()]; + for (int i = 0; i < indices.size(); i++) { + result[i] = indices.get(i); + } + return result; + } + + /** + * 根据运算符位置分割条件 + */ + private static String[] splitCondition(String condition, int[] operatorIndices) { + String[] parts = new String[operatorIndices.length + 1]; + int start = 0; + for (int i = 0; i < operatorIndices.length; i++) { + parts[i] = condition.substring(start, operatorIndices[i]).trim(); + start = operatorIndices[i] + 1; + } + parts[operatorIndices.length] = condition.substring(start).trim(); + return parts; + } + + /** + * 获取所有运算符 + */ + private static char[] getOperators(String condition, int[] operatorIndices) { + char[] operators = new char[operatorIndices.length]; + for (int i = 0; i < operatorIndices.length; i++) { + operators[i] = condition.charAt(operatorIndices[i]); + } + return operators; + } + + /** + * 检查单个条件 + */ + private static boolean checkSingleCondition(String condition, String str) { + condition = condition.trim(); + + // 从长到短检查运算符,避免冲突 + if (condition.startsWith("!%")) { + String substring = condition.substring(2); + return !str.contains(substring); // 不包含 + } else if (condition.startsWith("%")) { + String substring = condition.substring(1); + return str.contains(substring); // 包含 + } else if (condition.startsWith("==")) { + String operand = condition.substring(2); + return str.equals(operand); // 等于 + } else if (condition.startsWith("!=")) { + String operand = condition.substring(2); + return !str.equals(operand); // 不等于 + } + + return false; // 未识别的条件返回 false + } +} + diff --git a/特殊工艺规则配置2.xlsx b/特殊工艺规则配置2.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..0fd39f19ee7c837fdde5f4f6bdb8b4b26d22c571 GIT binary patch literal 17145 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