【Python插件入门】第8篇:账表表单插件原创
金蝶云社区-CQ周玉立
CQ周玉立
173人赞赏了该文章 1.3万次浏览 未经作者许可,禁止转载编辑于2022年08月18日 18:36:06
summary-icon摘要由AI智能服务提供

本文是对“Python插件入门”系列中的一篇关于“简单账表服务插件”的扩展,主要介绍了账表表单插件的概念、应用场景、新建方法及常用事件。账表表单插件通过继承AbstractDynamicFormPlugIn基类实现,用于丰富报表界面功能,如设置数据颜色、修改报表单元格数据、单据关联查询等。文中提供了账表表单插件的详细开发步骤和代码示例,包括初始化、加载、数据绑定、按钮点击等事件的处理方法,展示了如何通过Python代码对报表进行自定义和扩展。

往期回顾:

【Python插件入门】第1篇:Python插件入门讲解

【Python插件入门】第2篇:基本开发过程介绍

【Python插件入门】第3篇:插件中如何进行数据操作

【Python插件入门】第4篇:单据表单插件

【Python插件入门】第5篇:单据列表插件

【Python插件入门】第6篇:操作服务插件

【Python插件入门】第7篇:简单账表服务插件


    接上一篇,简单账表服务插件主要是完成了报表查询数据的构建,已经完成了简单账表查询功能的开发,那么对于查询界面在做一些"锦上添花"的功能,会让报表功能更加丰富,或者基于报表查询结果,再做一些单据联查、穿透查询等功能,可以通过账表表单插件来完成。

一、账表表单插件简介

    C#开发时,账表表单插件的基类是AbstractSysReportPlugIn与单据的表单插件基类不同,C#开始时要注意一下!Python插件开发的话,了解就行了,他也是AbstractDynamicFormPlugIn的派生类,和单据表单插件算是"兄弟"关系。账表表单插件是依赖于账表界面触发的,也属于界面类插件,既然都是继承于AbstractDynamicFormPlugIn,所以很多表单插件中的事件方法也是可以使用的。

    账表表单插件中的一些重要属性和成员这里就不单独介绍了,下面的常用事件讲解中会做介绍,继续往下看!

  • 账表表单插件常见应用场景

    ①账表查询界面设置数据颜色。

    ②修改报表单元格数据:转换百分数、千分号分隔符、修改底部合计结算逻辑等。

    ③单据关联查询。

    ④报表穿透查询,关联弹出其他账表。

    ⑤关闭表头排序功能

    ⑥报表表头字段赋值

    ⑦...

二、新建一个账表表单插件

  • 注意:这里提供一个引用比较全的账表表单插件示例模板,在附件中下载示例代码,复制到BOS里面注册!

  • Python账表表单插件注册方法:如下图所示,以上一篇测试示例报表为例,其他账表类似。

image.png


三、账表表单插件常用事件介绍

    这里做了表单插件的示例,对报表界面做了一些丰富,测试效果图如下:

    image.png

  • 下面看下账表表单插件中常用事件介绍:

#初始化
def OnInitialize(e):
    openPara=this.View.OpenParameter;#获取打开报表时传入的参数
    myPara=openPara.GetCustomParameter("参数标识");#根据参数标识获取某个打开参数
    if(myPara<>None):#若参数不为空
        myParaStr=("{0}").format(myPara);#将参数转换为字符串
        #将参数传递给过滤框,可在过滤框注册表单插件获取此参数
        param=SysReportShowParameter();
        param.CustomParams.Add("参数标识",myParaStr);
#账表页面加载完毕
def OnLoad(e):
    return;#这里示例不执行后面的代码
    #若报表没有显示表头字段,可通过如下代码隐藏表头部分,以免显示一块空白区域,影响用户体验
    sp=this.View.GetControl[SplitContainer]("FSpliteContainer");
    sp.HideFirstPanel(True);#折叠分割容器上面部分

