《BOS进阶培训-套打二次开发.ppt》由会员分享,可在线阅读,更多相关《BOS进阶培训-套打二次开发.ppt(76页珍藏版)》请在三一办公上搜索。
1、BOS进阶培训 套打二次开发,金蝶软件(中国)有限公司,商业分析系统部 李馥龙,目录,1、相关概念2、模板设计概述3、套打调用基本API4、数据提供者5、二次开发6、高级应用及API7、常见问题分析处理8、附:模板中的脚本,目录,1、相关概念2、模板设计概述3、套打调用基本API4、数据提供者5、二次开发6、高级应用及API7、常见问题分析处理8、附:模板中的脚本,相关概念套打,什么是套打?套打能做什么?,行业:在印刷好的表格中打印内容(凭证、帐簿、支票),EAS中的“套打”:自定义格式的票据、单据、报表的打印,广义的概念,EAS中的套打功能,处理除序时簿打印之外所有打印需求。,名称由来?沿袭
2、,狭义,套打模式 主要特征:每页格式一样,不在于是否用套打纸,相关概念套打,报表模式,相关概念基本原理,“平台”?“控件”?,模板,+数据,=结果,相关概念基本原理,模板统一管理,使用(调用)分散在各业务界面,“平台”?“控件”。,不是子系统树目录名称不能乱改,相关概念文件类型,套打元数据提供一种集成方式、字段的描述信息、只影响模板设计(*.bos-query)KDF 模板(废)KDF系列的Form格式(*.kdrs-form)ReportOne 模板ReportOne系列的Print格式(*.r1-print),相关概念KDF/ReportOne,2003,2006,2007,2008,1,
3、2,3,KDTable,报表平台,套打,控件,KDForm(),R1-Form(),4,R1-Print,5,1,扩展报表,KDF,ReportOne,扩展报表,目录,1、相关概念2、模板设计概述数据源设置组件及规则基本模式3、套打调用基本API4、数据提供者5、二次开发6、高级应用及API7、常见问题分析处理8、附:模板中的脚本,模板设计概述参考资料,参考 用户手册 BOS6.2 全参考 BOS开发者网络 http:/开发文档-BOS开发指南-BOS开发指南_套打模板制作(主要讲模板规则)研发内网 商业分析知识库 http:/ctrlsrv/ctrls设计器 示例模板生成向导,模板设计概述数
4、据源设置,添加、删除、重命名、参数设置、查看引用信息,重命名(可能有代码依赖),模板设计概述组件及规则:页,一个模板,自动对应了一个页对象。页是模板的可设计区域。通常,页的大小为纸张大小减去四边距后的尺寸,此时页与纸张一一对应,套打模式和大部分报表模式就是这种情形。当多数据源的报表模式,设计时内容就很多,此设计区域容纳不下的时候,允许修改页的高度。运行时,页自动与主数据源绑定。如果不存在“能引起分页的对象(如数据表)”绑定主数据源,则主数据源自动移至其下一条记录使页重复输出。,模板设计概述组件及规则:单元对象,单元对象包括:文字对象、金额对象、图片对象,它提供了一块固定的区域,用于展现对应的内
5、容。此内容可以是绑定字段,或自定义的固定内容。执行时,单元对象本身不引起分页,也不会引起数据源行集移动至下一条记录。注意区别,“单元对象”是离散的矩形区域,不等同于表格的“单元格”。,模板设计概述组件及规则:数据表,数据表是一种表格,它由规整的行、列组成,行列的交汇处为单元格。行、列、单元格是组成表格的基本元素。(注意区别“单元格”不等同于“单元对象”)数据表具有分组展现、统计功能,其数据行能根据数据源行集的每一行重复输出,它是一种可能引起分页的对象。数据表必须绑定唯一的一个数据源。行:普通行、分组行、数据行“套打型”和“报表型”单元格,类型(文字、字段、统计、容器等),融合,模板设计概述组件
6、及规则:网格,网格也是一种表格,同样由行、列、单元格是组成。网格本身不绑定数据,它的行没有类型;单元格可以输入文字、绑定字段或者作为容器放置其它对象。二个主要作用:布局(展示)、组合多个数据表,为了满足不确定内容的横向、折行排列需求。设计期定义的一块可供重复内容的区域,以及区域中的一个容器(可以直接绑定字段或放置内容组合)。区域绑定数据源。执行时,数据源的行集,每一行对应输出一个容器,并按预先设置好的方向排列:横向折行或纵向换列。,模板设计概述组件及规则:动态列表,模板设计概述基本模式,票据模式单据套打模式多数据源单据套打模式报表模式多数据源报表模式,票据模式单据套打模式多数据源单据套打模式报
7、表模式多数据源报表模式,模板设计概述基本模式1,主要特征:*单数据源*数据源的每一行记录对应一张票据*不带分录直接在页面上放置单元对象、可导入背景图片执行时,页自动与数据源绑定,对应行集的每一条记录重复输出多张票据。,票据模式单据套打模式多数据源单据套打模式报表模式多数据源报表模式,模板设计概述基本模式2,RowSet 形如:单据ID单据其它字段分录ID分录其它字段第1行单据A分录A-1第2行单据A分录A-2第3行单据B分录B-1第4行单据B分录B-2第5行单据B分录B-3第6行单据C分录C-1单数据源,数据表按单据ID分组,数据行设置套打型,分组行设置每页出现。,HD,模板设计概述基本模式3
8、,票据模式单据套打模式多数据源单据套打模式(如带审批的单据)报表模式多数据源报表模式,并列放二个数据表,套打型在前例的数据源(分组)的基础上,只能做成套打型。若希望做成报表型,必须修改数据源结构(变成多数据源报表模式)。,HmD,H,D1,D2,Btw.HDD,H,D1,D2,合起来,做分组,票据模式单据套打模式多数据源单据套打模式报表模式多数据源报表模式,模板设计概述基本模式4,“报表型”区别于“套打型”的特点是:不限定每页显示数据行数,行高可随内容自动调整(行高自适应),通常为第一页开头是表头,表体内容跨若干页,最后一页是表尾的形式。和单据套打类似,用一个数据表就可以解决问题。对数据表做必
9、要的分组;数据行设置为“报表型”;普通行、分组行的“每页出现”属性按需要设置。分组统计如果做在分组行,就是这一层分组的小计;做在普通行则是总计。,票据模式单据套打模式多数据源单据套打模式报表模式多数据源报表模式(简历模式),模板设计概述基本模式5,HmD,H,D1,D2,目录,1、相关概念2、模板设计概述3、套打调用基本API4、数据提供者5、二次开发6、高级应用及API7、常见问题分析处理8、附:模板中的脚本,套打调用基本API,KDNoteHelpercom.kingdee.bos.ctrl.report.forapp.kdnote.client.KDNoteHelper 类提供了统一的套
10、打调用API。数据提供者套打控件只识别取数接口(现在也提供查询Query的缺省实现DefaultNoteDataProvider,且推荐使用),具体的取数实现都是各业务集成时各自实现。对于实现取数接口的、给套打执行时提供数据的类,称之为DataProvider数据提供者。业务开发中,通常界面上会有 打印/打印预览 按钮,在框架的ListUI/EditUI类中,会有类似actionPrint_actionPerformed或actionPrintPreview_actionPerformed方法与之对应,套打的调用代码写在这样的方法中。,套打调用基本API,打印public void print
11、(String templateType,Object dataProvider,Component owner,boolean isShowPrinterDialog)参数说明:,这不是套打控件规定的用法了解,但不要被束缚。,套打调用基本API,打印预览public void printPreview(String templateType,Object dataProvider,Component owner)参数说明:,套打调用基本API,R1模板,取数接口AbstractPrintDataProvider,KDF模板,取数接口BOSQueryDelegate,适配器,DataProvi
12、der的类型声明是Object的附加说明,控件的内部实现,业务开发不用关心。了解,不会有疑惑。,代码只能有一份(要么旧的,要么新的);模板可能是任意的。怎么办?,套打调用基本API,为什么套打管理的目录名称不能乱改?(大小写敏感),目录,1、相关概念2、模板设计概述3、套打调用基本API4、数据提供者取数接口说明自定义实现查Query的缺省实现KDF取数接口对比5、二次开发6、高级应用及API7、常见问题分析处理8、附:模板中的脚本,数据提供者取数接口说明,package com.kingdee.bos.ctrl.reportone.r1.print.data;import com.kingd
13、ee.jdbc.rowset.IRowSet;/*since EAS 5.4*/public abstract class AbstractPrintDataProvider public abstract IRowSet getData(R1PrintDataSource dataSource)throws Exception;,套打模板中一个“数据源”,在执行过程中,执行引擎会通过此取数接口找集成环境要数据。,客户端,数据提供者取数接口说明,业务场景,套打控件,DataProvider,API,UI,执行引擎,数据提供者取数接口说明,实现示例(注意,不是套打控件规定的用法)public c
14、lass DemoDataProvider extends AbstractPrintDataProviderprivate Set billIds=null;private IMetaDataPK qpk=null;public DemoDataProvider(List billIdList,IMetaDataPK qpk)this.billIds=new HashSet(billIdList);this.qpk=qpk;public IRowSet getData(R1PrintDataSource dataSource)throws ExceptionIQueryExecutor ex
15、ec=QueryExecutorFactory.getRemoteInstance(qpk);exec.option().isAutoTranslateEnum=true;EntityViewInfo ev=new EntityViewInfo();FilterInfo filter=new FilterInfo();filter.getFilterItems().add(new FilterItemInfo(id,billIds,CompareType.INCLUDE);ev.setFilter(filter);exec.setObjectView(ev);IRowSet iRowSet=e
16、xec.executeQuery();return iRowSet;,public abstract class AbstractDemoEditUI extends.public void actionPrint_acrionPerformed(ActionEvent e)throws ExceptionKDNoteHelper hlp=new KDNoteHelper();DemoDataProvider dataProvider=new DemoDataProvider(.,new MetaDataPK(getTDQueryPK();hlp.print(getTDFileName(),d
17、ataProvider,this);protected String getTDFileName()protected String getTDQueryPK()public class DemoEditUI extends AbstractDemoEditUIprotected String getTDFileName()return/DemoA/DemoB/DemoC;protected String getTDQueryPK()return com.kingdee.demo.DemoQuery;,数据提供者取数接口说明,public abstract class AbstractPrin
18、tDataProvider public abstract IRowSet getData(R1PrintDataSource dataSource)throws Exception;public class R1PrintDataSource/*数据源名称*/public String getId()/*取得表示数据源依赖于其它数据源的参数*/public R1PrintDataParameter getAssociateParameter()/*取得指定名称的参数*/public R1PrintDataParameter getParam(String id)/*引用BOS Query的信
19、息,MetaDataPK的fullName*/public String getReference()/*取得所有排序字段(目前只是分组字段)*/public R1PrintDataSortItem getSortFields()/*创建BOS查Query所需的EntityViewInfo,*它包括了动态查询、模板中指定的排序等信息。*注意它不包含参数信息(如getAssociateParameter)。*/public EntityViewInfo createWrappedBosRuntimeInfo(),数据提供者取数接口说明,如果模板中存在多个数据源,执行时也都是通过这个唯一的接口取数
20、。实现代码中通过dataSource.getId()识别不同数据源。换句话说,数据源名称是集成环境预先定义好的,模板中必须按此命名。当然,如果模板中直接引用Query,而取数实现又对查Query做了支持(例如使用了DefaultNoteDataProvider),则名称无关紧要。通常多数据源存在“主-从”结构,即有依赖的情况,主数据源被依赖的字段值发生变化,从数据源会被要求重新取数。所以,即使是模板设计时逻辑上的“一个”数据源,也可能是多次由getData取得RowSet。此时,从数据源的取数是必须通过dataSource.getAssociateParameter().getValue()取
21、得所依赖的值作过滤的。,数据提供者自定义实现,publicclassDemoDataProviderextendsAbstractPrintDataProvider publicIRowSetgetData(R1PrintDataSourcedataSource)throwsExceptionif(主数据源名称.equals(dataSource.getId()/可能会以选中数据的ID做过滤条件查数据/构造RowSet returnrowset;elseif(从数据源名称.equals(dataSource.getId()R1PrintDataParameterparm=dataSource.
22、getAssociateParameter();StringparmValue=null;/参数值 if(parm!=null)parmValue=parm.getValue().toString();/以参数值为过滤条件取数据,构造RowSet returnrowset;/其它分支,数据提供者自定义实现,自行构造RowSet的参考代码:DynamicRowSet drs=new DynamicRowSet(3);/3列drs.setColInfo(1,field1,field1,Types.VARCHAR,null);drs.setColInfo(2,field2,field2,Types.
23、DECIMAL,null);drs.setColInfo(3,field3,field3,Types.BINARY,null);for(int i=1;i=10;i+)/10行drs.moveToInsertRow();drs.updateString(field1,第+i+行);drs.updateBigDecimal(field2,new BigDecimal(i);drs.updateBytes(field3,new byte0);/可支持图片drs.insertRow();drs.beforeFirst();,Btw.图片字段代码拼RowSet:rowset.setColInfo(,T
24、ypes.BINARY,);rowset.updateBytes(,byte);查Query:数据库,字段类型BLOBQuery,字段类型Object,数据提供者查Query的缺省实现,/*since EAS 5.9*/com.kingdee.bos.ctrl.report.forapp.kdnote.client.DefaultNoteDataProvider,数据提供者查Query的缺省实现,例1:kdNoteHelper.print(path,new DefaultNoteDataProvider(dataIds),ctrl);这是最简单的使用方法,创建实例后直接使用。其中,dataId
25、s是单据的“id”字段的值,java.util.List或java.util.Set。它可以是EditUI一个单据的id,也可以是ListUI选中的一批单据的id。此种写法要求模板中一定要直接引用Query。如果是多数据源的情况,依赖关系中参数名称一定要当前数据源作为“外键”的字段。,数据提供者查Query的缺省实现,例2:为了兼容模板中引用套打元数据(无Query信息)的方式,可以指定缺省的Query。DefaultNoteDataProvider dataProvider=new DefaultNoteDataProvider(dataIds);dataProvider.setMetaDa
26、taPK(com.kingdee.XxxQuery);kdNoteHelper.printPreview(path,dataProvider,ctrl);,数据提供者查Query的缺省实现,例3:多数据源的情况,对每个数据源都指定缺省的Query,且为从数据源的依赖关系指定作为“外键”的字段(则模板中数据源做依赖关系的参数名称可以随意写)。此例中,假设从数据源名称为“subData1”,字段为“parentId”。dataProvider.addMetaDataPK(subData1,com.XxxQuery1);dataProvider.addForeignKey(subData1,pare
27、ntId);,数据提供者查Query的缺省实现,例4:(自定义过滤条件)dataProvider.addCustomFilterMaker(subData1,new DefaultNoteDataProvider.ICustomFilterMaker()public void customize(FilterInfo filter,R1PrintDataParameter params)filter.getFilterItems().add(new FilterItemInfo(status,MultiApproveStatusEnum.SUBMIT_VALUE););ICustomFilte
28、rMaker是DefaultNoteDataProvider的内部接口,允许在查Query的时候通过代码指定固定的过滤条件。其实在DefaultNoteDataProvider内部,主数据源也已经包含了如下的过滤条件:filter.getFilterItems().add(new FilterItemInfo(id,dataIds,CompareType.INCLUDE);所以在前面出现的例子中,可以在构造函数中传dataIds。如果主数据源不是要过滤id字段,也可以通过setCustomFilterMaker接口修改。,数据提供者查Query的缺省实现,例5:(代理)可以将dataProvi
29、der作为代理,而将真实的取数任务转发给另外一个实现。DefaultNoteDataProvider dataProvider=new DefaultNoteDataProvider(dataIds);AbstractPrintDataProvider anotherDataProvider=new MyDataProvider();dataProvider.addProxyTarget(subData1,anotherDataProvider);,数据提供者查Query的缺省实现,例6:(性能优化)在具有主从关系的多数据源中,主数据源被依赖字段值的变化,都会导致每个从数据源取一次数。如果每次
30、都是通过远程执行一次查询,在广域网的环境中,多次的RPC可能成为性能的瓶颈。DefaultNoteDataProvider提供了批量查询的功能,可以通过开关开启。dataProvider.setBatchSupported(true);dataProvider.setNumberOfEachBatch(100);,数据提供者查Query的缺省实现,public class R1PrintDataSource/*数据源名称*/public String getId()/*取得表示数据源依赖于其它数据源的参数*/public R1PrintDataParameter getAssociatePar
31、ameter()/*取得指定名称的参数*/public R1PrintDataParameter getParam(String id)/*引用BOS Query的信息,MetaDataPK的fullName*/public String getReference()/*取得所有排序字段(目前只是分组字段)*/public R1PrintDataSortItem getSortFields()/*创建BOS查Query所需的EntityViewInfo,*它包括了动态查询、模板中指定的排序等信息。*注意它不包含参数信息(如getAssociateParameter)。*/public Enti
32、tyViewInfo createWrappedBosRuntimeInfo(),BIM生成的单据,套打调用时使用了DefaultNoteDataProvider。,只要模板中直接引用不同的Query,可以出不同的数据。,“套打二次开发不用写代码!”,能不能做成控件的内部实现,集成时不传DataProvider?,No,过滤条件,public class DemoDataProvider implements BOSQueryDelegate public IRowSet execute(BOSQueryDataSource ds)if(主数据源名称.equals(ds.getID()/返加主
33、数据源的结果集 else if(从数据源名称.equals(ds.getID()String paramVal=null;ArrayList ps=ds.getParams();if(ps.size()0)DSParam param=(DSParam)ps.get(0);paramVal=param.getValue().toString();/返回参数值为paramVal的子数据源的结果集/其它分支,数据提供者KDF取数接口对比,publicclassDemoDataProviderextendsAbstractPrintDataProvider publicIRowSetgetData(R
34、1PrintDataSourcedataSource)throwsException if(主数据源名称.equals(dataSource.getId()/可能会以选中数据的ID做过滤条件查数据/构造RowSet returnrowset;elseif(从数据源名称.equals(dataSource.getId()R1PrintDataParameterparm=dataSource.getAssociateParameter();StringparmValue=null;/参数值 if(parm!=null)parmValue=parm.getValue().toString();/以参
35、数值为过滤条件取数据,构造RowSet returnrowset;/其它分支,目录,1、相关概念2、模板设计概述3、套打调用基本API4、数据提供者5、二次开发6、高级应用及API7、常见问题分析处理8、附:模板中的脚本,二次开发,何谓“二次开发”?(此处省去一万字)“二次开发”是很空泛的说法,看具体做什么事情。写代码新做的业务模块BIM生成的单据标准业务数据不满足要求,二次开发,写代码新做的业务模块在按钮的事件代码中调用套打控件API,指定模板所在路径及数据提供者。BIM生成的单据BIM已替你生成了套打调用代码,生成模板存储路径、套打元数据、模板。可以在UI子类中覆盖getTDFileNam
36、e()方法改变模板所在路径;可以在UI子类中覆盖getTDQueryPK()方法改变缺省的给套打提供数据的Query。由于自动生成的代码使用了DefaultNoteDataProvider,可以在模板中直接引用任意Query,执行时就是用该Query取数。标准业务数据不满足要求财务,大部分是代码构造RowSet供应链、协同,大多是指定固定的Query提供数据,可以改这个Query。(供应链,XxxPrintQuery)协同(?),在UI子类中可以拿到DataProvider,put(key,anotherDataProvider),(key就是数据源名称,ifelse if,代理),二次开发,
37、标准业务数据不满足要求(续)怎么确定标准模块写死的是哪个Query?猜!问!(业务模块是否有帮助文档?)反编译!能不能知道当前场景用的是哪个数据提供者?在预览界面按F1,二次开发,结果集再加工,/*允许二次开发对套打数据源结果集再加工*/public abstract class AbstractDataProcessor/*对结果集再加工*param rowSet 系统得到的结果集*param ds 模板的数据源信息*return*throws Exception*/abstract public IRowSet process(IRowSet rowSet,R1PrintDataSourc
38、e ds)throws Exception;,二次开发,“连续套打”业务上需求,控件没有连续不连续的概念。EditUI(一张单据)=ListUI(多张单据)DataProvider支持取到数据。模板可能需要稍微修改(假如做分组)。,二次开发,数据汇总(月度订单汇总、部门工资汇总、)数据提供的方式定制Query,模板引用它(必须DataProvider支持);或者有办法扩展DataProvider,通过不同名称识别不同数据源。本质:SQL-group by模板的方式,不推荐(性能),二次开发,单据加审批意见数据提供的方式使DataProvider支持模板的方式,ID 单据号Number,二次开发
39、,按计量单位合计A1件B2个C3件D4个共4件,6个模板目前不支持做这样的统计,只能由数据源提供。,目录,1、相关概念2、模板设计概述3、套打调用基本API4、数据提供者5、二次开发6、高级应用及API7、常见问题分析处理8、附:模板中的脚本,高级应用及API直接打印,“直接打印”?直接打印1kdNoteHelper.print()第四个参数isShowPrinterDialog传false。第一次用选模板时记缺省模板。,高级应用及API 直接打印,直接打印2public int directPrint(String templatePath,Object dataProvider,boole
40、an isPreview,Component owner,boolean isShowPrinterDialog)第一个参数是指向模板,不是指向模板所在目录。“/DemoPath”=“/DemoPath/DemoTemplate.r1-print”第三个参数,isPreview,预览.print/.printPreview=.directPrint(true/false),可以单独弹出选模板对话框:(要挂另一个按钮,还要保存结果)public String selectTemplatePath(Component owner,String oldPath,String dir)oldPath:
41、上一次模板全路径;dir:目标文件夹。返回:模板全路径和别名,高级应用及API 打印次数控制,打印次数控制(或记录打印日志)在 打印 按钮事件中做?选打印机时取消、预览后点打印、预览后不打印public void addKDNoteActionListener(IPrintActionListener listener)在IPrintActionListener的beforePrint事件中完成。注意,beforePrint发生在数据传送给打印机之前,可以认为就是真实的打印发生了。打印时是与外部设备(打印机)通讯,由于技术上的原因,目前不存在“打印后”或“打印顺利完成”事件。,高级应用及API
42、 打印次数控制,/*在套打管理中,可以对一个业务单元(文件夹)设置数据的最多打印次数。此方法用于获取该设置值。*/public int getMaxPrintTimes2(String templateType)throws KDRSException/*如果在一个业务路径上设置了打印次数控制,该方法将返回true。*/public boolean isPrintTimesControllable2(String templateType)/*取得打印设置中,一次打印的份数。*/public int getCopies()/*设置一次打印的份数。*/public void setCopies(
43、int times)/*取消打印*/public void diposePrint()通常的实现逻辑:数据的实际打印次数由业务开发自行管理。每次打印前,判断已打份数是否达到最多打印次数(getMaxPrintTimes),达到了不能继续,取消打印(diposePrint)。再判断已打份数加上将打份数(getCopies)是否超过最多打印次数,超过则调整当前打印份数(setCopies)。记录已打印次数。,高级应用及API 导出PDF,导出PDFpublic boolean outputPdf(String templateType,Object dataProvider,Component o
44、wner,OutputStream outputStream)前三个参数与.print/.printPreview 一样,将内容写到第四个参数输出流。客户端的使用不建议使用此接口,而是安装PDF虚拟打印机,和普通打印一样进行。,高级应用及API 万佛朝宗,/*预览的初始状态,默认为整页。也可以设置为100%。*param isZoomFirstShow*true-整页;*false-100%*/public void setPreviewZoomFirstShow(boolean isZoomFirstShow)一个用套打做GUI报表的故事,目录,1、相关概念2、模板设计概述3、套打调用基本A
45、PI4、数据提供者5、二次开发6、高级应用及API7、常见问题分析处理8、附:模板中的脚本,常见问题分析处理,新添加的字段出不来只是改了套打元数据,字段名称是否对应?修改的不是代码中写死的那个Query。所有字段出不来模板原因(KDF),整个页面空白。数据源名称依赖代码?取数出异常?部分单据出不来,Query的问题:内联接/外联接。,常见问题分析处理,怎样检查数据源有没有数据或某些字段有没有值?模板,用数据表做最简单的列表。开发阶段,在数据提供者return rowset的地方加断点。检查Query,把SQL拷出来执行,但要加上单据ID过滤。,常见问题分析处理,看日志,回调的取数代码发生在这二
46、句日志之间(向外抛时没有After):DataProvider execute.DSs ID:xxxAfter DataProvider execute.DSs ID:xxx,Used time:xxx,如果是KDF模板,相应地是:BOSQuery delegate execute.DSs ID:xxxAfter BOSQuery delegate execute.DSs ID:xxx,Used time:xxx,常见问题分析处理,打印问题预览正常,输出到打印机有问题BOS开发者网络 http:/EAS BOS 下载中心 金蝶BOS打印问题FAQ(michael_huang 2009-07-0
47、2)Mykingdee 产品知识 金蝶BOS 金蝶BOS打印问题FAQ.pdf(黄勇 2009-07-02),目录,1、相关概念2、模板设计概述3、套打调用基本API4、数据提供者5、二次开发6、高级应用及API7、常见问题分析处理8、附:模板中的脚本,模板中的脚本简介,一、脚本语法1、该脚本系统采用类Java/JavaScript的语法。2、面向对象的设计:调用一个对象(假设其名称为text1)的某个方法(假设为getValue),书写为:text1.getValue();如果是当前对象,则text1可省略,直接写为:getValue()。后续说明中,以“对象ID.getValue()”描述
48、,方括号表示可省略。对象相关的方法在第一栏中列出。3、对象无关的方法,称为静态方法。在第二栏中列出。4、大小写敏感。5、变量定义,示例:var a=b+1;请注意,所定义变量的作用域最大只在当前脚本块,全局变量请使用set()、get()函数。二、什么是“前处理”/“后处理”?执行引擎在解析模板过程中,处理目标对象之前运行的脚本,称为该对象的“前处理脚本”,通常可用于修改初始值。执行引擎在解析模板过程中,处理目标对象之后运行的脚本,称为该对象的“后处理脚本”,通常可用于修改对象的输出结果。函数说明中,会在“适用”条目中注明函数适用于前处理或后处理,未注明者为两者皆可。,模板中的脚本示例1,例:
49、“盖章”固定的内容,有条件地控制是否显示。用图片对象,在其“后处理脚本”中写脚本进行控制。假设存在一个叫“是否完成”的字段isFinished,布尔值,单据状态为“完成”则加盖图章。展示图章的图片对象的脚本为:if(getFieldValue(数据源名称,isFinished)setHide(false);elsesetHide(true);脚本不是唯一的,只要符合语法,可以举一反三。上例也可写成:setHide(!getFieldValue(数据源名称,isFinished);或setHide(toStr(getFieldValue(数据源名称,isFinished)!=true);,模板中
50、的脚本示例2,例:true/false=是/否对象绑定目标字段,并在后处理脚本写上setValue(getValue()?是:否);或:setValue(toStr(getValue()=true?是:否);,模板中的脚本示例3,例:字段值拼接对象绑定字段(脚本中可省去写数据源名称),并在后处理脚本写上:var add=;if(getFieldValue(field1)!=null)add=getFieldValue(field1);if(getFieldValue(field2)!=null)add+=(+getFieldValue(field2)+);if(getFieldValue(fi