commit 6e6a23c92154d6602edd95b657d61761c6aa048b Author: wangtao Date: Fri Aug 26 15:05:17 2022 +0800 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..6e155bd --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +行列扩展辅助变更 + +背景: + + 模板开发过程中经常遇到插入删除行列的操作,而模板中的一些配置 比如【单元格-自定义显示值】、【web属性事件-参数】、【条件属性-超链/控件】、【js-getCellValue(x,x,x)】中的单元格,并不会自动变更, + 需要手动检查并修改,这个过程中往往会因为漏改或改错某个地方导致模板结果出错; + + 在此基础上,提供一个工具,可以实现自动扩展,并实现所有相关单元格都自动变更 + +使用方式: + + 1、插件安装后,打开设计器,菜单栏会多出一个【闪电】按钮 + 2、点击按钮,会打开一个页面,显示正在编辑的模板 + 3、模板中会显示当前编辑的是哪个报表块 + 如果是多sheet,会显示是第几个sheet(从0开始); + 如果是聚合报表,会显示报表块block的名称; + 如果是决策报表,会显示报表块report的名称 + 4、选择需要增删的行列,点击“一键替换”,就会将扩展后的模板,拷贝并重命名一份,在原模板同路径下 + 5、每次只能对一个报表块进行扩展,如需操作其它模块,在设计器中选中后,再次点击【闪电】按钮即可 + + +示例: + ![Image text](https://fanruan-dump.oss-cn-shanghai.aliyuncs.com/others/pic/1.png) . + ![Image text](https://fanruan-dump.oss-cn-shanghai.aliyuncs.com/others/pic/2.png) . + ![Image text](https://fanruan-dump.oss-cn-shanghai.aliyuncs.com/others/pic/3.png) + \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..2b364e7 --- /dev/null +++ b/build.gradle @@ -0,0 +1,125 @@ + +apply plugin: 'java' + + +ext { + /** + * 项目中依赖的jar的路径 + * 1.如果依赖的jar需要打包到zip中,放置在lib根目录下 + * 2.如果依赖的jar仅仅是编译时需要,防止在lib下子目录下即可 + */ + libPath = "$projectDir/../webroot/WEB-INF/lib" + + /** + * 是否对插件的class进行加密保护,防止反编译 + */ + guard = false + + def pluginInfo = getPluginInfo() + pluginPre = "fine-plugin" + pluginName = pluginInfo.id + pluginVersion = pluginInfo.version + + outputPath = "$projectDir/../webroot/WEB-INF/plugins/plugin-" + pluginName + "-1.0/classes" +} + +group = 'com.fr.plugin' +version = '10.0' +sourceCompatibility = '8' + +sourceSets { + main { + java.outputDir = file(outputPath) + output.resourcesDir = file(outputPath) + } +} + +ant.importBuild("encrypt.xml") +//定义ant变量 +ant.projectDir = projectDir +ant.references["compile.classpath"] = ant.path { + fileset(dir: libPath, includes: '**/*.jar') + fileset(dir: ".",includes:"**/*.jar" ) +} + +classes.dependsOn('clean') + +task copyFiles(type: Copy,dependsOn: 'classes'){ + from outputPath + into "$projectDir/classes" +} + +task preJar(type:Copy,dependsOn: guard ? 'compile_encrypt_javas' : 'compile_plain_javas'){ + from "$projectDir/classes" + into "$projectDir/transform-classes" + include "**/*.*" +} +jar.dependsOn("preJar") + +task makeJar(type: Jar,dependsOn: preJar){ + from fileTree(dir: "$projectDir/transform-classes") + baseName pluginPre + appendix pluginName + version pluginVersion + destinationDir = file("$buildDir/libs") + + doLast(){ + delete file("$projectDir/classes") + delete file("$projectDir/transform-classes") + } +} + +task copyFile(type: Copy,dependsOn: ["makeJar"]){ + from "$buildDir/libs" + from("$projectDir/lib") { + include "*.jar" + } + from "$projectDir/plugin.xml" + into file("$buildDir/temp/plugin") +} + +task zip(type:Zip,dependsOn:["copyFile"]){ + from "$buildDir/temp/plugin" + destinationDir file("$buildDir/install") + baseName pluginPre + appendix pluginName + version pluginVersion +} + +//控制build时包含哪些文件,排除哪些文件 +processResources { +// exclude everything +// 用*.css没效果 +// exclude '**/*.css' +// except this file +// include 'xx.xml' +} + +/*读取plugin.xml中的version*/ +def getPluginInfo(){ + def xmlFile = file("plugin.xml") + if (!xmlFile.exists()) { + return ["id":"none", "version":"1.0.0"] + } + def plugin = new XmlParser().parse(xmlFile) + def version = plugin.version[0].text() + def id = plugin.id[0].text() + return ["id":id,"version":version] +} + +repositories { + mavenLocal() + maven { + url = uri('http://mvn.finedevelop.com/repository/maven-public/') + } +} + +dependencies { + //使用本地jar + implementation fileTree(dir: 'lib', include: ['**/*.jar']) + implementation fileTree(dir: libPath, include: ['**/*.jar']) +} + +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} \ No newline at end of file diff --git a/build/install/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.zip b/build/install/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.zip new file mode 100644 index 0000000..9e61ae3 Binary files /dev/null and b/build/install/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.zip differ diff --git a/build/libs/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.jar b/build/libs/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.jar new file mode 100644 index 0000000..6e35a56 Binary files /dev/null and b/build/libs/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.jar differ diff --git a/build/temp/plugin/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.jar b/build/temp/plugin/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.jar new file mode 100644 index 0000000..6e35a56 Binary files /dev/null and b/build/temp/plugin/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.jar differ diff --git a/build/temp/plugin/plugin.xml b/build/temp/plugin/plugin.xml new file mode 100644 index 0000000..88b4ae6 --- /dev/null +++ b/build/temp/plugin/plugin.xml @@ -0,0 +1,22 @@ + + + com.fr.plugin.cafe_expand + + yes + no + 1.0.0 + 10.0 + 2020-01-01 + crm + + + + + + + + + + + + \ No newline at end of file diff --git a/build/tmp/makeJar/MANIFEST.MF b/build/tmp/makeJar/MANIFEST.MF new file mode 100644 index 0000000..59499bc --- /dev/null +++ b/build/tmp/makeJar/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/encrypt.xml b/encrypt.xml new file mode 100644 index 0000000..1401cd1 --- /dev/null +++ b/encrypt.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..88b4ae6 --- /dev/null +++ b/plugin.xml @@ -0,0 +1,22 @@ + + + com.fr.plugin.cafe_expand + + yes + no + 1.0.0 + 10.0 + 2020-01-01 + crm + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/cafe_expand/designerhelp/JumpToAnalysis.java b/src/main/java/com/fr/plugin/cafe_expand/designerhelp/JumpToAnalysis.java new file mode 100644 index 0000000..18c4f6f --- /dev/null +++ b/src/main/java/com/fr/plugin/cafe_expand/designerhelp/JumpToAnalysis.java @@ -0,0 +1,115 @@ +package com.fr.plugin.cafe_expand.designerhelp; + +import com.fr.design.fun.impl.AbstractDsinFrameUpButtonProvider; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JForm; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.JWorkBook; +import com.fr.design.utils.DesignUtils; +import com.fr.general.IOUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.plugin.cafe_expand.function.UnitTools; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.report.elementcase.TemplateElementCase; +import com.fr.report.poly.PolyECBlock; +import com.fr.third.springframework.util.FileCopyUtils; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; + +/** + * 设计器工具栏添加按钮 跳转到检测模板 + * */ +@EnableMetrics +public class JumpToAnalysis extends AbstractDsinFrameUpButtonProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public UIButton[] getUpButtons(int menuState) { + UIButton btn = new UIButton(IOUtils.readIcon("/com/fr/design/images/m_web/cache.png")); + btn.setToolTipText(InterProviderFactory.getProvider().getLocText("行列扩展分析")); + btn.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + JTemplate template = DesignerContext.getDesignerFrame().getSelectedJTemplate(); + String filePath= template.getPath().replace("reportlets/",""); + + String position=""; + + if( template instanceof JWorkBook){ + TemplateElementCase wb=((JWorkBook) template).getEditingElementCase(); + int sheetNum=template.getEditingReportIndex(); + position="sheet:"+sheetNum; + String sheetKind=wb.getClass().toString(); + + if(sheetKind.contains("poly")) + { + PolyECBlock block = (PolyECBlock) wb; + position=position+",blockName:"+block.getBlockName(); + } + } + else if(template instanceof JForm) + position="frm:"+template.getSelectElementCase().getWidgetName(); + + visitTc(filePath,position); + } + }); + return new UIButton[]{ + btn + }; + } + + public static void visitTc(String path,String position) + { + copyRvealFile(); + + String route="/view/report"; + ArrayList parameter = new ArrayList(); + ArrayList parameter_value = new ArrayList(); + parameter.add("viewlet"); + parameter_value.add("testcase/expand_analysis.cpt"); + + parameter.add("filePath"); + parameter_value.add(path); + + parameter.add("position"); + parameter_value.add(position); + + parameter.add("op"); + parameter_value.add("write"); + + DesignUtils.visitEnvServerByParameters(route, (String[])parameter.toArray(new String[0]), (String[])parameter_value.toArray(new String[0])); + } + + + /** + * 拷贝插件中的模板到报表目录下 + * */ + public static void copyRvealFile() + { + String path=JumpToAnalysis.class.getClass().getResource("/").getPath(); + path=path.substring(0, path.indexOf("WEB-INF") + 7) + "/reportlets/testcase/expand_analysis.cpt"; + + File f=new File(path); + if(!f.exists()) { + f.getParentFile().mkdir(); + String str = null; + try { + str = FileCopyUtils.copyToString(new InputStreamReader(JumpToAnalysis.class.getClassLoader().getResourceAsStream("expand_analysis.cpt"), "utf-8")); + + UnitTools.writeToMb(str, path); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/cafe_expand/function/DoExpandFile.java b/src/main/java/com/fr/plugin/cafe_expand/function/DoExpandFile.java new file mode 100644 index 0000000..497c99a --- /dev/null +++ b/src/main/java/com/fr/plugin/cafe_expand/function/DoExpandFile.java @@ -0,0 +1,615 @@ +package com.fr.plugin.cafe_expand.function; + +import com.fr.general.ComparatorUtils; +import com.fr.plugin.transform.FunctionRecorder; +import com.fr.script.AbstractFunction; +import com.fr.stable.StringUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import java.io.File; +import java.io.FileOutputStream; +import java.text.SimpleDateFormat; +import java.util.*; + +@FunctionRecorder(localeKey="FS_PLUGIN_CAFE_EXPAND") +public class DoExpandFile extends AbstractFunction { + public static Map> colExpandMap=new HashMap(); + public static Map> rowExpandMap=new HashMap(); + + public Object run(Object[] arg) { + + String result="模板文件不存在"; + String path=this.getClass().getResource("/").getPath(); + path=path.substring(0, path.indexOf("WEB-INF") + 7) + "/reportlets"; + + String filepath=arg[0].toString(); + String position=arg[1].toString(); + String colexpand=arg[2].toString(); + String rowexpand=arg[3].toString(); + path=path+"/"+filepath; + + File f= new File(path); + if(f.exists()) { + + Map colMap = getMap(colexpand); + Map rowMap = getMap(rowexpand); + colExpandMap.put(path, colMap); + rowExpandMap.put(path, rowMap); + + String newPath = getNewPath(path); + Element ele = start(path, position); + try { + FileOutputStream out = new FileOutputStream(newPath, true); + out.write(ele.asXML().getBytes("utf-8")); + out.flush(); + out.close(); + + result = newPath.substring(newPath.indexOf("reportlets") + 11); + rowExpandMap.remove(path); + colExpandMap.remove(path); + } catch (Exception e) { + result = e.getMessage(); + } + } + return result; + } + + private static Element start(String filePath,String position) + { + Element root = UnitTools.getRootEle(filePath); + int sheetNum=0; + + if(filePath.contains(".cpt")) + { + //position格式 sheet:1,blockName:block1 + String sheetArr[]=position.split(","); + sheetNum=Integer.parseInt(sheetArr[0].split(":")[1]); + + int i=0; + List sheetReports = root.elements(); + for (Element reportEle : sheetReports) { + String className = reportEle.attributeValue("class"); + if ("Report".equals(reportEle.getName()) && className.contains("WorkSheet")) { + if(i==sheetNum) {//只分析当前编辑的sheet页 + if (className.contains("PolyWorkSheet"))//聚合报表 + { + String editBlock=sheetArr[1].split(":")[1]; + + List polyReports = reportEle.elements(); + for (Element polyEle : polyReports) { + if (polyEle.getName().equals("Block")) { + String blockName = ""; + try { + blockName = polyEle.element("PECBAttr").attributeValue("blockName"); + } catch (Exception e) { + blockName = polyEle.element("PCBAttr").attributeValue("blockName"); + } + + if(ComparatorUtils.equals(editBlock,blockName)) {//只分析当前编辑的block + String bolckClass = polyEle.attributeValue("class"); + if (!bolckClass.contains("PolyChartBlock")) + doExpandCafe(polyEle,filePath); + break; + } + } + } + } else//普通报表 + doExpandCafe(reportEle,filePath); + + break; + } + i++; + } + } + } + else + { + Element Layout=root.element("Layout"); + if(Layout!=null)////解析报表主体 + { + String arr[]=position.split(";");//frm:report0 + if(ComparatorUtils.equals(arr[1],"frm")) + anaFrm(Layout,arr[1],filePath); + } + } + + //填报属性替换单元格 + Element webEle=root.element("ReportWebAttr"); + if(webEle!=null) + analysisEle(webEle,filePath,sheetNum); + + return root; + } + + + + + + /** + * 解析 决策报表 + * */ + private static void anaFrm(Element rootEle,String reportName,String filePath) + { + Element centerEle=rootEle; + List widgetList=centerEle.elements(); + for(Element widget:widgetList) + { + if("Widget".equals(widget.getName())) + { + String widgetKind=""; + Element inner=widget.element("InnerWidget"); + if(inner==null) + inner=widget; + String widgetName=inner.element("WidgetName").attributeValue("name"); + String className=inner.attributeValue("class"); + if(className.contains("WAbsolute")) + widgetKind="绝对画布块"; + else if(className.contains("WCardMainBorderLayout")) + { + widgetKind="temp"; + inner=inner.element("Center"); + } + else if(className.contains("WTabFitLayout")) + widgetKind="Tab标签"; + else if(className.contains("WTitleLayout")) + widgetKind="temp"; + + if(!"".equals(widgetKind)) + anaFrm(inner,reportName,filePath); + + else { + if (className.contains("ElementCaseEditor") && ComparatorUtils.equals(widgetName,reportName)) { + Element report=inner.element("FormElementCase"); + doExpandCafe(report,filePath); + break; + } + } + } + } + } + + + /** + * 报表块 模拟行列扩展 + * 修改单元格 c、r、cs、rs的值 + * */ + private static void doExpandCafe(Element reportRoot,String filePath) + { + List elepar = reportRoot.getParent().content(); + int index = elepar.indexOf(reportRoot); + + //变换单元格 + reportRoot=analysisEle(reportRoot,filePath,-1); + + //执行扩展行列 + List cellList=reportRoot.element("CellElementList").elements(); + for(Element cell:cellList) { + int col = Integer.parseInt(cell.attributeValue("c")); + int row = Integer.parseInt(cell.attributeValue("r")); + String cs = cell.attributeValue("cs");//横向合并单元格 + String rs = cell.attributeValue("rs");//纵向合并单元格 + int csnum=0; + if(cs!=null) + csnum=Integer.parseInt(cs); + int rsnum=0; + if(rs!=null) + rsnum=Integer.parseInt(rs); + + Map colMap=colExpandMap.get(filePath); + ListIterator> i=new ArrayList(colMap.entrySet()).listIterator(colMap.size()); + while(i.hasPrevious()) { + Map.Entry entry=i.previous(); + int colexpand[]=entry.getValue(); + if (colexpand[2] != 0) { + if (colexpand[1] == 0) { + //插入列 + if (colexpand[0] <= col) { + col = col + colexpand[2]; + cell.attribute("c").setValue(col + ""); + } else if (colexpand[0] < (col + csnum)) { + csnum = csnum + colexpand[2]; + cell.attribute("cs").setValue(csnum + ""); + } + } else { + //删除列 + int delete_c_Num = colexpand[0] + colexpand[2]; + if (colexpand[0] < col) { + if (delete_c_Num <= col)//不破坏当前单元格,位置往上移动 + { + col=col - colexpand[2]; + cell.attribute("c").setValue(col + ""); + } + //破坏部分单元格,扩展数要变动,同时位置往上移动 + else if (delete_c_Num >= col && delete_c_Num < (col + csnum)) { + int dim = delete_c_Num - col; + col=colexpand[0]; + csnum=csnum - dim; + cell.attribute("c").setValue(col + ""); + cell.attribute("cs").setValue(csnum + ""); + } else if (delete_c_Num >= (col + csnum))//破坏整个单元格 删除 + { + cell.getParent().remove(cell); + continue; + } + } else if (colexpand[0] == col)//正好从单元格所在行列开始删除 + { + if (delete_c_Num >= (col + csnum))//破坏整个单元格 删除 + { + cell.getParent().remove(cell); + continue; + } else//破坏部分单元格,扩展数要变动,单元格位置不变 + { + csnum=csnum - colexpand[2]; + cell.attribute("cs").setValue(csnum + ""); + } + } + //从单元格中间开始删除,单元格位置不变,只有扩展数变动 + else if (colexpand[0] > col && colexpand[0] < (col + csnum)) { + int num = csnum - colexpand[2]; + if (delete_c_Num > (col + csnum)) + num = num + delete_c_Num - (col + csnum); + if (num < 0) + num = 0; + csnum=num; + cell.attribute("cs").setValue(csnum + ""); + } + //从单元格下面删除,不影响当前单元格 + else if (colexpand[0] >= (col + csnum)) { + //跳过 + } + } + } + } + + Map rowMap=rowExpandMap.get(filePath); + ListIterator> ii=new ArrayList(rowMap.entrySet()).listIterator(rowMap.size()); + while(ii.hasPrevious()) { + Map.Entry entry=ii.previous(); + int rowexpand[]=entry.getValue(); + if (rowexpand[2] != 0) { + if (rowexpand[1] == 0) { + //插入行 + if (rowexpand[0] <= row) { + row = row + rowexpand[2]; + cell.attribute("r").setValue(row + ""); + } else if (rowexpand[0] < (row + rsnum)) { + rsnum = rsnum + rowexpand[2]; + cell.attribute("rs").setValue(rsnum + ""); + } + } else { + //删除行 + int delete_r_Num = rowexpand[0] + rowexpand[2]; + if (rowexpand[0] < row) { + if (delete_r_Num <= row)//不破坏当前单元格,位置往上移动 + { + row=row - rowexpand[2]; + cell.attribute("r").setValue(row + ""); + } + //破坏部分单元格,扩展数要变动,同时位置往上移动 + else if (delete_r_Num >= row && delete_r_Num < (row + rsnum)) { + int dim = delete_r_Num - row; + row=rowexpand[0]; + rsnum=rsnum - dim; + cell.attribute("r").setValue(row + ""); + cell.attribute("rs").setValue(rsnum + ""); + } else if (delete_r_Num >= (row + rsnum))//破坏整个单元格 删除 + { + cell.getParent().remove(cell); + continue; + } + } else if (rowexpand[0] == row)//正好从单元格所在行列开始删除 + { + if (delete_r_Num >= (row + rsnum))//破坏整个单元格 删除 + { + cell.getParent().remove(cell); + continue; + } else//破坏部分单元格,扩展数要变动,单元格位置不变 + { + rsnum=rsnum - rowexpand[2]; + cell.attribute("rs").setValue(rsnum + ""); + } + } + //从单元格中间开始删除,单元格位置不变,只有扩展数变动 + else if (rowexpand[0] > row && rowexpand[0] < (row + rsnum)) { + int num = rsnum - rowexpand[2]; + if (delete_r_Num > (row + rsnum)) + num = num + delete_r_Num - (row + rsnum); + if (num < 0) + num = 1; + rsnum=num; + cell.attribute("rs").setValue(num + ""); + } + //从单元格下面删除,不影响当前单元格 + else if (rowexpand[0] >= (row + rsnum)) { + //跳过 + } + } + } + } + } + + try { + + //替换后的,转换成新的ele,替换原来的report + Document new_ele = DocumentHelper.parseText(reportRoot.asXML()); + elepar.set(index,new_ele.getRootElement()); + + } catch (DocumentException e) { + e.printStackTrace(); + } + } + + + /** + * 逐行解析ele,变更需要扩展的内容 + * */ + private static Element analysisEle(Element ele, String filePath, int sheetNum) + { + String arr[]=ele.asXML().split("\n"); + StringBuilder sb=new StringBuilder(); + Map judgeMap=new HashMap(); + + //逐行解析字符串,将需要变更的单元格存入map + Map map=new LinkedHashMap(); + for(String lineTxt:arr) + { + anaStr(lineTxt , filePath , map); + anaJSstr(lineTxt , filePath , map); + } + + //map排序 + Map newmap=new LinkedHashMap(); + UnitTools.sortExpandCafe(map,newmap); + + + //逐行解析字符串,替换单元格 + for(String lineTxt:arr) + { + for (Map.Entry entry : newmap.entrySet()) { + String cafeStr=entry.getKey(); + + //判断是否包含了需要变更的单元格 + int index=lineTxt.indexOf(cafeStr); + + if(index>-1) + { + boolean judge=true; + if(sheetNum > -1) { + if (judgeMap.containsKey(cafeStr)) + judge = judgeMap.get(cafeStr); + else { + judge = UnitTools.judgeSheet(cafeStr, sheetNum); + judgeMap.put(cafeStr, judge); + } + } + if(judge) + lineTxt= UnitTools.replaceCafe(lineTxt,cafeStr,entry.getValue()); + } + } + + sb.append(lineTxt);sb.append("\n"); + } + + Element result=null; + try { + //替换后的,转换成新的ele,替换原来的report + Document new_ele = DocumentHelper.parseText(sb.toString()); + + List elepar = ele.getParent().content(); + elepar.set(elepar.indexOf(ele),new_ele.getRootElement()); + result=new_ele.getRootElement(); + + } catch (DocumentException e) { + e.printStackTrace(); + } + return result; + } + + + /** + * 解析字符串,获取单元格,判断单元格是否需要扩展 + * 需要扩展的元素存入map + * */ + private static void anaStr(String str,String filePath,Map m) + { + String tempStr=str; + List cafeList=new ArrayList(); + UnitTools.getCellCafe(str,cafeList); + for(int i=0;i m=colExpandMap.get(filePath); + + ListIterator> i=new ArrayList(m.entrySet()).listIterator(m.size()); + while(i.hasPrevious()) { + Map.Entry entry=i.previous(); + int c=entry.getKey(); + int arr[]=entry.getValue(); + if(col>c)//当前单元格列数大于插入列 + { + if (arr[1] == 0) + col = col + arr[2]; + else if (arr[1] == 1) + col = col - arr[2]; + } + } + return col; + } + + + /** + * 获取扩展后的行 + * */ + private static int getNewRow(int row,String filePath) + { + Map m=rowExpandMap.get(filePath); + + ListIterator> i=new ArrayList(m.entrySet()).listIterator(m.size()); + while(i.hasPrevious()) { + Map.Entry entry=i.previous(); + int r = entry.getKey(); + int arr[] = entry.getValue(); + + if (row > r)//当前单元格行数大于插入行 + { + if (arr[1] == 0) + row = row + arr[2]; + else if (arr[1] == 1) + row = row - arr[2]; + } + } + return row; + } + + + /** + * 解析js中涉及的的单元格 + * 如setCellValue(a,b,c); getCellValue(a,b,c) + * */ + private static void anaJSstr(String js,String filePath, Map map) + { + try { + int start1 = js.indexOf("e.getCellValue"); + if (start1 > 0) + anaJSValue(js, start1, filePath,map); + else { + int start2 = js.indexOf("e.setCellValue"); + if (start2 > 0) + anaJSValue(js, start2, filePath, map); + } + }catch (Exception e){} + } + + + /** + * 获取 变更后的js字符串,存入map + * */ + private static void anaJSValue(String str,int start,String filePath ,Map map) + { + String tempStr=str.substring(start+2); + int end=tempStr.indexOf(")"); + String value=tempStr.substring(0,end); + + String tempValue=value.substring(value.indexOf("(")+1); + String arr[]=tempValue.split(","); + String newStr=""; + if(value.contains("get")) + { + if(arr.length==3) { + int col = Integer.parseInt(arr[1].replaceAll(" ", "")); + int row = Integer.parseInt(arr[2].replaceAll(" ", "")); + + col = getNewCol(col, filePath); + row = getNewRow(row, filePath); + newStr = arr[0] + "," + col + "," + row; + } + else if(arr.length==2) + { + int col = Integer.parseInt(arr[0].replaceAll(" ", "")); + int row = Integer.parseInt(arr[1].replaceAll(" ", "")); + + col = getNewCol(col, filePath); + row = getNewRow(row, filePath); + newStr = col + "," + row; + } + } + else if(value.contains("set")) + { + int col=Integer.parseInt(arr[0].replaceAll(" ","")); + int row=Integer.parseInt(arr[1].replaceAll(" ","")); + + col=getNewCol(col,filePath); + row=getNewRow(row,filePath); + newStr=col+","+row+","+arr[2]; + } + + if(!StringUtils.equals(tempValue,newStr)) + //将变化的单元格存入map + map.put("(" + tempValue + ")", "(" + newStr + ")"); + + + int totalEnd=start+end+2; + anaJSstr(str.substring(totalEnd),filePath,map); + } + + + + /** + * 获取新文件路径 + * */ + private static String getNewPath(String path) + { + SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss"); + String nowtime = sdf.format(new Date()); + String newPath=path.substring(0,path.length()-4)+"_expand_"+nowtime+path.substring(path.length()-4); + + return newPath; + } + + /** + * 获取扩展的行列 1:1:1; + * 第一个,代表从哪开始 + * 第二个,代表插入还是删除(1删除,0插入) + * 第三个,代表扩展的数量 + * */ + private static Map getMap(String str) + { + Map map=new HashMap(); + try { + if (!StringUtils.isEmpty(str)) { + String arr[] = str.split(","); + for (String s : arr) { + String a[] = s.split(":"); + map.put(Integer.parseInt(a[0]) - 1,getExpandInfo(s)); + } + } + }catch (Exception e){}; + return map; + } + + private static int[] getExpandInfo(String str) + { + int arr[]={0,0,0}; + if(!StringUtils.isEmpty(str)) + { + try{ + String a[]=str.split(":"); + for(int i=0;i<3;i++) + arr[i]=Integer.parseInt(a[i]); + }catch (Exception e){} + } + return arr; + } +} diff --git a/src/main/java/com/fr/plugin/cafe_expand/function/UnitTools.java b/src/main/java/com/fr/plugin/cafe_expand/function/UnitTools.java new file mode 100644 index 0000000..171183d --- /dev/null +++ b/src/main/java/com/fr/plugin/cafe_expand/function/UnitTools.java @@ -0,0 +1,339 @@ +package com.fr.plugin.cafe_expand.function; + +import com.fr.stable.StringUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +public class UnitTools { + public static String colRow[] = { "A", "B", "C", "D", "E", "F", "G", "H", + "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", + "V", "W", "X", "Y", "Z" }; + + /** + * 获取文件根节点 + * */ + public static Element getRootEle(String filePath) + { + SAXReader reader = new SAXReader(); + File file=new File(filePath); + Document docXml=null; + try { + docXml = reader.read(file); + } catch (DocumentException e) { + e.printStackTrace(); + } + Element rootEle = docXml.getRootElement(); + return rootEle; + } + + /** + * 根据行列组合单元格 + * */ + public static String getCafe(String col,String row) + { + int cols=Integer.parseInt(col); + int rows=Integer.parseInt(row); + + int x = cols / 26; + String firstStr = ""; + if (x > 0) + { + firstStr = colRow[x - 1]; + cols=cols-26*x; + } + String secStr = colRow[cols]; + String thirdStr = (rows + 1) + ""; + String cafe = firstStr + secStr + thirdStr; + + return cafe; + } + + /** + * 根据单元格获取列 + * */ + public static String getCol(String cafe) + { + String col=""; + for(int i=0;i cafeList) + { + if(!StringUtils.isEmpty(strs)) { + String cafe = ""; + int beg = 0; + int end = 0; + int len = strs.length(); + for (int i = 0; i < len; i++) { + char character = strs.charAt(i); + if (Character.isLetter(character) && ((i > 1 && !Character.isLetterOrDigit(strs.charAt(i - 1))) || i <= 1)) {//第一个是字母,且前一个不是字符,或空 + beg = i; + if (i < (len - 1)) { + char secondC = strs.charAt(i + 1);//第二个字符 + if (Character.isDigit(secondC))//可能是数字 A1 + { + if (i < (len - 2))//第三个字符 + { + char thirdC = strs.charAt(i + 2); + if (Character.isDigit(thirdC))//还是数字A11 + { + if (i < (len - 3)) { + char fourthC = strs.charAt(i + 3); + if (!Character.isLetterOrDigit(fourthC))//不是字符,也不是数字 + { + end = i + 3; + cafe = character + secondC + thirdC + ""; + } + } else { + end = i + 3; + cafe = character + secondC + thirdC + ""; + } + } else if (!Character.isLetterOrDigit(thirdC))//不是字符,也不是数字 + { + end = i + 2; + cafe = character + secondC + ""; + } + } else { + end = i + 2; + cafe = character + secondC + ""; + } + } else if (Character.isLetter(secondC))//可能是字符 如AB1 + { + if (i < (len - 2))//第三个字符,只能是数字 + { + char thirdC = strs.charAt(i + 2); + if (Character.isDigit(thirdC))//是数字AB1 + { + if (i < (len - 3))//第4个字符 + { + char fourthC = strs.charAt(i + 3); + if (!Character.isLetterOrDigit(fourthC))//不是字符,也不是数字 + { + end = i + 3; + cafe = character + secondC + thirdC + ""; + } else if (Character.isDigit(fourthC))//还是数字 AB11 + { + if (i < (len - 4)) { + char fifthC = strs.charAt(i + 4); + if (!Character.isLetterOrDigit(fifthC))//不是字符,也不是数字 + { + end = i + 4; + cafe = character + secondC + thirdC + fourthC + ""; + } + } else { + end = i + 4; + cafe = character + secondC + thirdC + fourthC + ""; + } + } + } else { + end = i + 3; + cafe = character + secondC + thirdC + ""; + } + } + } + } + } + } + if (!"".equals(cafe)) + break; + } + if (end > beg) + cafeList.add(strs.substring(beg, end)); + if (!"".equals(cafe)) { + String nextStr = strs.substring(end); + getCellCafe(nextStr, cafeList); + } + } + } + + + /** + * 填报中单元格给的格式 + * */ + public static String getcafeStr(String cafe){ + int colRow[] = getColRow(cafe); + return ""; + } + + /** + * 获取单元格行列 + * */ + public static int[] getColRow(String cafe) + { + int colRow[]=new int[2]; + String col= UnitTools.getCol(cafe); + colRow[0]= UnitTools.getColNum(col); + colRow[1]=Integer.parseInt(cafe.replace(col,""))-1; + + return colRow; + } + + /** + * 需要变更的cafe排序 + * 比如C2->C3,C3->C4 + * 要先处理C3->C4 + * LinkedHashMap 按顺序读写 + * */ + public static void sortExpandCafe(Map map, Map newmap) + { + for (Map.Entry entry : map.entrySet()) { + String v=entry.getValue(); + String k=entry.getKey(); + + map.remove(k); + + if(map.containsKey(v)) + { + map.put(k,v); + sortExpandCafe(map,newmap); + break; + } + else{ + newmap.put(k,v); + sortExpandCafe(map,newmap); + break; + } + } + } + + /** + * 判断getValue(a,b,c)是否要替换 + * a=sheetNum才替换 + * */ + public static boolean judgeSheet(String cafe,int sheetNum) + { + boolean judge=true; + try { + if (cafe.startsWith("(") && sheetNum!=-1) { + cafe = cafe.replace("(", "").replace(")", "").replace(" ", ""); + String arr[] = cafe.split(","); + if (!arr[2].startsWith("\"") && !arr[2].startsWith("'"))//第三个是字符串,说明是setvalue,不用管 + { + int sheet = Integer.parseInt(arr[0]); + if (sheetNum != sheet)//同一个sheet才替换 + judge = false; + } + } + }catch (Exception e){} + return judge; + } + + /** + * 拷贝文件 + * */ + public static void copyFile(String oldPath, String newPath) { + try { + File oldfile = new File(oldPath); + if (oldfile.exists()) { + InputStream inStream = new FileInputStream(oldPath); + + File nfile=new File(newPath); + if(nfile.exists()) + nfile.delete(); + nfile.getParentFile().mkdir(); + + FileOutputStream fileOfutputStream = new FileOutputStream(newPath); + byte[] buffer = new byte[1024]; + int length; + while ((length = inStream.read(buffer)) != -1) { + fileOfutputStream.write(buffer, 0, length); + } + inStream.close(); + fileOfutputStream.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void writeToMb(String sbs,String path) + { + try { + FileOutputStream out = new FileOutputStream(path, true); + out.write(sbs.getBytes("utf-8")); + out.flush(); + out.close(); + } + catch (Exception e) + {} + } +} diff --git a/src/main/resources/1.png b/src/main/resources/1.png new file mode 100644 index 0000000..a6e33eb Binary files /dev/null and b/src/main/resources/1.png differ diff --git a/src/main/resources/2.png b/src/main/resources/2.png new file mode 100644 index 0000000..385a63d Binary files /dev/null and b/src/main/resources/2.png differ diff --git a/src/main/resources/3.png b/src/main/resources/3.png new file mode 100644 index 0000000..c28598f Binary files /dev/null and b/src/main/resources/3.png differ diff --git a/src/main/resources/expand_analysis.cpt b/src/main/resources/expand_analysis.cpt new file mode 100644 index 0000000..2885c54 --- /dev/null +++ b/src/main/resources/expand_analysis.cpt @@ -0,0 +1,817 @@ + + + + + + + + + + + + +tpS9pn7o^TY^)/i@AT:>AS^:uR##?@Y=.b +@Ntf=#GBERh.SW^WgcX3R`b60I=-$aT#[1gQ6HCU38\S9.EL\g&$IPH,aL5Nn4LogC]A$PGTA +bH6Kn,a[pF3XS?F2'Yq(U!K@NqE%Da_Z).NB9EC9d![R(=Qu#[YA@W)4jXsGs]A23e@@cb-.Q +KKl(T"Aremc*?=$^g*0@\12nH1#/(\I2Te?.=2g_U`e;gjT8~ +]]> + + + + + + + + + + +^V]A?.Oc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 && len(F9) <> 0, CONCATENATE(C9, ":", D9, ":", F9), "")]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 && len(F12) <> 0, CONCATENATE(C12, ":", E12, ":", F12), "")]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ + + + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +