Browse Source

first commit

master
wangtao 2 years ago
commit
6e6a23c921
  1. 26
      README.md
  2. 125
      build.gradle
  3. BIN
      build/install/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.zip
  4. BIN
      build/libs/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.jar
  5. BIN
      build/temp/plugin/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.jar
  6. 22
      build/temp/plugin/plugin.xml
  7. 2
      build/tmp/makeJar/MANIFEST.MF
  8. 13
      encrypt.xml
  9. 22
      plugin.xml
  10. 115
      src/main/java/com/fr/plugin/cafe_expand/designerhelp/JumpToAnalysis.java
  11. 615
      src/main/java/com/fr/plugin/cafe_expand/function/DoExpandFile.java
  12. 339
      src/main/java/com/fr/plugin/cafe_expand/function/UnitTools.java
  13. BIN
      src/main/resources/1.png
  14. BIN
      src/main/resources/2.png
  15. BIN
      src/main/resources/3.png
  16. 817
      src/main/resources/expand_analysis.cpt

26
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)

125
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"
}

BIN
build/install/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.zip

Binary file not shown.

BIN
build/libs/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.jar

Binary file not shown.

BIN
build/temp/plugin/fine-plugin-com.fr.plugin.cafe_expand-1.0.0.jar

Binary file not shown.

22
build/temp/plugin/plugin.xml

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plugin>
<id>com.fr.plugin.cafe_expand</id>
<name><![CDATA[行列扩展辅助变更]]></name>
<active>yes</active>
<hidden>no</hidden>
<version>1.0.0</version>
<env-version>10.0</env-version>
<jartime>2020-01-01</jartime>
<vendor>crm</vendor>
<description><![CDATA[行列扩展辅助变更]]></description>
<change-notes><![CDATA[无]]></change-notes>
<extra-core>
<FunctionDefineProvider class="com.fr.plugin.cafe_expand.function.DoExpandFile" name="DoExpandFile" description="扩展单元格"/>
</extra-core>
<extra-designer>
<DesignerFrameUpButtonProvider class="com.fr.plugin.cafe_expand.designerhelp.JumpToAnalysis"/>
</extra-designer>
<function-recorder class="com.fr.plugin.cafe_expand.function.DoExpandFile"/>
</plugin>

2
build/tmp/makeJar/MANIFEST.MF

@ -0,0 +1,2 @@
Manifest-Version: 1.0

13
encrypt.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<target name="compile_encrypt_javas" depends="copyFiles">
<echo message="加密文件"/>
<echo message="${projectDir}"/>
<taskdef name="pretreatment" classname="com.fr.plugin.pack.PluginPretreatmentTask">
<classpath refid="compile.classpath"/>
</taskdef>
<pretreatment baseDir="${projectDir}"/>
</target>
<target name="compile_plain_javas" depends="copyFiles">
</target>
</project>

22
plugin.xml

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plugin>
<id>com.fr.plugin.cafe_expand</id>
<name><![CDATA[行列扩展辅助变更]]></name>
<active>yes</active>
<hidden>no</hidden>
<version>1.0.0</version>
<env-version>10.0</env-version>
<jartime>2020-01-01</jartime>
<vendor>crm</vendor>
<description><![CDATA[行列扩展辅助变更]]></description>
<change-notes><![CDATA[无]]></change-notes>
<extra-core>
<FunctionDefineProvider class="com.fr.plugin.cafe_expand.function.DoExpandFile" name="DoExpandFile" description="扩展单元格"/>
</extra-core>
<extra-designer>
<DesignerFrameUpButtonProvider class="com.fr.plugin.cafe_expand.designerhelp.JumpToAnalysis"/>
</extra-designer>
<function-recorder class="com.fr.plugin.cafe_expand.function.DoExpandFile"/>
</plugin>

115
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();
}
}
}
}

