本文介绍了三种在二次开发(二开)时常用的科目余额表取数方法:1)直接从余额表取数,包括普通余额表和调整期余额表,并介绍了如何根据账簿ID和是否包含调整期凭证选择正确的表名;2)从虚拟余额表取数,虽然旧版本中有,但已不推荐使用,新版本中则推荐使用虚拟过账方法获取包含未过账凭证的余额数据;3)通过WEB API方式取数,介绍了如何通过API接口查询科目余额表数据,包括必要的参数和注意事项。
本文介绍三种二开时常用的科目余额表取数方法,大家可以根据实际情况选择。
一、直接从余额表取数
我们知道,科目余额数据来源于凭证,凭证通过过账,得到各明细科目及其升级科目的累计余额,相关数据保存在我们熟知的科目余额表(T_GL_BALANCE)表中,相似的,如果凭证上的科目启用了数量,那么,过账的同时,还会累计出数量余额,数据保存在数量余额表(T_GL_BALANCEQTY)中,如果科目是损益类科目,也会将数据统计到损益余额表(T_GL_BALANCEPROFIT)中。这就是传说中的三大余额表。
事实上,自从星空系统支持调整期后,如果对应的账簿启用了调整期,那么除了正常期间过账数据产生的三大余额表,还有包含调整期数据的调整期余额表(T_GL_BALANCEADJUST)和调整期数量余额表(T_GL_BALANCEQTYADJUST),它们分别用来存放包含了调整期科目数据的余额和数量余额。也就是说,对于启用了调整期的账簿来说,其普通余额表T_GL_BALANCE和T_GL_BALANCEQTY是调整期的两个余额表T_GL_BALANCEADJUST和T_GL_BALANCEADJUSTQTY的子集。因此,账表取数时,如果需要包含调整期凭证的数据,就从调整期余额表取数,否则就从普通余额表取。
系统提供了统一的方法,只需要来判断指定的账簿是否有调整期并直接返回应该取数的正确表名:
/// <summary> /// 单账簿使用,根据账簿ID和是否包含调整期凭证获取科目余额表的表名和数量余额表表名 /// </summary> /// <param name="ctx">上下文</param> /// <param name="lAccountBookId">账簿ID</param> /// <param name="bExcludeAdjustVch">不包含调整期,默认包含,即默认值为false</param> /// <returns>返回科目余额表名,数量余额表名</returns> public static BalanceTableObject GetBalanceTableName(Context ctx, long lAccountBookId, bool bExcludeAdjustVch = false){...}
获得科目余额表名时,调用方法示例如下:
var strBalanceTblName = Kingdee.K3.FIN.GL.App.Core.VoucherAdjust.BalanceAdjustService.GetBalanceTableName(ctx, lAccountBookId, false).BalanceTbl;
需要注意的是:没有调整期损益余额表,因此,无论是不是调整期数据,损益余额都保存在损益余额表(T_GL_BALANCEPROFIT)中
下图列出了不同凭证过账后余额数据的去向。
因此,二开时,对于取已过账凭证的余额数据或历史期间的余额数据,可以根据是否需要包含调整期凭证,直接从这此余额表中取数。
二,从虚拟余额表取数
在星空的早期版本中,存在一种特殊的余额表,它的表名是T_BL_BALANCE_账簿ID,这是按账簿分别存储的虚拟过账余额表,凭证保存后,各科目的余额数据就会直接进入对应账簿的虚拟余额表中,因此,这个余额表保存了所有凭证,包括未过账凭证的余额数据。但随着系统的迭代更新,该余额表已废弃,系统已不再使用,但为了兼容旧版,该余额表依然存在于账套中。由于已不被新版本系统支持,数据的完整性和准确性无保障,因此,二开时,不建议使用。
在新版本中,如果需要包含未过账凭证的余额数据,可以调用系统提供的虚拟过账方法——VoucherVirPostService.GetVoucherVirPostBalance(),传入适合的参数,即可返回相应的临时表名,包括余额表(BalaneTemp),数量余额表(QtyBalanceTemp)和损益余额表(ProfitBlanceTemp),直接访问相应的临时表可以取得相应的数据。
详细示例如下:
//如果需要包含未过账凭证 If(IsIncloudUnPostedVoucher) { //实例化虚拟过账参数类 VoucherPostParameters postParam = new VoucherPostParameters(); //给各参数赋值 postParam.PostType = GlVoucherPostType.PeriodScope; postParam.BookId = iAcctBookId; postParam.CurrencyId = iCurrencyID; postParam.BegingYear = iStartYear; postParam.BegingPeriod = iStartPeriod; postParam.EndYear = iEndYear; postParam.EndPeriod = iEndPeriod; postParam.LstAccountIds = lstAccountId; postParam.IsContainDetailId = ShowDetailItem; //包含数量 postParam.IsNoContainQty=false; //包含调整期 postParam.IsContainAdjustPeriod = true; //包含损益数据 postParam.IsNoContainProfit = false; //其它参数根据实际需要使用… //虚拟过账获取数据临时表 VirtualPostTemps virtualPostTemps = VoucherVirPostService.GetVoucherVirPostBalance(ctx, postParam); var strBalanceTable = virtualPostTemps.BalanceTemp; var strQtyBalanceTable = virtualPostTemps.QtyBalanceTemp; var strProfitBalanceTable = virtualPostTemps.ProfitBalanceTemp; }
关于虚拟过账参数类VoucherPostParameters的具体参数及说明,可以在开发调用时用“.”号实时取得。如下图所示:
注:
1,得到的三张临时表的表结构和实际对应的物理余额表结构一致。
2,需要强调的是:虚拟过账涉及数据量和计算量较大,对系统性能影响较大,如果账簿存在未过账的历史调整期凭证或单个期间数据量较大,极端情况下可能造成数据库表空间不够,甚至服务器内存用尽,最后服务器崩溃的严重后果,因此,请谨慎使用虚拟过账方法。
3,虚拟过账方法生成三张临时表,二开一定要记得,在使用完后及时删除,否则不断积累可能造成数据库膨胀,临时表泛滥,影响系统性能。
4,虚拟过账参数详细说明,请参见:总账凭证虚拟过账参数说明 (kingdee.com)
PS:当明确需要包含未过账凭证时,必须调用上面的虚拟过账方法,从生成的临时表中取余额数据,注意,临时表使用完后应该尽快删除。同时,根据是否需要包含调整期数据,指定参数IsContainAdjustPeriod的值,此时,虚拟过账内部会自动处理调整期问题。如果不需要包含未过账凭证,则不建议调用上面的虚拟过账方法,而是应该参考第一条,直接从物理表中取数,同时,根据是否需要包含调整期数据,调用GetBalanceTableName()方法获取正确的物理表表名。
三,通过WEB API方式取数
前面介绍的方法是通过二开插件的方式,调用系统方法获取科目余额数据,这种方式有一定局限性,比如,只能用.Net进行二开,需要挂载插件等,这对于公有云用户来说,不大方便,代价有点高。目前,星空系统从2021年6月的版本开始,已支持通过WEB API方式查询现有账表的数据,当然也包含取科目余额表的数据啦。
具体如何通过WEB API方式调用星空API接口,可以参见open.kingdee.com网站,这里有详尽的指导文档和示例。本文仅就取科目余额数据相关的知识点加以解释。
{ FieldKeys:"" //需要查询的字段名集合,字符串类型,格式:"key1,key2,...",指定待查字段时,须确保当前查询条件的结果集中包含待查字段,由于账表最终展示列采用动态生成技术,因此,此处可用的账表字段名由最终账表对应的后台临时表中的字段决定。 IsVerifyBaseDataField:"true" StartRow:0 //开始行号,用于分页取数,对于数据量大时,建议分页取数 Limit:2000 //一定要限定输出行数,否则可能因数据量过大而导致超时,甚至服务器瘫痪。 SchemeId:"" //当指定方案ID时,就是按方案查询,就可以不再指定后面的具体参数了。 Model:{ FACCTBOOKID:{ FNumber:"" } FCURRENCY:"" FSTARTYEAR:"" FSTARTPERIOD:"" FENDYEAR:"" FENDPERIOD:"" FSTARTBALANCE:{ FNumber:"" } FENDBALANCE:{ FNumber:"" } FBALANCELEVEL:"" … } }
注:Model中各字段出现的顺序至关重要,它决定了系统处理这些参数的顺序,不同的顺序可能导致意外的结果,因此,务必按上面示例中的顺序生成请求json串。一个可以参考的原则是:json中字段的顺序保持和系统中对应功能界面上手工指定字段值的顺序一致。
推荐阅读