#报表页面数据加载完毕
def AfterBindData(e):
    listGrid=this.View.GetControl("FList");
    listGrid.SetCustomPropertyValue("AllowSorting"False);#关闭表头的排序功能
    reportModel=this.Model;#SysReportModel类型,报表数据模型
    billObj=reportModel.DataObject;#报表页面实体数据包
    reportView=this.View;#SysReportView类型,报表界面View
    titles=reportModel.ReportTitles;#获取账表服务插件中构建的报表表头字段集
    msg="";
    for title in titles:
        fldKey=title.TitleKey;#表头字段标识
        fldValue=title.TitleValue;#表头字段值
        fldCtl=reportView.GetControl(title.TitleKey);#获取表头字段控件
        #fldCtl.Enabled=True;#默认是锁定的,可通过此代码放开表头字段,允许编辑
        #fldCtl.Visible=False;#隐藏表头字段
    customFilterObj=reportModel.FilterParameter.CustomFilter;#报表过滤框快捷过滤实体数据包
    orgObj=customFilterObj["F_BPW_OrgId"];#获取组织过滤字段
    orgId=orgObj["Id"if(orgObj<>Noneelse "0";#获取组织Id
    this.Model.SetItemValueByID("F_BPW_OrgId",orgId,0);#给表头组织字段赋值成基础资料
    #this.View.ShowMessage(msg);

#按钮点击事件
def ButtonClick(e):
    key=e.Key.ToUpperInvariant();#按钮标识大写
    if(key=="F_BPW_TestBtn".ToUpperInvariant()):
        this.Model.SetItemValueByID("F_BPW_OrgId",0,0);
        reportModel=this.Model;#SysReportModel类型,报表数据模型
        customFilterObj=reportModel.FilterParameter.CustomFilter;#报表过滤框快捷过滤实体数据包
        customFilterObj["F_BPW_OrgId"]=None;#清空过滤数据包中的组织字段
        customFilterObj["F_BPW_OrgId_Id"]=0;
        this.View.Refresh();#清空组织后刷新,获取所有组织数据
        
#表头菜单点击事件
def BarItemClick(e):
    key=e.BarItemKey.ToUpperInvariant();#菜单标识大写
    if(key=="F_BPW_MyBtn".ToUpperInvariant()):
        reportModel=this.Model;#SysReportModel类型,报表数据模型
        rowCount=reportModel.GetRowCount();#报表数据总行数
        tab=reportModel.DataSource;#账表数据源DataTable,报表所有行数据
        x=rowCount;
        mytab=reportModel.GetData(0,x);#获取报表0-x行数据,返回DataTable对象
        tempTabName=tab.TableName;#账表临时表名称,每一次查询报表都会不一样
        msg=("表头菜单{0}点击啦!").format(key);
        this.View.ShowMessage(msg);

#格式化行数据,每一行会运行一次 
#在此事件中可以设置报表数据的颜色
def OnFormatRowConditions(args):
    if(args.DataRow.ColumnContains("orgName")==True):#根据字段标识判断是否显示了该字段
        ss= ("{0}").format(args.DataRow["orgName"]);    #获取字段值,这里是取组织名称
        if("蓝海" in ss):#组织名称包含"蓝海"
            fc=FormatCondition();
            fc.BackColor="#ccffff";#背景色
            fc.ForeColor = "#FF0000";#前景色
            #fc.ColorField = "orgName";#颜色字段
            #fc.ApplayRow = False;#适用整行,默认值为True,设置ColorField时,才会单独对字段设置颜色,否则应用整行
            args.FormatConditions.Add(fc);
    reportModel=this.Model;
    tab=reportModel.DataSource;
    allFlds=tab.Columns;#报表所有字段
    #循环对动态列进行判断,数量不为0显示颜色
    for fld in allFlds:
        fldKey=fld.ColumnName;
        if("_" not in fldKey or fldKey.StartsWith("F")==False):#非数量动态列,不做处理
            continue;#自定义的动态列名规则,我示例报表动态数量列名是F开头且包含下划线,其他字段均不满足此条件
        if(args.DataRow.ColumnContains(fldKey)==True):
            qty= float(args.DataRow[fldKey]);
            if(qty<>0):
                fc=FormatCondition();
                fc.BackColor="#CCCCCC";#背景色
                fc.ForeColor ="#FF0000";#前景色
                fc.ColorField = fldKey;#颜色字段
                fc.ApplayRow = False;
                args.FormatConditions.Add(fc);

#去除尾0,自定义方法供参考
def remove_exponent(i):
    t=str(i);
    return t.rstrip('0').strip('.'if '.' in t else t;
#单元数据格式化
#在这个事件里面可以对报表原输出的单元格内容做修改
def FormatCellValue(args):
    fldkey=args.Header.Key;#字段标识
    if(fldkey=="F2018_1_4" ):
        dr=args.DataRow;#获取当前行的数据
        valueStr= ("{0}").format(args.FormateValue);#获取该字段原输出值
        args.FormateValue=("{0}%").format(round(float(valueStr)*100,2));#转换成百分数
    elif(fldkey=="orgName"):
        dr=args.DataRow;#获取当前行的数据
        valueStr= ("{0}").format(args.FormateValue);#获取该字段原输出值
        args.FormateValue=valueStr.Replace("蓝海","***");#将组织名称中的"蓝海"替换成***
    elif("_" in fldkey and fldkey.StartsWith("F")==True):
        args.FormateValue=remove_exponent(args.FormateValue);#去除尾0
        #oldValue=Decimal.Parse(args.FormateValue);#转换成Decimal
        #args.FormateValue =oldValue.ToString("N");#设置千分位分隔符
    cellTye=int(args.CellType);#单元格类型,0:普通,1:合计,2:小计
    if(cellTye==1 and fldkey=="F2018_1_6"):#判断底部合计行,可对底部合计行做自定义计算修改
        #这里演示将F2018_1_6底部合计修改成:F2018_1_4+F2018_1_5
        newSumValue=float(args.DataRow["F2018_1_4"])+float(args.DataRow["F2018_1_5"]);
        args.FormateValue=("{0}").format(newSumValue);

#单元格超链接点击事件
def EntryButtonCellClick(e):
    row=e.Row;#点击超链接所在序号,从1开始
    fldKey=e.FieldKey.ToUpperInvariant();#点击单元格字段标识大写
    msg=("点击了第{0}行的[{1}]").format(row,fldKey);
    this.View.ShowMessage(msg);
    #e.Cancel=True;#取消点击事件
    #获取当前单元格的值
    reportModel=this.Model;
    tab=reportModel.DataSource;
    value=("{0}").format(tab.Rows[row-1][e.FieldKey]);

#单元格双击事件
#简单账表 表单不会触发EntityRowDoubleClick事件,用此事件代替
def CellDbClick(Args):
    #Args.Cancel=True;#取消事件,若二开标准报表,可以此取消标准功能自带的双击事件
    row=Args.CellRowIndex;#双击序号,从1开始
    fldKey=Args.Header.FieldName;#双击单元格的字段名
    #获取当前单元格的值
    reportModel=this.Model;
    tab=reportModel.DataSource;
    value=("{0}").format(tab.Rows[row-1][fldKey]);#也可以传其他字段名,即可获取其他字段值
    msg=("点击了第{0}行的[{1}],{1}值={2}").format(row,fldKey,value);
    this.View.ShowMessage(msg);

#行点击事件
def EntityRowClick(e):
    row=e.Row;#点击的行序号,从1开始
    #msg=("点击了第{0}行!").format(row);
    #this.View.ShowMessage(msg);
    reportView=this.View;
    selectedDataRows=reportView.SelectedDataRows;#获取选中行,若启用了允许多选,则可获取到所有选中行
    if(selectedDataRows==None or selectedDataRows.Length==0):#无选中行数据
        return;
    #下面实现选中行合计功能
    dt=selectedDataRows[0].Table;
    allFlds=dt.Columns;#报表所有字段
    jsonArr=JSONArray();
    DIC={};
    DIC["F2018_1_4"]="2018-1-4";#添加需要合计的字段标识和字段标题的字典
    DIC["F2018_1_5"]="2018-1-5";
    for fldKey in DIC.keys():
        columnIndex=allFlds.IndexOf(fldKey);
        sumValue=0;
        for selectRow in selectedDataRows:
            fldValue=float(selectRow.ItemArray[columnIndex]);#取出选中行对应字段的值
            sumValue=sumValue+fldValue;
        jsonObj=JSONObject();
        jsonObj.Put("Value",remove_exponent(sumValue));
        jsonObj.Put("Caption",("{0}:").format(DIC[fldKey]));
        jsonArr.Add(jsonObj);
    listGrid=this.View.GetControl("FList");
    listGrid.SetSelectRowsTips(jsonArr);#输出到前端,按下alt键并把鼠标放到选中行的区域,即可看到效果

四、经典实践案例参考

    有了账表表单插件确实可以丰富很多功能,以下是整理的各位大佬分享的一些账表表单插件的常用案例。

    大多是C#插件示例,但是结合上面常用事件介绍中的Python示例,使用Python插件实现也不是难事。


==========================本篇正文结束=====================================

用2篇文章把Python账表开发的核心介绍完了,应该能满足95%以上的报表需求了。

示例代码已经上传附件,老规矩,大家按需下载!

感谢大家持续关注,点赞、评论、收藏,您的点赞、评论就是我前进的动力。


下一篇:【Python插件入门】第9篇-单据转换插件

发布于 金蝶云星空BOS开发交流圈 社群

图标赞 173
173人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
1人打赏
还没有人打赏,快来当第一个打赏的人吧!