615
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<String,Map<Integer, int[]>> colExpandMap=new HashMap();
public static Map<String,Map<Integer, int[]>> 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<Integer, int[]> colMap = getMap(colexpand);
Map<Integer, int[]> 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<Element> 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<Element> 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<Element> 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;
}
}
}
}
}
/**
* 报表块 模拟行列扩展
* 修改单元格 crcsrs的值
* */
private static void doExpandCafe(Element reportRoot,String filePath)
{
List elepar = reportRoot.getParent().content();
int index = elepar.indexOf(reportRoot);
//变换单元格
reportRoot=analysisEle(reportRoot,filePath,-1);
//执行扩展行列
List<Element> 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<Integer,int[]> colMap=colExpandMap.get(filePath);
ListIterator<Map.Entry<Integer,int[]>> i=new ArrayList(colMap.entrySet()).listIterator(colMap.size());
while(i.hasPrevious()) {
Map.Entry<Integer,int[]> 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<Integer,int[]> rowMap=rowExpandMap.get(filePath);
ListIterator<Map.Entry<Integer,int[]>> ii=new ArrayList(rowMap.entrySet()).listIterator(rowMap.size());
while(ii.hasPrevious()) {
Map.Entry<Integer,int[]> 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<String,Boolean> judgeMap=new HashMap();
//逐行解析字符串,将需要变更的单元格存入map
Map<String, String> map=new LinkedHashMap();
for(String lineTxt:arr)
{
anaStr(lineTxt , filePath , map);
anaJSstr(lineTxt , filePath , map);
}
//map排序
Map<String, String> newmap=new LinkedHashMap();
UnitTools.sortExpandCafe(map,newmap);
//逐行解析字符串,替换单元格
for(String lineTxt:arr)
{
for (Map.Entry<String, String> 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<String, String> m)
{
String tempStr=str;
List<String> cafeList=new ArrayList();
UnitTools.getCellCafe(str,cafeList);
for(int i=0;i<cafeList.size();i++)
{
String cafe=cafeList.get(i);
String newCafe=getNewCafe(cafe,filePath);
if(!ComparatorUtils.equals(cafe,newCafe))
{
//将变化的单元格存入map
m.put(cafe,newCafe);
m.put(UnitTools.getcafeStr(cafe), UnitTools.getcafeStr(newCafe));
}
}
}
/**
* 获取 扩展后的 单元格
* */
private static String getNewCafe(String cafe,String filePath)
{
int colRow[] = UnitTools.getColRow(cafe);
int newCol=getNewCol(colRow[0],filePath);
int newRow=getNewRow(colRow[1],filePath);
return UnitTools.getCafe("" + newCol, newRow + "");
}
/**
* 获取扩展后的列
* */
private static int getNewCol(int col,String filePath)
{
Map<Integer,int[]> m=colExpandMap.get(filePath);
ListIterator<Map.Entry<Integer,int[]>> i=new ArrayList(m.entrySet()).listIterator(m.size());
while(i.hasPrevious()) {
Map.Entry<Integer,int[]> 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<Integer,int[]> m=rowExpandMap.get(filePath);
ListIterator<Map.Entry<Integer,int[]>> i=new ArrayList(m.entrySet()).listIterator(m.size());
while(i.hasPrevious()) {
Map.Entry<Integer,int[]> 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<String, String> 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<String, String> 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<Integer,int[]> getMap(String str)
{
Map<Integer,int[]> 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;
}
}

339
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<cafe.length();i++)
{
if(Character.isLetter(cafe.charAt(i)))
col+=cafe.charAt(i);
else
break;
}
return col;
}
/**
* 根据英文字母获取下标
* */
public static int getColNum(String col)
{
int num=0;
int len=col.length();
for(int i=0;i<len;i++)
{
String c=col.substring(0,1);
for(int j=0;j<26;j++)
{
if(c.equals(colRow[j])){
num=num+j+26*(len-1-i);
break;
}
}
col=col.replaceFirst(c,"");
}
return num;
}
/**
* 自定义replace方法替换字符串中的单元格
* */
public static String replaceCafe(String str,String before,String after)
{
int size=before.length();
String newStr="";
int len=str.length();
int i=0;
while(i<=len)
{
int start=str.indexOf(before);
if(start==-1){
newStr+=str;
break;
}
else if(start+size<len)
{
char character=str.charAt(start+size);
if(!Character.isDigit(character))
{
String temp=str.substring(0,start+size);
newStr=newStr+temp.replace(before,after);
}
else
newStr+=str;
str=str.substring(start+size);
}
else if(start+size==len)
newStr=newStr+str.replace(before,after);
i=i+start+size+1;
}
return newStr;
}
/**
* 从字符串中提取单元格 如A1
* isDigit 判断数值isLetter 判断英文字母
* 根据模板实际情况最大ZZ99
* */
public static void getCellCafe(String strs, List<String> 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 "<ColumnRow column=\""+colRow[0]+"\" row=\""+colRow[1]+"\"/>";
}
/**
* 获取单元格行列
* */
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<String, String> map, Map<String, String> newmap)
{
for (Map.Entry<String, String> 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)
{}
}
}

BIN
src/main/resources/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
src/main/resources/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
src/main/resources/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

817
src/main/resources/expand_analysis.cpt

@ -0,0 +1,817 @@
<?xml version="1.0" encoding="UTF-8"?>
<WorkBook xmlVersion="20211223" releaseVersion="11.0.0">
<TableDataMap>
<TableData name="ds1" class="com.fr.data.impl.EmbeddedTableData">
<Parameters/>
<DSName>
<![CDATA[null]]></DSName>
<ColumnNames>
<![CDATA[uid,,.,,letter]]></ColumnNames>
<ColumnTypes>
<![CDATA[java.lang.Long,java.lang.String]]></ColumnTypes>
<RowData ColumnTypes="java.lang.Long,java.lang.String">
<![CDATA[4jZ2e"@3Ga;*3qth'H&SVLW+4[fK5,"p>tpS9pn7o^TY^)/i@<hgb>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~
]]></RowData>
</TableData>
<TableData name="ds2" class="com.fr.data.impl.EmbeddedTableData">
<Parameters/>
<DSName>
<![CDATA[null]]></DSName>
<ColumnNames>
<![CDATA[uid,,.,,uname]]></ColumnNames>
<ColumnTypes>
<![CDATA[java.lang.Long,java.lang.String]]></ColumnTypes>
<RowData ColumnTypes="java.lang.Long,java.lang.String">
<![CDATA[1Z3Z35NunJ;D(>^V]A?.Oc<LDN~
]]></RowData>
</TableData>
</TableDataMap>
<ReportWebAttr>
<ServerPrinter/>
<WebWriteContent>
<ToolBars>
<ToolBarManager>
<Location>
<Embed position="1"/>
</Location>
<ToolBar>
<Widget class="com.fr.report.web.button.write.Submit">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[${i18n('Fine-Engine_Report_Utils_Submit')}]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[submit]]></IconName>
<Verify failVerifySubmit="false" value="true"/>
<Sheet onlySubmitSelect="false"/>
</Widget>
<Widget class="com.fr.report.web.button.write.Verify">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[${i18n('Fine-Engine_Report_Verify_Data')}]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[verify]]></IconName>
</Widget>
<Widget class="com.fr.report.web.button.NewPrint">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[${i18n('Fine-Engine_Print')}]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[print]]></IconName>
</Widget>
<Widget class="com.fr.report.web.button.Export">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[${i18n('Export')}]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[export]]></IconName>
<ExtraButton ButtonName="Word-plugin-export-pdf">
<Buttons Word-plugin-export="true"/>
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[pdf 导出]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[pdf]]></IconName>
</ExtraButton>
<ExtraButton ButtonName="Word-plugin-export">
<Buttons Word-plugin-export="true"/>
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[word 导出]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[word]]></IconName>
</ExtraButton>
<Buttons pdf="true" excelP="true" excelO="true" excelS="true" word="true" image="true" html="true"/>
</Widget>
<Widget class="com.fr.report.web.button.Email">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[${i18n('Fine-Engine_Report_Email')}]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[email]]></IconName>
<EmailButton customConsignee="true" consigneeByDepartment="false" consigneeByRole="false"/>
</Widget>
<Widget class="com.fr.report.web.button.write.AppendColumnRow">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[${i18n('Fine-Engine_Add_Record')}]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[appendrow]]></IconName>
</Widget>
<Widget class="com.fr.report.web.button.write.ShowCellValue">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<widgetValue/>
<LabelAttr verticalcenter="true" textalign="0" autoline="false"/>
<FRFont name="SimSun" style="0" size="72"/>
<border style="0">
<color>
<FineColor color="-723724" hor="-1" ver="-1"/>
</color>
</border>
</Widget>
</ToolBar>
</ToolBarManager>
</ToolBars>
<EditRowColor setColor="false"/>
<WebWrite SheetPosition="3"/>
<RptLocation isShowAtLeft="true"/>
<UnloadCheck/>
<ShowWidgets show="true"/>
<OtherAttr autoStash="false"/>
</WebWriteContent>
</ReportWebAttr>
<ElementCaseMobileAttr>
<ElementCaseMobileAttrProvider horizontal="1" vertical="1" zoom="true" refresh="false" isUseHTML="false" isMobileCanvasSize="false" appearRefresh="false" allowFullScreen="false" allowDoubleClickOrZoom="true" functionalWhenUnactivated="false"/>
</ElementCaseMobileAttr>
<Report class="com.fr.report.worksheet.WorkSheet" name="sheet1">
<ReportPageAttr>
<HR/>
<FR/>
<HC/>
<FC/>
</ReportPageAttr>
<ColumnPrivilegeControl/>
<RowPrivilegeControl/>
<RowHeight defaultValue="723900">
<![CDATA[723900,990600,876300,533400,990600,876300,533400,990600,723900,533400,990600,723900,723900,533400,723900,723900,335280,723900]]></RowHeight>
<ColumnWidth defaultValue="2743200">
<![CDATA[762000,3200400,3505200,1257300,3390900,2743200,2743200,266700,1447800,266700,1447800,2743200]]></ColumnWidth>
<CellElementList>
<C c="0" r="0">
<PrivilegeControl/>
<Expand>
<cellSortAttr/>
</Expand>
</C>
<C c="11" r="0">
<PrivilegeControl/>
<HighlightList>
<Highlight class="com.fr.report.cell.cellattr.highlight.DefaultHighlight">
<Name>
<![CDATA[条件属性1]]></Name>
<Condition class="com.fr.data.condition.ListCondition"/>
<HighlightAction class="com.fr.report.cell.cellattr.highlight.ColWidthHighlightAction"/>
</Highlight>
</HighlightList>
<Expand/>
</C>
<C c="1" r="1" s="0">
<O>
<![CDATA[页面]]></O>
<PrivilegeControl/>
<Expand/>
</C>
<C c="11" r="1">
<O t="XMLable" class="com.fr.base.Formula">
<Attributes>
<![CDATA[=CONCATENATE(L9)]]></Attributes>
</O>
<PrivilegeControl/>
<Expand/>
</C>
<C c="13" r="1" cs="5" rs="11">
<O>
<![CDATA[功能说明:\\n1、后台拷贝一份当前模板,并按上面填写的扩展行列规则,进行扩展\\n2、如果是多sheet、多个block,或者frm多个报表块,每次只扩展“位置”中指定的报表块,如果想继续扩展其它报表块,需要在扩展后的模板的基础上继续操作\\n3、部分js代码中涉及的部分行列可能不支持,目前支持\\n getCellValue(sheet,col,row);getCellValue(col,row);\\n setCellValue(col,row,val); \\n不支持的如\\n FR.columnRow2CellStr({col: col, row: row}) 等,这类暂时需要手动更改,后续会完善\\n4、扩展后的模板请预览检查后再覆盖当前模板,避免有问题;\\n5、每次执行都会产生一个新的备份模板,请及时删除不需要的备份后的模板,避免模板太多]]></O>
<PrivilegeControl/>
<Expand>
<cellSortAttr/>
</Expand>
</C>
<C c="1" r="2" cs="6" s="1">
<O t="XMLable" class="com.fr.base.Formula">
<Attributes>
<![CDATA[=$filePath]]></Attributes>
</O>
<PrivilegeControl/>
<Expand/>
</C>
<C c="1" r="4" s="0">
<O>
<![CDATA[位置]]></O>
<PrivilegeControl/>
<Expand/>
</C>
<C c="11" r="4">
<O t="XMLable" class="com.fr.base.Formula">
<Attributes>
<![CDATA[=CONCATENATE(L12)]]></Attributes>
</O>
<PrivilegeControl/>
<Expand/>
</C>
<C c="1" r="5" cs="6" s="1">
<O t="XMLable" class="com.fr.base.Formula">
<Attributes>
<![CDATA[=$position]]></Attributes>
</O>
<PrivilegeControl/>
<Expand/>
</C>
<C c="1" r="7" cs="6" s="0">
<O>
<![CDATA[扩展列]]></O>
<PrivilegeControl/>
<Expand/>
</C>
<C c="1" r="8" s="1">
<O>
<![CDATA[在]]></O>
<PrivilegeControl/>
<CellPageAttr/>
<CellInsertPolicy>
<InsertPolicy>
<![CDATA[copy]]></InsertPolicy>
</CellInsertPolicy>
<Expand dir="0"/>
</C>
<C c="2" r="8" s="1">
<PrivilegeControl/>
<Widget class="com.fr.form.ui.ComboBox">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<allowBlank>
<![CDATA[false]]></allowBlank>
<CustomData>
<![CDATA[false]]></CustomData>
<Dictionary class="com.fr.data.impl.TableDataDictionary">
<FormulaDictAttr kiName="uid" viName="letter"/>
<TableDataDictAttr>
<TableData class="com.fr.data.impl.NameTableData">
<Name>
<![CDATA[ds1]]></Name>
</TableData>
</TableDataDictAttr>
</Dictionary>
<widgetValue/>
</Widget>
<Present class="com.fr.base.present.DictPresent">
<Dictionary class="com.fr.data.impl.TableDataDictionary">
<FormulaDictAttr kiName="uid" viName="letter"/>
<TableDataDictAttr>
<TableData class="com.fr.data.impl.NameTableData">
<Name>
<![CDATA[ds1]]></Name>
</TableData>
</TableDataDictAttr>
</Dictionary>
</Present>
<Expand dir="0"/>
</C>
<C c="3" r="8" cs="2" s="1">
<O t="I">
<![CDATA[0]]></O>
<PrivilegeControl/>
<CellPageAttr/>
<Widget class="com.fr.form.ui.ComboBox">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<allowBlank>
<![CDATA[false]]></allowBlank>
<DirectEdit>
<![CDATA[false]]></DirectEdit>
<CustomData>
<![CDATA[false]]></CustomData>
<Dictionary class="com.fr.data.impl.TableDataDictionary">
<FormulaDictAttr kiName="uid" viName="uname"/>
<TableDataDictAttr>
<TableData class="com.fr.data.impl.NameTableData">
<Name>
<![CDATA[ds2]]></Name>
</TableData>
</TableDataDictAttr>
</Dictionary>
<widgetValue/>
</Widget>
<Present class="com.fr.base.present.DictPresent">
<Dictionary class="com.fr.data.impl.TableDataDictionary">
<FormulaDictAttr kiName="uid" viName="uname"/>
<TableDataDictAttr>
<TableData class="com.fr.data.impl.NameTableData">
<Name>
<![CDATA[ds2]]></Name>
</TableData>
</TableDataDictAttr>
</Dictionary>
</Present>
<CellInsertPolicy>
<InsertPolicy>
<![CDATA[copy]]></InsertPolicy>
</CellInsertPolicy>
<Expand dir="0"/>
</C>
<C c="5" r="8" s="1">
<O t="I">
<![CDATA[1]]></O>
<PrivilegeControl/>
<CellPageAttr/>
<Widget class="com.fr.form.ui.NumberEditor">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<allowBlank>
<![CDATA[false]]></allowBlank>
<NumberAttr allowDecimals="false" allowNegative="false">
<widgetValue/>
</NumberAttr>
</Widget>
<CellInsertPolicy>
<InsertPolicy>
<![CDATA[copy]]></InsertPolicy>
</CellInsertPolicy>
<Expand dir="0"/>
</C>
<C c="6" r="8" s="1">
<O>
<![CDATA[列]]></O>
<PrivilegeControl/>
<CellPageAttr/>
<CellInsertPolicy>
<InsertPolicy>
<![CDATA[copy]]></InsertPolicy>
</CellInsertPolicy>
<Expand dir="0"/>
</C>
<C c="8" r="8">
<PrivilegeControl/>
<Widget class="com.fr.report.web.button.write.AppendRowButton">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[add]]></IconName>
<FixCell row="8" col="1"/>
</Widget>
<Expand/>
</C>
<C c="10" r="8">
<PrivilegeControl/>
<Widget class="com.fr.report.web.button.write.DeleteRowButton">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[delete]]></IconName>
<FixCell row="8" col="1"/>
</Widget>
<Expand/>
</C>
<C c="11" r="8">
<O t="XMLable" class="com.fr.base.Formula">
<Attributes>
<![CDATA[=if(len(C9) <> 0 && len(F9) <> 0, CONCATENATE(C9, ":", D9, ":", F9), "")]]></Attributes>
</O>
<PrivilegeControl/>
<CellPageAttr/>
<CellInsertPolicy>
<InsertPolicy>
<![CDATA[copy]]></InsertPolicy>
</CellInsertPolicy>
<Expand/>
</C>
<C c="1" r="10" cs="6" s="0">
<O>
<![CDATA[扩展行]]></O>
<PrivilegeControl/>
<Expand/>
</C>
<C c="1" r="11" s="1">
<O>
<![CDATA[在第]]></O>
<PrivilegeControl/>
<CellPageAttr/>
<CellInsertPolicy>
<InsertPolicy>
<![CDATA[copy]]></InsertPolicy>
</CellInsertPolicy>
<Expand dir="0"/>
</C>
<C c="2" r="11" s="1">
<PrivilegeControl/>
<Widget class="com.fr.form.ui.NumberEditor">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<allowBlank>
<![CDATA[false]]></allowBlank>
<regMsg>
<![CDATA[最小值为0]]></regMsg>
<NumberAttr allowDecimals="false" allowNegative="false" minValue="0.0">
<widgetValue/>
</NumberAttr>
</Widget>
<Expand dir="0"/>
</C>
<C c="3" r="11" s="1">
<O>
<![CDATA[行后]]></O>
<PrivilegeControl/>
<CellPageAttr/>
<CellInsertPolicy>
<InsertPolicy>
<![CDATA[copy]]></InsertPolicy>
</CellInsertPolicy>
<Expand/>
</C>
<C c="4" r="11" s="1">
<O t="I">
<![CDATA[0]]></O>
<PrivilegeControl/>
<CellPageAttr/>
<Widget class="com.fr.form.ui.ComboBox">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<allowBlank>
<![CDATA[false]]></allowBlank>
<DirectEdit>
<![CDATA[false]]></DirectEdit>
<CustomData>
<![CDATA[false]]></CustomData>
<Dictionary class="com.fr.data.impl.TableDataDictionary">
<FormulaDictAttr kiName="uid" viName="uname"/>
<TableDataDictAttr>
<TableData class="com.fr.data.impl.NameTableData">
<Name>
<![CDATA[ds2]]></Name>
</TableData>
</TableDataDictAttr>
</Dictionary>
<widgetValue/>
</Widget>
<Present class="com.fr.base.present.DictPresent">
<Dictionary class="com.fr.data.impl.TableDataDictionary">
<FormulaDictAttr kiName="uid" viName="uname"/>
<TableDataDictAttr>
<TableData class="com.fr.data.impl.NameTableData">
<Name>
<![CDATA[ds2]]></Name>
</TableData>
</TableDataDictAttr>
</Dictionary>
</Present>
<CellInsertPolicy>
<InsertPolicy>
<![CDATA[copy]]></InsertPolicy>
</CellInsertPolicy>
<Expand dir="0"/>
</C>
<C c="5" r="11" s="1">
<O t="I">
<![CDATA[1]]></O>
<PrivilegeControl/>
<CellPageAttr/>
<Widget class="com.fr.form.ui.NumberEditor">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<allowBlank>
<![CDATA[false]]></allowBlank>
<NumberAttr allowDecimals="false" allowNegative="false">
<widgetValue/>
</NumberAttr>
</Widget>
<CellInsertPolicy>
<InsertPolicy>
<![CDATA[copy]]></InsertPolicy>
</CellInsertPolicy>
<Expand dir="0"/>
</C>
<C c="6" r="11" s="1">
<O>
<![CDATA[行]]></O>
<PrivilegeControl/>
<CellPageAttr/>
<CellInsertPolicy>
<InsertPolicy>
<![CDATA[copy]]></InsertPolicy>
</CellInsertPolicy>
<Expand dir="0"/>
</C>
<C c="8" r="11">
<PrivilegeControl/>
<Widget class="com.fr.report.web.button.write.AppendRowButton">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[add]]></IconName>
<FixCell row="11" col="1"/>
</Widget>
<Expand/>
</C>
<C c="10" r="11">
<PrivilegeControl/>
<Widget class="com.fr.report.web.button.write.DeleteRowButton">
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
<IconName>
<![CDATA[delete]]></IconName>
<FixCell row="11" col="1"/>
</Widget>
<Expand/>
</C>
<C c="11" r="11">
<O t="XMLable" class="com.fr.base.Formula">
<Attributes>
<![CDATA[=if(len(C12) <> 0 && len(F12) <> 0, CONCATENATE(C12, ":", E12, ":", F12), "")]]></Attributes>
</O>
<PrivilegeControl/>
<CellPageAttr/>
<CellInsertPolicy>
<InsertPolicy>
<![CDATA[copy]]></InsertPolicy>
</CellInsertPolicy>
<Expand/>
</C>
<C c="1" r="12" cs="6" s="2">
<O>
<![CDATA[若在第一行前插入,填 0]]></O>
<PrivilegeControl/>
<Expand/>
</C>
<C c="1" r="15">
<PrivilegeControl/>
<Widget class="com.fr.form.ui.FreeButton">
<Listener event="click" name="点击1">
<JavaScript class="com.fr.js.JavaScriptImpl">
<Parameters>
<Parameter>
<Attributes name="path"/>
<O t="XMLable" class="com.fr.base.Formula">
<Attributes>
<![CDATA[=$filePath]]></Attributes>
</O>
</Parameter>
<Parameter>
<Attributes name="position"/>
<O t="XMLable" class="com.fr.base.Formula">
<Attributes>
<![CDATA[=$position]]></Attributes>
</O>
</Parameter>
</Parameters>
<Content>
<![CDATA[contentPane.stopEditing();
var ec= contentPane.curLGP.getCellValue("L2");
var er= contentPane.curLGP.getCellValue("L5");
if(ec=="" && er=="")
FR.Msg.toast("请先配置扩展行 或 列");
else if(ec.startWith(",") || er.startWith(","))
FR.Msg.toast("扩展行列配置不完整");
else
{
var newFile=FR.remoteEvaluate("=DoExpandFile('"+path+"','"+position+"','"+ec+"','"+er+"')");
contentPane.setCellValue(2,15, " 扩展后的模板:"+newFile+";请刷新设计器查看");
}]]></Content>
</JavaScript>
</Listener>
<WidgetName name="changeBut"/>
<WidgetAttr aspectRatioLocked="false" aspectRatioBackup="-1.0" description="">
<MobileBookMark useBookMark="false" bookMarkName="" frozen="false"/>
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[一键替换]]></Text>
<Hotkeys>
<![CDATA[]]></Hotkeys>
</Widget>
<Expand>
<cellSortAttr/>
</Expand>
</C>
<C c="2" r="15" cs="9" s="3">
<PrivilegeControl/>
<Expand/>
</C>
<C c="1" r="26">
<PrivilegeControl/>
<Expand/>
</C>
<C c="2" r="26">
<PrivilegeControl/>
<Expand/>
</C>
<C c="3" r="26">
<PrivilegeControl/>
<Expand/>
</C>
<C c="4" r="26">
<PrivilegeControl/>
<Expand/>
</C>
<C c="5" r="26">
<PrivilegeControl/>
<Expand/>
</C>
<C c="6" r="26">
<PrivilegeControl/>
<Expand/>
</C>
</CellElementList>
<ReportAttrSet>
<ReportSettings headerHeight="0" footerHeight="0">
<PaperSetting/>
<FollowingTheme background="false"/>
<Background name="ColorBackground">
<color>
<FineColor color="-1" hor="-1" ver="-1"/>
</color>
</Background>
</ReportSettings>
<Header reportPageType="0">
<Background name="NullBackground"/>
<LeftList/>
<CenterList/>
<RightList/>
</Header>
<Footer reportPageType="0">
<Background name="NullBackground"/>
<LeftList/>
<CenterList/>
<RightList/>
</Footer>
</ReportAttrSet>
<PrivilegeControl/>
</Report>
<ReportParameterAttr>
<Attributes showWindow="true" delayPlaying="true" windowPosition="1" align="0" useParamsTemplate="true" currentIndex="0"/>
<PWTitle>
<![CDATA[参数]]></PWTitle>
</ReportParameterAttr>
<StyleList>
<Style imageLayout="1">
<FRFont name="微软雅黑" style="0" size="104">
<foreground>
<FineColor color="-1" hor="-1" ver="-1"/>
</foreground>
</FRFont>
<Background name="ColorBackground">
<color>
<FineColor color="-11555390" hor="-1" ver="-1"/>
</color>
</Background>
<Border>
<Top style="1">
<color>
<FineColor color="-5973267" hor="-1" ver="-1"/>
</color>
</Top>
<Bottom style="1">
<color>
<FineColor color="-5973267" hor="-1" ver="-1"/>
</color>
</Bottom>
<Left style="1">
<color>
<FineColor color="-5973267" hor="-1" ver="-1"/>
</color>
</Left>
<Right style="1">
<color>
<FineColor color="-5973267" hor="-1" ver="-1"/>
</color>
</Right>
</Border>
</Style>
<Style horizontal_alignment="0" imageLayout="1">
<FRFont name="微软雅黑" style="0" size="72"/>
<Background name="ColorBackground">
<color>
<FineColor color="-657158" hor="-1" ver="-1"/>
</color>
</Background>
<Border>
<Top style="1">
<color>
<FineColor color="-3024920" hor="-1" ver="-1"/>
</color>
</Top>
<Bottom style="1">
<color>
<FineColor color="-3024920" hor="-1" ver="-1"/>
</color>
</Bottom>
<Left style="1">
<color>
<FineColor color="-3024920" hor="-1" ver="-1"/>
</color>
</Left>
<Right style="1">
<color>
<FineColor color="-3024920" hor="-1" ver="-1"/>
</color>
</Right>
</Border>
</Style>
<Style imageLayout="1">
<FRFont name="微软雅黑" style="0" size="64">
<foreground>
<FineColor color="-236032" hor="-1" ver="-1"/>
</foreground>
</FRFont>
<Background name="NullBackground"/>
<Border/>
</Style>
<Style imageLayout="1">
<FRFont name="SimSun" style="1" size="72">
<foreground>
<FineColor color="-6737152" hor="-1" ver="-1"/>
</foreground>
</FRFont>
<Background name="NullBackground"/>
<Border/>
</Style>
</StyleList>
<DesignerVersion DesignerVersion="LAA"/>
<PreviewType PreviewType="1"/>
<TemplateThemeAttrMark class="com.fr.base.iofile.attr.TemplateThemeAttrMark">
<TemplateThemeAttrMark name="兼容主题" dark="false"/>
</TemplateThemeAttrMark>
<StrategyConfigsAttr class="com.fr.esd.core.strategy.persistence.StrategyConfigsAttr">
<StrategyConfigs/>
</StrategyConfigsAttr>
<TemplateCloudInfoAttrMark class="com.fr.plugin.cloud.analytics.attr.TemplateInfoAttrMark" pluginID="com.fr.plugin.cloud.analytics.v11" plugin-version="3.7.0.20220804">
<TemplateCloudInfoAttrMark createTime="1639012631677"/>
</TemplateCloudInfoAttrMark>
<TemplateIdAttMark class="com.fr.base.iofile.attr.TemplateIdAttrMark">
<TemplateIdAttMark TemplateId="02c4a67b-9af2-4370-a23b-2d6a93bb018c"/>
</TemplateIdAttMark>
</WorkBook>
Loading…
Cancel
Save