zoukankan      html  css  js  c++  java
  • [Axapta]带参数的RunbaseReport最佳实践

    AX中RunbaseReport类用来运行一个报表,它可以定义一些参数,在弹出对话框的时候设置这些参数,以列出工单为例,先看看不考虑从其他form点击纪录带入参数的时候如何实现这个报表。下图是所用到的几个对象:

    菜单项TestProdReport指向类TestProdReport,下面是类TestProdReport的代码:

    class TestProdReport extends RunbaseReport
    {
        NoYesId     showOnlyOpen;
        DialogField dfShowOnlyOpen;
    
        #define.CurrentVersion(0)
        #localmacro.CurrentList
            showOnlyOpen
        #endmacro
    }
    
    static void main(Args args)
    {
        TestProdReport prodReport = new TestProdReport();
        ;
    
        if (prodReport.prompt())
            prodReport.run();
    }
    
    public identifiername lastValueElementName()
    {
        return reportStr(TestProdReport);
    }
    
    public NoYes parmShowOnlyOpen(NoYes _showOnlyOpen = showOnlyOpen)
    {
        showOnlyOpen = _showOnlyOpen;
    
        return showOnlyOpen;
    }
    
    public Object dialog(DialogRunbase dialog, boolean forceOnClient)
    {
        DialogRunbase   ret;
        ;
    
        ret = super(dialog, forceOnClient);
        dfshowOnlyOpen = ret.addFieldValue(typeid(NoYesId),showOnlyOpen,"Show only open orders");
    
        return ret;
    }
    
    public boolean getFromDialog()
    {
        boolean ret;
    
        ret = super();
    
        showOnlyOpen = dfShowOnlyOpen.value();
    
        return ret;
    }
    
    public container pack()
    {
        return [#CurrentVersion, #CurrentList] + [super()];
    }
    
    public boolean unpack(container packedClass)
    {
        container       base;
        boolean         ret;
        Integer         version    = RunBase::getVersion(packedClass);
        boolean         dummy;
    
        switch (version)
        {
            case #CurrentVersion:
                [version, #CurrentList, base] = packedClass;
                ret = super(base);
                break;
            default:
                ret = false;
        }
    
        return ret;
    }

    报表TestProdReport的代码:

    public class ReportRun extends ObjectRun
    {
        TestProdReport  testProdReport;
    }
    
    public void init()
    {
        ;
    
        testProdReport = this.args().caller();
    
        super();
    
    
    }
    
    public boolean send(Common _cursor, int _level=1, boolean _triggerOffBody=TRUE, boolean _newPageBeforeBody=FALSE)
    {
        boolean     ret;
        ProdTable   _prodTable;
        ;
    
        if(_cursor.TableId==tablenum(ProdTable))
        {
            _prodTable = _cursor;
            if(testProdReport.parmShowOnlyOpen() && _prodTable.ProdStatus==ProdStatus::Completed)
                return true;
        }
    
        ret = super(_cursor, _level, _triggerOffBody, _newPageBeforeBody);
    
        return ret;
    }

    这里我们是在报表的Send函数判断工单状态根据条件过滤掉已关闭的工单,这不是最好的办法,因为Query仍会查询出所有的工单纪录,在一定程度上影响性能,更好的办法是重载fetch方法,在fetch方法中获取报表的query,在query中根据条件加入对ProdStatus的过滤条件,再由Query创建QueryRun,运行QueryRun获取ProdTable纪录Send,这里就不再演示了。

    现在的问题是如果把TestProdReport菜单项添加到ProdTable form中,在ProdTable form上点击这个菜单只显示当前ProdTable纪录到报表该如何来做呢?

    首先在TestProdReport类定义中添加变量来纪录form中的当前纪录:

    ProdTable   prodTable;

    添加parmXXX函数来传入这条ProdTable纪录:

    public ProdTable parmProdTable(ProdTable _prodTable = prodTable)
    {
        ;
        prodTable = _prodTable;
    
        return prodTable;
    }

    添加函数initFromArgs来从传入的Args初始化这条纪录:

    private void initFromArgs(Args args)
    {
        ;
        if ( args && args.dataset())
        {
            switch(args.dataset())
            {
                case(tablenum(ProdTable)) :
                    this.parmProdTable(args.record());
                    break;
                default:
    
             }
            this.makeReportRun(); //创建ReportRun对象
            this.initQueryRun();  //初始化Report的QueryRun,必须是手工调用,正常运行报表是不会调用这个函数的,它调用后面的initQuery
        }
    }

    添加initQuery函数来初始化Query,initQuery函数会被initQueryRun()调用,在这里我们根据传入的ProdTable纪录根据主键工单号ProdId来过滤:

    public Query initQuery()
    {
        QueryBuildDataSource    queryBuildDataSource;
        QueryBuildRange         queryBuildRange;
        Query                   query;
        ;
        query = super();
    
        queryBuildDataSource = query.dataSourceTable(tablenum(ProdTable));
        if (!queryBuildDataSource)
            queryBuildDataSource = query.addDataSource(Tablenum(ProdTable));
    
        queryBuildRange = queryBuildDataSource.findRange(fieldnum(ProdTable, ProdId));
        if (!queryBuildRange)
            queryBuildRange = queryBuildDataSource.addRange(fieldnum(ProdTable, ProdId));
    
        if (prodTable)
            queryBuildRange.value(prodTable.ProdId);//根据工单号来筛选
    
        return query;
    }

    最后修改main函数,调用initFromArgs来初始化就可以了:

    static void main(Args args)
    {
        TestProdReport prodReport = new TestProdReport();
        ;
        prodReport.getLast();
        prodReport.initFromArgs(args);
        if (prodReport.prompt())
            prodReport.run();
    }

    注意这里在调用initFromArgs函数之前调用了一次getLast(),如果不在这里调用一次getLast(),后面的prompt()会在内部调用一次getLast(),把上一次pack的query读入,显示出来的对话框中看到的是上一次的内容,也就把initFromArgs()创建的Query的给覆盖了,所以这里先调用一次getLast(),prompt()会看到这个函数已经调用过了就不再调用了,所以这行是必须的。当前纪录的工单号相应的会出现在对话框中的过滤选项内:

    以上就是如何在报表中根据form的当前纪录来过滤的实现办法。这里还要说一个runbaseReport的initParmDefault()函数,它是在第一次运行报表时会被调用,一旦有pack/unpack成功之后就不会在调用,在这里可以针对报表的第一次运行做一些初始化的工作,针对我们的这个报表是不需要的。

    再把我们的这个例子扩展开,如果说在ProdTable form中选中了多条纪录,要在报表上打印出这多条纪录又该怎么办呢?

    我们调用传入纪录的isFormDataSource()来判断是否来自于form的DataSource,如果是则使用common.Datasource()方法获得formDataSource,再使用formDatasource.getFirst(true)、formDatasource.getNext()轮询获取选中纪录的主键,然后设置到Query的Range中就可以了。基本结构是一样的,这里就不再演示了,下面的链接可以下载这个演示的project,从AXAPTA 3.0系统导出:https://files.cnblogs.com/duanshuiliu/TestProdReport.zip

  • 相关阅读:
    [SDOI2015]约数个数和
    [POI2007]ZAP-Queries
    fpu栈溢出
    shader 汇编
    sample a texture as a rendertarget
    ID3d11asynchronous
    DEVICE DRAW VERTEX BUFFER TOO SMALL
    模型的一个点显示在原点
    setrendertraget 上下颠倒
    skinned mesh 蜘蛛样
  • 原文地址:https://www.cnblogs.com/duanshuiliu/p/2586051.html
Copyright © 2011-2022 走看看