NCV5公式技术红皮书.docx
- 文档编号:12596251
- 上传时间:2023-04-20
- 格式:DOCX
- 页数:40
- 大小:29.39KB
NCV5公式技术红皮书.docx
《NCV5公式技术红皮书.docx》由会员分享,可在线阅读,更多相关《NCV5公式技术红皮书.docx(40页珍藏版)》请在冰豆网上搜索。
NCV5公式技术红皮书
公式技术红皮书
NC-UAP5.0
用友NC-UAP
2018-09-22
目录
第一章新版公式使用手册1
1.公式主要功能1
2.公式的基本使用方法2
2.1创建公式执行器2
2.2设置公式执行器环境3
2.3设置公式的值3
2.4对公式进行语法检查3
2.5提取公式变量4
2.6给公式变量赋值4
2.7取得公式的值5
3.数值型计算结果小数位的控制5
4.自定义变量的使用6
5.如何从公式中提取变量8
6.空值””,NULL值及Zero值的处理9
7.如何进行列操作11
8.利用自定义函数扩展公式功能11
9.外接函数的使用12
10.运算符重载13
11.公式简单调试14
附录1公式解析器内置变量列表15
附录2公式解析器内置公式列表15
1.数学运算函数15
2.条件判断函数18
3.数据库查询函数20
4.字符串相关函数21
5.日期函数23
6.类型转换函数23
7.货币金额函数24
8.多语言翻译函数25
9.其他函数26
第一章新版公式使用手册
1.公式主要功能
1.支持一般的算术运算+,-,*,/,ˆ,%
例如:
sin(1.35)*a/b+cos(3.4)/c
其中a,b,c均为变量
2.支持对数值型计算结果小数位的控制
3.支持逻辑运算符&&(兼容老版&),||(兼容老版|),!
例如:
iif((a&b)||(c&&d),"right","wrong")
其中a,b,c,d均为变量
4.支持比较运算符>,>=,<,<=,==,!
=等,支持null值的处理。
例如:
iif((a>b&&a!
=null)||(c<=d),"right","wrong")
其中a,b,c,d均为变量
5.支持自定义变量,变量可按Object和String两种方式传入
例如:
col1->var1+var2
其中var1,var2均为自定义变量,可以为String型,也可以为任意类型
6.公式除了支持String,Number型数据运算,还支持自定义类型
例如:
combine(vo1,vo2)
其中vo1,vo2可为自定义的数据类型,具体用法参考后面的说明
7.支持操作符(+,-,*,/,>,>=,<,<=,==)重载(通过实现相应的接口)
例如:
iif((car1>car2)||(factory1<=factory2),"right","wrong")
其中car1,car2,factory1,factory2的运算符通过实现相应的接口进行重载。
8.可以在数值型一维数组之间进行加减乘除运算(数组长度必须相等),即支持列操作.
例如var1=[1,2,3,4];var2=[2,3,4,5];可对var1,var2进行各种运算。
9.系统函数支持,NC常用函数支持
例如:
sin,cos,ceil,floor,toChinese,getChineseCurrency(),iif()
等等,详细支持的函数请参见附录。
10.支持外接用户函数.(可以是一个java的方法)
例如:
公式combine("nihao","hao")中,combine是一个自定义函数,可以指定绑定到一个JAVA类的具体方法,可参考后面的例子。
11.支持自定义函数.具体应用可参考后面的详细说明(第1.8节)
有时候公式解析器内部的函数并不能完全满足用户的要求,此时用户可添加自定义函数。
例如:
hello("saysomething",person),hello为一个自定义函数,
动态注册到公式解析器中。
12.支持客户端公式和服务端公式.
以满足前台及后台调用,主要体现在数据库查询的方式上有一定的差别。
13.支持多行公式批量运算,且保持变量的传递性.
例如:
a->col1+col2;
b->a+col1*col3;
c->a+b;
14.支持一个线程内多个公式执行器实例交替运行的情况,但不支持多个线程内同一公式执行器实例交替运行。
所以如果程序中起多线程的话,建议每个线程单独创建自己的公式解析器示例。
例如下面的代码是可行的:
FormulaParseFatherf=newFormulaParse();
f.setExpress(formula);
f.setNullAsZero(true);
FormulaParseFatherf1=
newFormulaParse();f1.setNullAsZero(false);
f.setDataSArray(map);
String[]res=f.getValueS();
2.公式的基本使用方法
使用公式解析器的基本步骤如下:
2.1创建公式执行器
如果在客户端使用公式解析:
FormulaParseFatherf=newnc.ui.pub.formulaparse.FormulaParse();
如果在服务端使用公式解析:
FormulaParseFatherf=newnc.bs.pub.formulaparse.FormulaParse();
如果不知道当前的代码会在哪一端运行,可以用下面的方法进行判断:
if(RuntimeEnv.getInstance().isRunningInServer()){
parse=newnc.bs.pub.formulaparse.FormulaParse();
}else{
parse=newnc.ui.pub.formulaparse.FormulaParse();
}
2.2设置公式执行器环境
(自定义变量及自定义函数可参考后续章节描述)
这里可以给公式执行器添加自定义变量,例如:
UFDoublevar1=newUFDouble(5.368);
f.addVariable(var1);
或者添加自定义函数,例如:
类YourFunction是一个定义的函数类(关于如何自定义函数,请参考自定义函数一节),在公式中函数取名为"yourfun",则可以这样添加你的自定义函数:
f.addFunction("yourfun",newYourFunction);
2.3设置公式的值
设置公式执行器环境非必须步骤。
对于单行公式:
Stringfomula="sin(30)*2-56/78";
f.setExpress(fomula);
对于多行公式:
String[]formulas=newString[]
{
"viewmny1->viewnum*viewprice-rate*0.23",
"viewmny2->viewnum*viewprice-rate*0.24"
};
f.setExpressArray(formulas);
2.4对公式进行语法检查
在设置完公式之后,直接调用执行器的check()方法便可以进行公式检查:
boolisok=f.check();
如果返回结果为false,那么说明公式存在语法错误,调用getError()可以获得具体的错误信息:
Stringerrmsg=f.getErrorMsg();
下面是一段具体应用的代码:
FormulaParseFatherf=newnc.ui.pub.formulaparse.FormulaParse();
Stringformula="a->getChineseCurrency(cchmny,34)";
booleanisok=f.check();if(!
isok)
{
System.out.println(f.getError());
return;
}
另外,如果还没有设置公式,仅仅是想校验公式的正确性,则可以直接通过
checkExpress(Stringformula)
或者:
checkExpressArray(formulas)
来检查公式,例如:
boolisok=f.checkExpress(formulas);//单行公式
boolisok=f.checkExpressArray(formulas);//多行公式
注意:
如果是多行公式,那么只要有一个公式写法是错误的,那么检查结果就会是false。
2.5提取公式变量
在单据模板和打印模板的应用中,公式中的变量并不是已知的,需要从公式中分析得到,取得公式中的变量之后,再把相应的值赋给变量。
新版公式解析器
中提取公式中变量的接口和老版是一致的:
VarryVO[]varrys=f.getVarryArray();
下面是单据模板里取公式变量的典型代码:
//设置表达式
formulas=filterUsedFormulas(bfc,formulas);
if(formulas==null)
returnnull;
f.setExpressArray(formulas);
//获得变量名
finalVarryVO[]varrys=f.getVarryArray();
2.6给公式变量赋值
下面是一段给公式变量赋值的代码:
//下列代码假设varrys不会为null
VarryVO[]varrys=f.getVarryArray();
for(inti=0;i { String[]varries=varrys[i].getVarry(); //提取公式变量非必须步骤 if(varries! =null) { for(intj=0;j { //从外部环境取得变量的值 ObjectvarryValue=getVarryValue(varries[j]); //传递给公式 f.addVariable(varries[i],varryValue); } } } 2.7取得公式的值 根据公式具体的应用场景,取值有多种形式,如下所示: 单行公式返回单个值: Objectres=f.getValueAsObject(); 单行公式返回一列值: Object[]res=f.getValueO(); 多行公式返回多列值: Object[][]res=f.getValueOArray(); 单行公式返回单个字符串 Stringres=f.getValue(); 单行公式返回一列字符串: String[]res=f.getValueS(); 多行公式返回多列字符串 String[][]res=f.getValueOArray(); 3.数值型计算结果小数位的控制 当利用公式解析器进行数值型的运算时,可以对输出结果的小数位进行控制。 公式解析器中提供了以下几个接口: publicvoidsetScale(intscale); 设置返回精度,截位默认为四舍五入。 对Double,UFDouble型返回结果有效。 publicvoidsetScale(intscale,introundingup); 设置返回精度及截位规则,对Double,UFDouble型返回结果有效。 publicvoidsetScale(Stringvarname,intscale); 针对具体的变量设置返回精度,截位默认为四舍五入。 publicvoidsetScale(Stringvarname,intscale,introundingup); 针对具体的变量设置返回精度及截位规则,对所有数值型返回结果有效。 如果不做任何设置,那么输出结果与UFDouble的默认精度一致,为8位小数。 下面是一个具体的示例: FormulaParseFatherf=newnc.ui.pub.formulaparse.FormulaParse(); String[]formulas=newString[] { "a->cchmny*cchmny*cchmny", "b->a*cchmny", "c->a*b*cchmny" }; f.setExpressArray(formulas); Mapmap=newHashMap(); Listv2=newArrayList(); v2.add(newUFDouble(1.99999));//rowvalue v2.add(newUFDouble(2.9999));//rowvalue v2.add(newUFDouble(3.99999)); v2.add(newUFDouble(1.999994));//rowvalue map.put("cchmny",v2); f.setDataSArray(map); f.setScale("a",5); f.setScale("b",6); Object[][]res=f.getValueOArray(); assertEquals("应该相等! ","7.99988",res[0][0].toString()); 10 assertEquals("应该相等! ","15.999680",res[1][0].toString()); //默认精度为8 assertEquals("应该相等! ","255.98976018",res[2][0].toString()); 4.自定义变量的使用 公式支持自定义变量,只要相关的操作允许的话,自定义变量可以是任何类型的,下面的代码说明了如何加入一个名为var1,UFDouble型的变量: FormulaParseFatherf=newnc.ui.pub.formulaparse.FormulaParse(); Stringformula="a->round(var1,3)"; f.addVariable("var1",newUFDouble(3.56893)); 除了可以加入简单类型的变量,还可以加入ArrayList3,用户自定义对象4等等,下面的代码演示了如何加入一个ArrayList型的变量: FormulaParseFatherf=newnc.ui.pub.formulaparse.FormulaParse(); Stringformula="a->round(var1,3)"; Listlist1=newArrayList(); list1.add(newUFDouble(56.2354)); list1.add(newUFDouble(23.2343)); f.addVariable("var1",list1); 另外还可以批量的加入多个变量,公式解析器提供两个接口如下: setDataSArray(Hashtable[]);//老版接口要求,不推荐使用 setDataSArray(Map); 需要注意的是,由于老版接口setDataSArray(Hashtable[])所有的参数均通过字符串传入,所以在以此方式传入参数时,存在真假字符串之分,真字符串形如: v1[0]="\"SHVO0000000000000005\""; v1[1]="\"SHVO0000000000000005\""; v1[2]="\"SHVO0000000000000005\""; 即在字符串的两端加上双引号”,表示传入的参数为String类型,如果两端不加这个符号,则表示传入的为数值型,公式解析器会将其转换为数值型处理,例如: v1[0]="623.23"; v1[1]="5263.12"; v1[2]="5242.01"; 而如果通过addVariable(name,Value)或者以setDataSArray(Map)方式传入参数时,参数的类型取决于实际传入的类型,公式解析器不会做任何转换: -),请注意下面两段代码的差别。 老版公式接口,判断真假字符串: FormulaParseFatherf=newnc.ui.pub.formulaparse.FormulaParse(); f.setExpress("a->var1+var2"); Listv2=newArrayList(); v2.add("100");//rowvalue v2.add("200");//rowvalue Hashtablemap=newHashtable(); map.put("var1",v2); map.put("var2",v2); Hashtable[]maps=newHashtable[1]; maps[0]=map; f.setDataSArray(maps);//将会转为数值 f.setScale (2); String[]res=f.getValueS(); assertEquals("Shouldequal: ","200.00",res[0].toString()); 新版增加的接口,传什么就是什么,完全按Object方式传递参数: FormulaParseFatherf=newnc.ui.pub.formulaparse.FormulaParse(); f.setExpress("a->var1+var2"); Listv2=newArrayList(); v2.add("100");//rowvalue v2.add("200");//rowvalue Mapmap=newHashMap(); map.put("var1",v2); map.put("var2",v2); f.setDataSArray(map);//当作字符串 f.setScale (2); String[]res=f.getValueS(); assertEquals("Shouldequal: ","100100",res[0].toString()); 注意: 公式中的变量取名不可与内置自定义变量名(可参考附录内置变量列表)相同,也不得与内置的函数名(可参考附录内置公式列表)相同。 如果和内置变量相同,公式解析可能会得到不正确的结果;如果变量和内置函数名相同,则会报公式解析错误。 5.如何从公式中提取变量 单据模板和打印模板的公式解析要求可以解析识别公式中的列变量,以便从模板中取得相应的值赋给这些列变量。 比如对下面的公式: String[]formulas=newString[] { "viewcode->getColValue(hyca_viewobj,viewcode, pk_viewobj,pk_viewobj)", "viewchinaname->getColValue(hyca_viewobj,viewchinaname, pk_viewobj1,pk_viewobj1)", "summny->cchmny*25/5+cchmny" } FormulaParseFatherf=newnc.ui.pub.formulaparse.FormulaParse(); f.setExpressArray(formulas); 得到的varrys的信息如下: varrys[0]: formulaName: viewcode;varry[1]: pk_viewobj varrys[1]: formulaName: viewchinaname;varry[1]: pk_viewobj1 varrys[2]: formulaName: summny;varry[1]: cchmny 其中VarryVO的定义如下: publicclassVarryVO { StringformulaName=null;//公式名: 等号左边 String[]varry=null;//变量,等号右边的变量 } 利用varrys的信息就可以从模板中取得相应列变量的值,并将公式返回的值赋给每行公式左边列名所对应的列。 下面是提取变量的另一个例子,演示了从复杂的函数中提取列变量: String[]formulas=newString[] { "viewcode->hyca_viewobj*cvn(hyca_viewobj,viewcode, pk_viewobj,pk_viewobj) +viewcode*cvs(hyca_viewobj,viewcode, pk_viewobj,pk_viewobj1)", "viewchinaname->getColNmV(hyca_viewobj,viewchinaname, pk_viewobj,pk_viewobj2)" }; FormulaParseFatherf=newnc.ui.pub.formulaparse.FormulaParse(); f.setExpressArray(formulas); VarryVO[]varrys=f.getVarryArray(); assertEquals("应该相等! ",2,varrys.length); assertEquals("应该相等! ",4,(varrys[0].getVarry()).length); 6.空值””,NULL值及Zero值的处理 在公式解析中,请注意区分以下三个概念: 空值: 指长度为0的字符串,"" NULL值: 指没有分配任何空间的Object,类似JAVA语言里的NULL Zero值: 指Double(0) 公式执行器有一个共有函数setNullAsZero(booleanvalue),用于设置在运算过程中是否需要将NULL值作为Zero值来进行运算。 默认状态下,公式执行器设置setNullAsZero(false)。 请看下面的例子: Stringformula[]=newString[]{ "a->val1/val2", "b->val1*val2" }; FormulaParseFatherf=newFormulaParse(); f.addVariable("val1",null); f.addVariable("val2",newDouble(56)); f.setExpressArray(formula); f.setNullAsZero(true);//设置为true String[][]res=f.getValueSArray(); //val1当做Double(0)计算,得出a=0 assertEquals("应该相等! ","0.00000000",res[0][0]); //val1当做Double(0)计算,得出b=0 assertEquals("应该相等! ","0.00000000",res[1][0]); 如果上例中setNullAsZero(false),因为null值无法参与运算,那么得到的结果为空。 对于setNullAs
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- NCV5 公式 技术 红皮书