NCV60公式技术红皮书.docx
- 文档编号:12702037
- 上传时间:2023-04-21
- 格式:DOCX
- 页数:47
- 大小:33.77KB
NCV60公式技术红皮书.docx
《NCV60公式技术红皮书.docx》由会员分享,可在线阅读,更多相关《NCV60公式技术红皮书.docx(47页珍藏版)》请在冰豆网上搜索。
NCV60公式技术红皮书
公式解析器使用指南
第一章新版公式使用手册2
1.1公式主要功能2
1.2公式的基本使用方法3
1.3数值型计算结果小数位的控制6
1.4自定义变量的使用7
1.5如何从公式中提取变量9
1.6空值””,NULL值及Zero值的处理10
1.7如何进行列操作11
1.8利用定义函数扩展公式功能12
1.9外接函数的使用13
1.10(5.02new)配置装载自定义函数13
1.11运算符重载14
1.12公式简单调试15
1.13公式使用最佳实践17
附录:
公式解析器内置公式列表21
3.1数学运算函数21
3.2条件判断函数24
3.3数据库查询函数25
3.4字符串相关函数27
3.5日期函数28
3.6类型转换函数28
3.7货币金额函数29
3.8多语言翻译函数31
3.9其他函数31
3.105.02新增函数31
3.11V5.5新增函数32
第一章新版公式使用手册
1.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.支持自定义函数.具体应用可参考后面的详细说明(第17页第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();
15.支持单表查询类公式的自动SQL合并,极大提高查询效率(V56版本)。
1.2公式的基本使用方法
使用公式解析器的基本步骤如下:
1.创建公式执行器
如果在客户端使用公式解析:
FormulaParseFatherf=new;
如果在服务端使用公式解析:
FormulaParseFatherf=new;
如果不知道当前的代码会在哪一端运行,可以用下面的方法进行判断:
if(RuntimeEnv.getInstance().isRunningInServer()){
parse=new;
}else{
parse=new;
}
如果在客户端执行公式,但是又不希望使用前台缓存(注:
在前台通过公式查询跨公司大数据档案时会严重影响LFU算法效果,导致前台缓存数据量急剧增加,影响缓存的稳定性,此种场景下不建议在前台执行公式,所以NC报表类执行公式要求不走前台缓存),可以使用:
FormulaParseFatherf=new;
2.设置公式执行器环境(自定义变量及自定义函数可参考后续章节描述)
这里可以给公式执行器添加自定义变量,例如:
UFDoublevar1=newUFDouble(5.368);
f.addVariable(var1);
或者添加自定义函数,例如:
类YourFunction是一个定义的函数类(关于如何自
定义函数,请参考自定义函数一节),在公式中函数取名为"yourfun",则可以这样
添加你的自定义函数:
f.addFunction("yourfun",newYourFunction);
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);
4.对公式进行语法检查
在设置完公式之后,直接调用执行器的check()方法便可以进行公式检查:
boolisok=f.check();
如果返回结果为false,那么说明公式存在语法错误,调用getError()
可以获得具体的错误信息:
Stringerrmsg=f.getErrorMsg();
下面是一段具体应用的代码:
FormulaParseFatherf=new;
Stringformula="a->getChineseCurrency(cchmny,34)";
booleanisok=f.check();if(!
isok)
{
;
return;
}
另外,如果还没有设置公式,仅仅是想校验公式的正确性,则可以直接通过
checkExpress(Stringformula)
或者:
checkExpressArray(formulas)
来检查公式,例如:
boolisok=f.checkExpress(formulas);//单行公式
boolisok=f.checkExpressArray(formulas);//多行公式
注意:
如果是多行公式,那么只要有一个公式写法是错误的,那么检查结果就会
是false。
5.提取公式变量
在单据模板和打印模板的应用中,公式中的变量并不是已知的,需要从公式中
分析得到,取得公式中的变量之后,再把相应的值赋给变量。
新版公式解析器
中提取公式中变量的接口和老版是一致的:
VarryVO[]varrys=f.getVarryArray();
下面是单据模板里取公式变量的典型代码:
//设置表达式
formulas=filterUsedFormulas(bfc,formulas);
if(formulas==null)
returnnull;
f.setExpressArray(formulas);
//获得变量名
finalVarryVO[]varrys=f.getVarryArray();
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); } } } 7.取得公式的值 根据公式具体的应用场景,取值有多种形式,如下所示: 单行公式返回单个值: Objectres=f.getValueAsObject(); 单行公式返回一列值: Object[]res=f.getValueO(); 多行公式返回多列值: Object[][]res=f.getValueOArray(); 单行公式返回单个字符串 Stringres=f.getValue(); 单行公式返回一列字符串: String[]res=f.getValueS(); 多行公式返回多列字符串 String[][]res=f.getValueOArray(); 1.3数值型计算结果小数位的控制 当利用公式解析器进行数值型的运算时,可以对输出结果的小数位进行控制。 公式 解析器中提供了以下几个接口: publicvoidsetScale(intscale); 设置返回精度,截位默认为四舍五入。 对Double,UFDouble型返回结果有效。 publicvoidsetScale(intscale,introundingup); 设置返回精度及截位规则,对Double,UFDouble型返回结果有效。 publicvoidsetScale(Stringvarname,intscale); 针对具体的变量设置返回精度,截位默认为四舍五入。 publicvoidsetScale(Stringvarname,intscale,introundingup); 针对具体的变量设置返回精度及截位规则,对所有数值型返回结果有效。 如果不做任何设置,那么输出结果与UFDouble的默认精度一致,为8位小数。 下面是一个具体的示例: FormulaParseFatherf=new; 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.",res[2][0].toString()); 1.4自定义变量的使用 公式支持自定义变量,只要相关的操作允许的话,自定义变量可以是任何类型的,下面的代码说明了如何加入一个名为var1,UFDouble型的变量: FormulaParseFatherf=new; Stringformula="a->round(var1,3)"; f.addVariable("var1",newUFDouble(3.56893)); 除了可以加入简单类型的变量,还可以加入ArrayList3,用户自定义对象4等等,下面的代码演示了如何加入一个ArrayList型的变量: FormulaParseFatherf=new; 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=new; 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=new; 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()); 注意: 公式中的变量取名不可与内置自定义变量名(可参考第25页第2章内置变量列表)相同,也不得与内置的函数名(可参考第26页第3章内置变量列表)相同,如果和内置变量相同,公式解析可能会得到不正确的结果;如果变量和内置函数名相同,则会报公式解析错误。 1.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=new; 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=new; f.setExpressArray(formulas); VarryVO[]varrys=f.getVarryArray(); assertEquals("应该相等! ",2,varrys.length); assertEquals("应该相等! ",4,(varrys[0].getVarry()).length); 1.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值无法参与运算,那么得到的结果为空。 对于setNullAsZero函数,需要注意的是,NULL值当作Zero值来处理仅仅是指在运算过程中,不适用于返回值为NULL时的处理,例如: Stringformula[]="a->val1"; FormulaParseFatherf=newFormulaParse(); f.addVariable("val1",null); f.setExpress(formula); f.setNullAsZero(true); Stringres=f.getValue(); //val1当做Double(0)计算,但结果res为空值. 如果上例中,想要返回0,则可以这么改写公式: Stringformula[]="a->toNumber(val1)"; Formu
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- NCV60 公式 技术 红皮书