182 lines
8.8 KiB
Python
182 lines
8.8 KiB
Python
import clr
|
||
clr.AddReference("System")
|
||
clr.AddReference("Kingdee.BOS")
|
||
clr.AddReference("Kingdee.BOS.Core")
|
||
clr.AddReference("Kingdee.BOS.DataEntity")
|
||
clr.AddReference("Kingdee.BOS.App")
|
||
clr.AddReference("Kingdee.BOS.Contracts")
|
||
clr.AddReference("Kingdee.BOS.ServiceHelper")
|
||
from Kingdee.BOS import*
|
||
from Kingdee.BOS.Contracts import*
|
||
from Kingdee.BOS.Contracts.Report import*
|
||
from Kingdee.BOS.Core import *
|
||
from Kingdee.BOS.Core.Metadata import *
|
||
from Kingdee.BOS.Core.Report import*
|
||
from Kingdee.BOS.Core.SqlBuilder import*
|
||
from Kingdee.BOS.Core.Enums import *
|
||
from Kingdee.BOS.App.Data import*
|
||
from Kingdee.BOS.Orm.DataEntity import*
|
||
from System import*
|
||
from System.ComponentModel import*
|
||
from System.Collections.Generic import*
|
||
from System.Text import*
|
||
from System.Threading.Tasks import*
|
||
from Kingdee.BOS.ServiceHelper import *
|
||
#初始化,在此事件中设置报表的属性全局参数
|
||
def Initialize():
|
||
this.ReportProperty.ReportType=ReportType.REPORTTYPE_NORMAL;
|
||
this.IsCreateTempTableByPlugin=True;
|
||
#是否支持分组汇总,在后面GetSummaryColumnInfo方法中添加汇总字段,
|
||
#要在BOS中过滤框的汇总页签配置汇总信息,可参考:简单账表分组汇总设置
|
||
this.ReportProperty.IsGroupSummary=True;
|
||
#IsUIDesignerColumns=False,表示报表的列通过插件控制,后续在GetReportHeaders中构建列头
|
||
#需要在BOS过滤框的显示隐藏列中维护,字段标识与临时表字段保持一致
|
||
#账表列头构建更多详细说明参考:账表列构建
|
||
this.ReportProperty.IsUIDesignerColumns=False;
|
||
|
||
#创建临时报表,正式进入账表取数sql拼接并取数,把账表取数结果放到创建的临时表中
|
||
#如果参数(this.IsCreateTempTableByPlugin=True),即调用BuilderReportSqlAndTempTable构建临时表
|
||
#否则调用以下3个接口,完成账表取数逻辑的sql指令即:BuilderSelectFieldSQL、BuilderTempTableOrderBySQL、BuilderFormWhereSQL
|
||
#rptfilter:账表参数,可以从这里获取过滤条件等
|
||
#tableName:系统自动创建的账表临时表名,具备唯一性,最终报表页面展示的数据绑定此临时表,所以最终的报表结果数据要写入此临时表中
|
||
def BuilderReportSqlAndTempTable(rptfilter,tableName):
|
||
#baseDataTemp=filter.BaseDataTempTable;#基础资料临时表;若设置了数据范围权限,该表会把根据数据范围过滤出来的内码存入临时表;
|
||
#循环获取所有基础资料数据范围的数据,可用来拼接到报表SQL里面实现数据权限过滤
|
||
#for b in baseDataTemp:
|
||
# baseType=b.BaseDataFormId;#基础资料FormId
|
||
# PKFldName=b.PKFieldName;#临时表中基础资料主键字段名,例如,FORGID
|
||
# baseTempTab=b.TempTable;#基础资料数据范围临时表名
|
||
#filterStr=filter.FilterParameter.FilterString;#过滤框条件页签过滤表达式
|
||
#过滤框快捷过滤页签的实体数据包,从这里面获取自定义的过滤字段值
|
||
#DynamicObject类型,用前面讲的实体数据包操作方式取值,用绑定实体属性标识
|
||
custFilter = rptfilter.FilterParameter.CustomFilter;
|
||
if(custFilter==None):
|
||
return;
|
||
orgObj=custFilter["F_BPW_OrgId"];#获取组织
|
||
whereOrgs="";
|
||
if(orgObj != None):
|
||
orgId=("{0}").format(orgObj["Id"]);#组织ID
|
||
whereOrgs=(" and a.FPURCHASEORGID in ({0}) ").format(orgId);#选择了组织,拼接组织过滤
|
||
materials=custFilter["F_BPW_Materials"];#物料多选过滤
|
||
matList=List[str]();
|
||
if(materials != None):
|
||
for m in materials:
|
||
materialNum="'"+str(m["F_BPW_Materials"]["Number"])+"'";#取出过滤框选择的多个物料编码
|
||
matList.Add(materialNum);
|
||
whereMat=(" and m.FNumber in ({0})").format(str.Join(",",matList)) if(matList.Count>0) else "";#拼接物料多选过滤
|
||
beginDate=str(custFilter["F_BPW_BeginDate"]);#获取开始日期
|
||
EndDate=str(custFilter["F_BPW_EndDate"]);#获取结束日期
|
||
beginDate=str(DateTime.Parse(("{0}").format(beginDate)).AddDays(-1));#开始日期的前一天
|
||
itemDate=beginDate;
|
||
fldsSql=List[str]();#动态列头SQL,相当于Select后面的部分字段是动态拼接的,以此来实现动态列
|
||
#从开始日期起,循环加1天,一直到结束日期,过滤界面要控制录入的开始日期必须<结束日期,在过滤界面注册表单插件即可实现
|
||
while(itemDate != EndDate):
|
||
myDate=DateTime.Parse(("{0}").format(itemDate));
|
||
fldKey=("F{0}_{1}_{2}").format(myDate.Year,myDate.Month,myDate.Day);#根据每个日期构建唯一的列名
|
||
ss=("{0}=SUM(Case when a.FDATE='{1}' then b.FQty else 0 end)").format(fldKey,myDate);#构建每天订单数量合计SQL
|
||
fldsSql.Add(ss);#将SQL添加到动态列SQL集合中备用
|
||
nextDate=myDate.AddDays(1);
|
||
itemDate=str(nextDate);#迭代+1天
|
||
myDate=DateTime.Parse(("{0}").format(itemDate));#这里是选择的截止日期,由于循环到最后一天跳出了,这里补充一天的数据
|
||
fldKey=("F{0}_{1}_{2}").format(myDate.Year,myDate.Month,myDate.Day);
|
||
ss=("{0}=SUM(Case when a.FDATE='{1}' then b.FQty else 0 end)").format(fldKey,myDate);
|
||
fldsSql.Add(ss);#将SQL添加到动态列SQL集合中备用
|
||
#raise Exception(str.Join(',',fldsSql));#调试时,可用此行代码,看看构建的动态列SQL对不对
|
||
#组装最终写入报表临时表的SQL
|
||
#注意!!!: 最终临时表一定要有FIDENTITYID ,要从1开始,且不重复 ,不断号,不然前台显示空白!!!!
|
||
sql=("""/*dialect*/?select row_Number() Over(order by a.orgName,a.MaterialNum) FIDENTITYID, a.*
|
||
into {0}
|
||
from
|
||
(select orgL.FNAME orgName,m.FNUMBER MaterialNum,mL.FNAME materialName,mL.FSPECIFICATION SpecNum,unitL.FNAME unit,
|
||
{1}
|
||
from t_PUR_POOrder a
|
||
inner join T_ORG_ORGANIZATIONS org on org.FORGID=a.FPURCHASEORGID
|
||
inner join T_ORG_ORGANIZATIONS_L orgL on orgL.FORGID=org.FORGID and orgL.FLOCALEID=2052
|
||
inner join t_PUR_POOrderEntry b on a.FID=b.FID
|
||
inner join T_BD_MATERIAL m on m.FMATERIALID=b.FMATERIALID
|
||
inner join T_BD_MATERIAL_L mL on mL.FMATERIALID=m.FMATERIALID and mL.FLOCALEID=2052
|
||
inner Join T_BD_UNIT_L unitL on unitL.FUNITID=b.FUNITID and unitL.FLOCALEID=2052
|
||
where a.FDATE>='{3}' and a.FDATE<='{4}' {2} {5}
|
||
group by orgL.FNAME,m.FNUMBER,mL.FNAME,mL.FSPECIFICATION,unitL.FNAME
|
||
) a
|
||
""").format(tableName,str.Join(',',fldsSql),whereOrgs,beginDate,EndDate,whereMat);
|
||
#raise Exception(sql);#可以通过此方法弹出Sql语句进行调试验证
|
||
DBUtils.Execute(this.Context,sql);#执行SQL,将报表数据写入临时表
|
||
|
||
#构建账表列头
|
||
def GetReportHeaders(Filter):
|
||
header=ReportHeader();
|
||
localEid=this.Context.UserLocale.LCID;#获取当前语言环境代码,中文为2052
|
||
header.AddChild("orgName",LocaleValue("采购组织",localEid));#字段名,列头标题,字段名与临时表中的字段名保持对应,相当于每一个列头对应临时表的哪个字段
|
||
header.AddChild("MaterialNum",LocaleValue("物料编码",localEid));
|
||
header.AddChild("materialName",LocaleValue("物料名称",localEid));
|
||
header.AddChild("SpecNum",LocaleValue("规格型号",localEid));
|
||
header.AddChild("unit",LocaleValue("采购单位",localEid));
|
||
|
||
#下面根据过滤条件选择的日期区间,动态构建列头,和上面构建SQL字段的逻辑类似
|
||
custFilter = Filter.FilterParameter.CustomFilter;
|
||
beginDate=str(custFilter["F_BPW_BeginDate"]);#获取开始日期
|
||
EndDate=str(custFilter["F_BPW_EndDate"]);#获取结束日期
|
||
itemDate=beginDate;
|
||
fldsSql=List[str]();
|
||
while(itemDate != EndDate):
|
||
myDate=DateTime.Parse(("{0}").format(itemDate));
|
||
fldKey=("F{0}_{1}_{2}").format(myDate.Year,myDate.Month,myDate.Day);#这里的字段名要和前面构建的SQL字段对应
|
||
header.AddChild(fldKey,LocaleValue(str(("{0}-{1}-{2}").format(myDate.Year,myDate.Month,myDate.Day)),localEid),SqlStorageType.SqlDecimal);
|
||
nextDate=myDate.AddDays(1);
|
||
itemDate=str(nextDate);
|
||
myDate=DateTime.Parse(("{0}").format(itemDate));
|
||
fldKey=("F{0}_{1}_{2}").format(myDate.Year,myDate.Month,myDate.Day);#这里的字段名要和前面构建的SQL字段对应
|
||
header.AddChild(fldKey,LocaleValue(str(("{0}-{1}-{2}").format(myDate.Year,myDate.Month,myDate.Day)),localEid),SqlStorageType.SqlDecimal);
|
||
#设置列的索引,使其可以按照以上列头构建的顺序显示
|
||
colIndex=0;
|
||
for child in header.GetChilds():
|
||
if(child.GetChildCount()==0):
|
||
child.ColIndex=colIndex;
|
||
colIndex=colIndex+1;
|
||
else:
|
||
child.ColIndex = colIndex;
|
||
colIndex=colIndex+1;
|
||
for childHeader in child.GetChilds():
|
||
childHeader.ColIndex=colIndex;
|
||
colIndex=colIndex+1;
|
||
return header;
|
||
|
||
#设置报表表头字段值
|
||
#这里主要是把过滤框设置的字段值,显示到报表表头
|
||
def GetReportTitles(Filter):
|
||
reportTitles=ReportTitles();
|
||
custFilter=Filter.FilterParameter.CustomFilter;#获取过滤框的数据包
|
||
orgObj=custFilter["F_BPW_OrgId"];#获取组织
|
||
beginDate=str(custFilter["F_BPW_BeginDate"]);#获取开始日期
|
||
EndDate=str(custFilter["F_BPW_EndDate"]);#获取结束日期
|
||
if(orgObj != None):
|
||
reportTitles.AddTitle("F_BPW_OrgId", orgObj["Name"]);
|
||
reportTitles.AddTitle("F_BPW_BeginDate", beginDate);
|
||
reportTitles.AddTitle("F_BPW_EndDate", EndDate);
|
||
return reportTitles;
|
||
|
||
#设置报表底部合计列
|
||
def GetSummaryColumnInfo(rptfilter):
|
||
result=List[SummaryField]();
|
||
#由于这里的数量字段是动态构建的,所以也需要动态添加合计列,字段名与前面保持一致
|
||
custFilter = rptfilter.FilterParameter.CustomFilter;
|
||
beginDate=str(custFilter["F_BPW_BeginDate"]);#获取开始日期
|
||
EndDate=str(custFilter["F_BPW_EndDate"]);#获取结束日期
|
||
itemDate=beginDate;
|
||
fldsSql=List[str]();
|
||
while(itemDate != EndDate):
|
||
myDate=DateTime.Parse(("{0}").format(itemDate));
|
||
fldKey=("F{0}_{1}_{2}").format(myDate.Year,myDate.Month,myDate.Day);#这里的字段名要和前面构建的SQL字段对应
|
||
result.Add(SummaryField(fldKey,BOSEnums.Enu_SummaryType.SUM));
|
||
nextDate=myDate.AddDays(1);
|
||
itemDate=str(nextDate);
|
||
myDate=DateTime.Parse(("{0}").format(itemDate));
|
||
fldKey=("F{0}_{1}_{2}").format(myDate.Year,myDate.Month,myDate.Day);
|
||
result.Add(SummaryField(fldKey,BOSEnums.Enu_SummaryType.SUM));
|
||
return result;
|
||
|
||
#报表关闭触发,通常在此处清理报表过程产生的临时表
|
||
def CloseReport():
|
||
this.DropTempTable();
|