package com.mixsmart.utils; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.*; import java.awt.Color; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.NumberTickUnit; import org.jfree.chart.axis.TickUnits; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.ValueMarker; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.StandardXYItemRenderer; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.chart.renderer.xy.XYStepRenderer; import org.jfree.chart.title.TextTitle; import org.jfree.data.xy.DefaultXYDataset; import org.jfree.ui.RectangleInsets; import org.jsoup.Jsoup; import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.IoUtil; import org.springblade.core.tool.utils.ResourceUtil; import org.springblade.manager.bean.TableInfo; import org.springblade.manager.dto.Coords; import org.springblade.manager.dto.ElementData; import org.springblade.manager.dto.FormData; import org.springblade.manager.entity.Formula; import java.awt.*; import java.awt.Font; import java.awt.geom.Ellipse2D; import java.io.*; import java.util.*; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import static java.util.regex.Pattern.*; /** * @author yangyj * @Date 2022/7/14 15:55 * @description TODO */ public class FormulaUtils { public static Map triangleSquare(Object ranges){ Map map =new HashMap<>(); if(StringUtils.isEmpty(ranges)){ //z的默认取值范围 ranges="(0,15)"; } Matcher m = RegexUtils.matcher("(\\-?\\d+)(\\D)(\\+?\\d+)",ranges.toString()); if(m.find()) { System.out.println(); int min = StringUtils.handObj2Integer(m.group(1)); int max = StringUtils.handObj2Integer(m.group(3)); Integer[] r = pythagorean(min, max); map.put("X", String.valueOf(r[0])); map.put("Y", String.valueOf(r[1])); map.put("Z", String.valueOf(r[2])); } return map; } /** * @Description 字符串相似度 * @Param [s1, s2] * @return double * @Author yangyj * @Date 2023.04.12 18:01 **/ public static double getJaccardSimilarity(String s1, String s2) { Set set1 = new HashSet<>(); Set set2 = new HashSet<>(); for (char c : s1.toCharArray()) { set1.add(c); } for (char c : s2.toCharArray()) { set2.add(c); } Set intersection = new HashSet<>(set1); intersection.retainAll(set2); Set union = new HashSet<>(set1); union.addAll(set2); return (double) intersection.size() / union.size(); } public static Double similarity(String s1,String s2){ return getJaccardSimilarity(parseItemName(s1),parseItemName(s2)); } /** * result[0]^2+result[1]^2=result[2]^2 result[] 元素均为正整数 */ public static Integer[] pythagorean(Integer min,Integer max){ Integer[] result = null; List list = new ArrayList<>(); for(int i=1;i<=max;i++){ for(int j=1;j<=max;j++){ double tmp = Math.sqrt(Math.pow(i,2)+Math.pow(j,2)); int z= (int) Math.round(tmp); if(mint.setValue(null)); if(data instanceof List){ List values = (List) data; if(!nullOrBlank){ values=values.stream().filter(StringUtils::isNotEmpty).collect(Collectors.toList()); } if(values.size()>fd.getValues().size()){ /*当生成的数据超过实际容量的时候,会自动追加页数*/ if(fd.getCoordsList().size()==1){ if(values.stream().filter(CustomFunction::containsZH).anyMatch(e->e.toString().contains("\n"))){ fd.getValues().get(0).setValue(values.stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining())); }else{ fd.getValues().get(0).setValue(values.stream().map(StringUtils::handleNull).collect(Collectors.joining("、"))); } }else{ // copy(fd,values); for(int n=0;n overList=values.stream().skip(fd.getValues().size()).collect(Collectors.toList()); List coordsList = fd.getCoordsList(); int addPage=(int)Math.ceil((double)overList.size()/(double)coordsList.size()); fd.setAddPages(addPage); ElementData last =fd.getValues().get(fd.getValues().size()-1); int indexBase=last.getIndex()+1; List addList= new ArrayList<>(); for(int i=0;ie.setValue(data)); }else{ fd.getValues().get(0).setValue(data); } } } public static List getTableInfoList(JSONArray dataArray) { if (dataArray != null && !dataArray.isEmpty()) { List result = new ArrayList<>(); for (int m = 0; m < dataArray.size(); m++) { TableInfo tableInfo = new TableInfo(); JSONObject dataInfo2 = dataArray.getJSONObject(m); // tableInfo.setContractId(dataInfo2.getString("contractId")); tableInfo.setPkeyId(dataInfo2.getString("pkeyId")); tableInfo.setProjectId(dataInfo2.getString("projectId")); //huangjn 填报的类型,施工或监理 tableInfo.setClassify(dataInfo2.getString("classify")); //设置首件信息 setFirstData(dataInfo2, tableInfo); // //设置日志信息 setTheLogData(dataInfo2, tableInfo); dataInfo2.fluentRemove("contractId") .fluentRemove("pkeyId") .fluentRemove("p_key_id") .fluentRemove("projectId") .fluentRemove("classify") .fluentRemove("pickerKey") .fluentRemove("id") .fluentRemove("isFirst") .fluentRemove("firstNodeId") .fluentRemove("isTheLog") .fluentRemove("theLogId") .fluentRemove("linkTabIds") .fluentRemove("recordTime") .fluentRemove("businessId") .fluentRemove("sourceUrl") .fluentRemove("pdfUrl") .fluentRemove("firstFileName") .fluentRemove(""); // 计算数据 LinkedHashMap> dataMap = dataInfo2.keySet().stream().filter(e -> e.contains("__")).collect(Collectors.groupingBy(e -> e.split("__")[0], LinkedHashMap>::new, Collectors.toList())); LinkedHashMap dataMap2 = new LinkedHashMap<>(); // 字段组合 for (String k : dataMap.keySet()) { if (dataMap.get(k).size() > 1 && !dataMap.get(k).contains("000Z")) { String[] ziduan = dataMap.get(k).toArray(new String[]{}); String temp = ""; for (int i = 0; i < ziduan.length - 1; i++) { for (int j = 0; j < ziduan.length - i - 1; j++) { Integer tr = Integer.parseInt((ziduan[j].split("__")[1]).split("_")[0]); Integer td = Integer.parseInt(ziduan[j].split("__")[1].split("_")[1]); Integer tr_1 = Integer.parseInt(ziduan[j + 1].split("__")[1].split("_")[0]); Integer td_1 = Integer.parseInt(ziduan[j + 1].split("__")[1].split("_")[1]); if (tr > tr_1 && td == td_1) { //纵向排序 temp = ziduan[j]; ziduan[j] = ziduan[j + 1]; ziduan[j + 1] = temp; } } } String lastStr = dataInfo2.getString(ziduan[0]) + "_^_" + ziduan[0].split("__")[1]; for (int i = 1; i < ziduan.length; i++) { String keyData = dataInfo2.getString(ziduan[i]); if (!keyData.equals("")) { lastStr += "☆" + dataInfo2.getString(ziduan[i]) + "_^_" + ziduan[i].split("__")[1]; } } dataMap2.put(k, lastStr); } else { String dataVal = dataInfo2.getString(dataMap.get(k).get(0)); dataMap2.put(k, dataVal + "_^_" + dataMap.get(k).get(0).split("__")[1]); } } dataMap2.put("p_key_id", tableInfo.getPkeyId()); tableInfo.setDataMap(dataMap2); result.add(tableInfo); } return result; } return null; } public static void setFirstData(JSONObject dataInfo2, TableInfo tableInfo) { //huangjn 判断是否是首件 if (dataInfo2.containsKey("isFirst")) { tableInfo.setIsFirst(dataInfo2.getString("isFirst")); } //huangjn 判断是否是首件 //首件资料绑定的节点 if (dataInfo2.containsKey("firstNodeId")) { tableInfo.setFirstNodeId(dataInfo2.getString("firstNodeId")); } //首件ID(编辑时有值,新增时为空) if (dataInfo2.containsKey("firstId")) { tableInfo.setFirstId(dataInfo2.getString("firstId")); } //源文件 if (dataInfo2.containsKey("sourceUrl")) { tableInfo.setSourceUrl(dataInfo2.getString("sourceUrl")); } //pdfUrl if (dataInfo2.containsKey("pdfUrl")) { tableInfo.setPdfUrl(dataInfo2.getString("pdfUrl")); } //文件名称 if (dataInfo2.containsKey("firstFileName")) { tableInfo.setFirstFileName(dataInfo2.getString("firstFileName")); } //关联的信息 if (dataInfo2.containsKey("linkProcessList")) { tableInfo.setLinkProcessList(dataInfo2.getJSONArray("linkProcessList")); } } /** * 设置日志信息 */ public static void setTheLogData(JSONObject dataInfo2, TableInfo tableInfo) { //huangjn 判断是否是日志 if (dataInfo2.containsKey("isTheLog")) { tableInfo.setIsTheLog(dataInfo2.getString("isTheLog")); } //huangjn 判断是否是日志 //huangjn 日志ID if (dataInfo2.containsKey("theLogId")) { tableInfo.setTheLogId(dataInfo2.getString("theLogId")); } //huangjn 日志ID //huangjn 日志勾选的工序 if (dataInfo2.containsKey("linkTabIds")) { tableInfo.setLinkTabIds(dataInfo2.getJSONArray("linkTabIds")); } //huangjn 日志勾选的工序 //huangjn 日志所选时间 if (dataInfo2.containsKey("recordTime")) { tableInfo.setRecordTime(dataInfo2.getString("recordTime")); } //huangjn 日志所选时间 //huangjn 每份填报数据的id,目前日志专用 if (dataInfo2.containsKey("id")) { tableInfo.setBusinessId(dataInfo2.getString("id")); } //huangjn 每份填报数据的id,目前日志专用 } /**从元素名称中解析项目名称*/ public static String parseItemName(String eName){ if (StringUtils.isEmpty(eName)) { return eName; } String str = eName.replaceAll("\\s", ""); Pattern pattern = compile("[((_]"); String[] candidate = pattern.split(str); String regex = "[^\\u4e00-\\u9fa5]+"; Pattern p = compile(regex); return Arrays.stream(candidate) .filter(s -> !isContainKeywords(s)) .map(s -> filterString(s, p)) .collect(Collectors.joining()); } private static String filterString(String s, Pattern p) { Matcher matcher = p.matcher(s); return matcher.replaceAll("").replaceAll(getRegex(), "").replaceAll("(设计|合格).*",""); } private static String getRegex() { return "(在合格标准内|满足设计要求|质量评定|评定|判定|项目|总数|抽测|实测|偏差|尺量)"; } private static boolean isContainKeywords(String s) { List keywords = Arrays.asList( "每", "个","附录","抽查","测","求","小于","大于","检查","仪","按"); return keywords.stream().anyMatch(s::contains); } /** * @Description 深度拷贝 * @Param [originalList] * @return java.util.List * @Author yangyj * @Date 2023.04.28 14:18 **/ public static List copyList(List originalList) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(originalList); oos.close(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); @SuppressWarnings("unchecked") List copiedList = (List) ois.readObject(); ois.close(); return copiedList; } catch (Exception e) { e.printStackTrace(); } return null; } /** * @Description Poi 动态执行公式 测试 * @Param [url] * @Author yangyj * @Date 2023.05.05 14:28 **/ public static void evaluateFormulaCell(String url) { try { url="C:/Users/yangyj/Desktop/test.xlsx"; Workbook workbook = WorkbookFactory.create(new File(url)); Sheet sheet = workbook.getSheetAt(0); Cell cell = sheet.getRow(0).getCell(0); FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator(); CellType cellType = evaluator.evaluateFormulaCellEnum(cell); if (cellType == CellType.NUMERIC) { double value = cell.getNumericCellValue(); System.out.println("公式计算结果:" + value); } else if (cellType == CellType.STRING) { String value = cell.getStringCellValue(); System.out.println("公式计算结果:" + value); } cell.setCellFormula("B1+C1+D1"); evaluator.clearAllCachedResultValues(); cellType = evaluator.evaluateFormulaCellEnum(cell); if (cellType == CellType.NUMERIC) { double value = cell.getNumericCellValue(); System.out.println("公式计算结果:" + value); } else if (cellType == CellType.STRING) { String value = cell.getStringCellValue(); System.out.println("公式计算结果:" + value); } }catch (IOException | InvalidFormatException e){ e.printStackTrace(); } } public static Map getElementCell(String uri) { try { return Jsoup.parse(IoUtil.readToString(new FileInputStream(ResourceUtil.getFile(uri)))) .select("table").first() .select("tr").stream() .flatMap(tr->tr.select("td").stream()) .filter(d->!d.children().isEmpty()) .map(d->d.children().get(0)).map(d->d.attr("keyname")).filter(StringUtils::isNotEmpty).map(e->e.split("__")) .collect( Collectors.toMap( b -> b[0], b -> b[1], (v1, v2) -> v1 + ";" + v2 ) ); }catch (Exception e){ e.printStackTrace(); return new HashMap<>(); } } public static List itemNames =Arrays.asList( "" ,"压 实 度 (%)下路床 特重、极重交通荷载等级 设计值" ,"1△_压 实 度 (%)_下路床_轻、中及重交通 荷载等级_0.3m~0.8m_≧96_≧95_≧94_实测值或实测偏差值" ,"1△_压 实 度 (%)_下路提_轻、中及重交通 荷载等级_>1.5m_≧93_≧92_≧90_实测值或实测偏差值" ,"1△_压 实 度 (%)_上路提_轻、中及重交通 荷载等级_0.8m~1.5m_≧94_≧94_≧93_实测值或实测偏差值" ,"压 实 度 (%)下路提 轻、中及重交通荷载等级 设计值" ,"压 实 度 (%)下路床 特重、极重交通荷载等级 合格率" ,"压 实 度 (%)下路提 轻、中及重交通荷载等级\t合格率" ,"5△_保护层 厚度 (mm)_基础、锚碇、墩台身、墩柱_±10_实测值或实测偏差值" ,"钢筋骨架尺寸宽、高或直径 (mm)_尺量:按骨架总数30%抽测_±5_实测值或实测偏差值" ,"钢筋骨架尺寸长 (mm)_±10_尺量:按骨架总数30%抽测_实测值或实测偏差值" , "受力钢筋间距 (mm)同排 梁、板、拱肋及拱上建筑 设计值" ,"受力钢筋间距 (mm)同排 梁、板、拱肋及拱上建筑 合格率" ," 箍筋、构造钢筋、螺旋筋间距(mm) 设计值" ,"箍筋、构造钢筋、螺旋筋间距(mm) 合格率" ,"实测项目_桩位 (mm)_群桩_≤100_质量评定_合格判定" ,"实测项目_桩位 (mm)_群桩_≤100_实测值或实测偏差值" ,"实测项目_桩位 (mm)_排架桩_实测值或实测偏差值" ,"实测项目_桩位 (mm)_排架桩_质量评定_合格判定" ,"实测项目_桩位 (mm)_群桩_≤100_质量评定_合格率(%)" ,"实测项目_桩位 (mm)_排架桩_质量评定_合格率(%)" ,"3△_支座高程(mm)_满足设计要求;设 计未要求时±5_水准仪:测每支座中心线_实测值或实测偏差值" ,"基底承载力(KPa)_不小于设计_直观或动力触探试验_实测值或实测偏差值" ,"实 测 项 目_花卉数量_满足设计要求_实测值或实测偏差值" ,"实 测 项 目_2△_草坪、草本地被覆盖率(%)_取弃土场绿 地_≥90_实测值或实测偏差值" ,"轴线偏位(mm)_全站仪:20m检查3点_实测值或实测偏差值" ,"1△_基材混合物喷射厚度(mm)_设计厚度±10_实测值或实测偏差值" ,"1△_混凝土强度 (MPA)_在合格标准内_按附录D检查_实测值或实测偏差值" ); public static void mainOo(String[] args) { itemNames.stream().map(FormulaUtils::parseItemName).forEach(System.out::println); } // public static void mainXy(String[] args) { // DefaultXYDataset dataset = new DefaultXYDataset(); // double[][] data = { { 1.0, 2.0, 3.0 }, { 4.0, 5.0, 6.0 } }; // dataset.addSeries("Series 1", data); // // JFreeChart chart = ChartFactory.createScatterPlot( // "测试散点图", // 标题 // "X", // 横轴标题 // "Y", // 纵轴标题 // dataset, // 数据集 // PlotOrientation.VERTICAL, // 图表方向 // true, // 是否显示图例 // false, // 是否生成工具提示 // false // 是否生成URL链接 // ); // // 设置字体 // Font titleFont = new Font("SimSun", Font.PLAIN, 18); // 指定使用宋体字体 // Font axisFont = new Font("SimSun", Font.PLAIN, 12); // 指定使用宋体字体 // // // 设置标题字体 // TextTitle title = chart.getTitle(); // title.setFont(titleFont); // XYPlot plot = (XYPlot) chart.getPlot(); // plot.setBackgroundPaint(Color.WHITE); // plot.getRenderer().setSeriesShape(0, new Ellipse2D.Double(-4, -4, 8, 8)); // plot.getRenderer().setSeriesPaint(0, Color.BLUE); // // 自定义 X 轴刻度 // NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis(); // domainAxis.setTickUnit(new NumberTickUnit(1)); // 设置刻度间隔 // domainAxis.setRange(0.0, 7.5); // 设置轴的范围 // // // 自定义 Y 轴刻度 // NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); // // rangeAxis.setTickUnit(NumberAxis.createStandardTickUnits().get(0)); // 设置刻度间隔 // rangeAxis.setRange(0.0, 7.0); // 设置轴的范围 // // // 添加横杠 // for(int i=1;i<5;i++){ // double value = i; // 横杠的位置 // ValueMarker marker = new ValueMarker(value); // marker.setPaint(Color.BLUE); // 横杠的颜色 // plot.addRangeMarker(marker); // } // ChartPanel chartPanel = new ChartPanel(chart); // chartPanel.setPreferredSize(new Dimension(500, 400)); // // // // 保存图表为图片 // try { // int width = 800; // int height = 600; // ChartUtilities.saveChartAsPNG(new File("C:/Users/yangyj/Desktop/Swap_space/poi_statistics.png"), chart, width, height); // // } catch (IOException e) { // e.printStackTrace(); // } // // // } }