传递对象: Form -> Class -> Report
本文试图举例,由窗体传递对象到类,再由类传递到报表,以下原码在AX4.0 sp1环境下运行通过.
通过while多次打开AOT->MenuItem->Report对象,显示多份领料单日志报表.
//Soondy @champway -Silverlit-Prodution Picking List Report (mutilple selection)
//@Form
str SelectedRecordsUnPosted()
{
    FormDataSource  ProdJTable_DS;
    ProdJournalTable _ProdJournalTable;
    str             RtnStr;
    ;
    ProdJTable_DS   = ProdJournalTable.dataSource();

    _ProdJournalTable = ProdJTable_DS.getFirst(true);

    RtnStr = '';

    if (_ProdJournalTable) //muti line
    {
        while(_ProdJournalTable)
        {
            if (_ProdJournalTable.Posted==NoYes::No)
            {
                RtnStr = RtnStr + ',' + _ProdJournalTable.JournalId ;
            }
            _ProdJournalTable = ProdJTable_DS.getNext();
        }
        RtnStr = strdel(RtnStr,1,1);

    }
    else // one line only
    {
        if (ProdJournalTable.Posted==NoYes::No)
        {
             RtnStr=ProdJournalTable.JournalId;
        }
    }

    Return RtnStr;

}

//@Classs

static void main(Args args)
{
    CHM_ProdPickList_Multi_Print    theClass;
    str                                                 str_SelectJournal="";
    ;
    theClass = new CHM_ProdPickList_Multi_Print();
    theClass.parmCallerArgs(args);
    theClass.flagInitFilterStringFirstTime();

    if (args && args.dataset())
    {
        str_SelectJournal = args.caller().SelectedRecordsUnPosted();
        if (str_SelectJournal=="")
        {
            info("Report is empty," +"@SYS77792" +"- Report");
            RETURN;
        }
    }


    if (theClass.prompt())
    {
        theClass.runReport(args);
    }
}

void initRanges()
{
    Args                                _args;
    QueryBuildDataSource   queryBuildDataSource;
    QueryBuildRange            queryBuildRangeJournal;
    str                                   _SelectJournal;
    ;
    _args = this.parmCallerArgs();
    queryBuildDataSource    = SysQuery::findOrCreateDataSource(this.queryRun().query(), tablenum(ProdJournalBOM));
    queryBuildRangeJournal  = SysQuery::findOrCreateRange(queryBuildDataSource, fieldnum(ProdJournalBOM,JournalId));

    if (_args && _args.dataset())
    {
        _SelectJournal = _args.caller().SelectedRecordsUnPosted();
        queryBuildRangeJournal.value(_SelectJournal);
    }

}


void runReport(Args _args)
{
    Query                              query = new Query();
    QueryBuildDataSource    qbds;
    QueryBuildRange             range;
    Args                                 parameters = new Args();
    MenuFunction                  ProdPickingListMenu;
    ProdJournalBom              _ProdJournalBom;
    str                                    _str_seletionJournalId;
    str                                    _Lst_seletionJournalId;
    prodJournalBOM             prodJournalBOM;
    ;

    if (_args && _args.dataset())
    {
        query = this.queryRun().query();
        qbds = query.dataSourceTable(tablenum(prodJournalBom));
        SysQuery::findOrCreateRange(qbds, fieldnum(prodJournalBom,JournalId));
        range = SysQuery::findOrCreateRange(qbds, fieldnum(prodJournalBom,JournalId));

        while (queryRun.next())
        {
               prodJournalBOM = queryRun.get(tablenum(ProdJournalBOM));
               if (prodJournalBOM.JournalId && _Lst_seletionJournalId != prodJournalBOM.JournalId)
               {
                   _str_seletionJournalId = prodJournalBOM.JournalId;
                   _Lst_seletionJournalId = _str_seletionJournalId;
                   ProdPickingListMenu = new MenuFunction(menuitemoutputstr(CHM_ProdPickList_Multi), MenuItemType::Output);
                   parameters.parmObject(reportDimParm);
                   parameters.parm(_str_seletionJournalId);

                   ProdPickingListMenu.run(parameters);

               }

        }

    }

}

//@ Report
void init()
{
    ;
    firstPage         = true;
    showDialog        = true;
    showQuery         = true;
    dialogUnpacked    = false;
    gNum              = 0;
    gLstJournalId     ="";
    gLstItemId        ="";
    gUpdatedFlag      = false;
    CHM_TMPProdPickList.setTmpData(gTMPProdPickList);

    if(!this.hasAccessProdJournalBOM())
    {
        throw error(strfmt("@SYS94257", tablestr(ProdJournalBOM)));
    }

    hasAccessInventTransferLine     = this.hasAccessInventTransferLine();
    hasAccessInventReportDimHistory = this.hasAccessInventReportDimHistory();

    companyInfo       = CompanyInfo::find();

    super();
    reportDimParm = this.args().parmObject();// soondy 20070810
   //reportDimParm = new InventReport_DimParm();
}

public boolean fetch()
{
    InventTransferLine  inventTransferLine;
    MapEnumerator       me;
    boolean             showReferenceHeader = true;
    boolean             isDeliveryNoteDesign;
    str                 _str_selectionJournal;
    //boolean             isFirst=true;
    ;

    queryRun            = new QueryRun(query);


    _str_selectionJournal = this.args().parm();
    queryRun.query().dataSourceName("ProdJournalBOM").addRange(fieldnum(ProdJournalBOM,JournalId)).value(_str_selectionJournal);//soondy 20070809

    queryRun.query().dataSourceName("ProdJournalBOM").addSortField(fieldnum(ProdJournalBOM,ItemId));

    while (queryRun.next())
    {
        if (queryRun.changed(tablenum(ProdBOM)))
        {
            prodJournalBOM = queryRun.get(tablenum(ProdJournalBOM));
            prodBOM = queryRun.get(tablenum(ProdBOM));

            if(hasAccessInventTransferLine)
            {
                select firstonly inventTransferLine
                    where   inventTransferLine.TransferId           == prodBOM.InventRefId &&
                            inventTransferLine.InventTransIdReceive == prodBOM.InventRefTransId;
            }

            isDeliveryNoteDesign = this.parmUseDeliveryLayout() && this.purchOrderId(prodJournalBOM.JournalId);

            if(!isDeliveryNoteDesign)
            {
                this.send(prodJournalBOM);
            }
            else if(!inventTransferLine.RecId)
            {
                this.send(prodJournalBOM);
            }
            else
            {
                if(hasAccessInventTransferLine)
                {
                    mapInventTransferLine.insert(inventTransferLine, prodJournalBOM.JournalId);
                }
            }
        }
    }


    // Show References section
    if(hasAccessInventTransferLine && this.design().name()=='VendorDeliveryNote')
    {
        me = mapInventTransferLine.getEnumerator();
        while (me.moveNext())
        {
            if(me.currentValue() == prodJournalId)
            {
                if(isReferencesSent && showReferenceHeader)
                {
                    headerReferences.executeSection();
                }
                inventTransferLine = me.currentKey();
                this.send(inventTransferLine);
                isReferencesSent    = true;
                showReferenceHeader = false;
            }
        }
    }

//Soondy 20070619 beg.
    if(!isDeliveryNoteDesign)
    {
        //if (gLstItemId!="" && gUpdatedFlag == True)
        if (gLstItemId!="")
        {
            gTMPProdPickList.clear();
            while select gTMPProdPickList
                  where gTMPProdPickList.ItemId == gLstItemId//ProdJournalBOM.ItemId &&
                    //  gTMPProdPickList.InventLocationId ==ProdJournalBOM.inventDim().InventLocationId
            {

                txtNumS.text("");
                txtItemId.text(gTMPProdPickList.ItemId);
                txtOldItemId.text(gTMPProdPickList.OldItemId);
                //txtItemName.text(gTMPProdPickList.ItemName);
                txtWarehouse.text(gTMPProdPickList.InventLocationId);
                txtBOMUnit.text(gTMPProdPickList.BOMUnit);
                txtInventOnHand.text(strltrim(num2str(gTMPProdPickList.inventOnHand,18,2,1,2)));
                //Dennis 2007.07.02 ====begin
                //txtPickUsageQty.text(strltrim(num2str(gTMPProdPickList.PickUsageQty,18,4,1,2)));
                //txtPickUsageQty.text("");

                totalQty = gTMPProdPickList.BOMConsump;
                //info(num2str(prodTable.QtyStUp,6,2,1,2));
                //info("StartedQty: "+num2str(startedQty,6,2,1,2));
                //info("TotalQty: " + num2str(totalQty,6,2,1,2));
                //info(int2str(numberOfLinesPerItem));
                if(startedQty != 0 && numberOfLinesPerItem >= 2)
                {
                    txtPickUsageQty.text(strltrim(num2str(totalQty/startedQty/numberOfLinesPerItem,18,4,1,2)));
                }
                else if(startedQty == 0 && numberOfLinesPerItem >= 2)
                {
                    txtPickUsageQty.text("");
                }
                else
                {
                    txtPickUsageQty.text(strltrim(num2str(gTMPProdPickList.PickUsageQty,18,4,1,2)));
                }

                //====end
                txtRemainBOMFinancial.text(strltrim(num2str(gTMPProdPickList.RemainBOMFinancial,18,2,1,2)));
                txtBOMProposal.text(strltrim(num2str(gTMPProdPickList.BOMProposal,18,2,1,2)));
                txtBOMConsump.text(strltrim(num2str(gTMPProdPickList.BOMConsump,18,2,1,2)));

                element.execute(1);

                ttsbegin;
                gTMPProdPickList.clear();
                delete_from gTMPProdPickList;
                numberOfLinesPerItem = 0;
                ttscommit;
                gUpdatedFlag = False;

            }

        }
        gLstItemId = ProdJournalBOM.ItemId;
    }
//Soondy 20070619 end.
    return true;
}

注:
由本文传递对象的例子引发另一个问题的思考.
问题:
我看过别人的代码,很多时候在处理Query的addRage时,通常是将字符串拼凑('A,B,C,D,E')然后在分解('A','B','C','D'),这样的方式会不会有个限制,当字符串的长度超过某一个数值的时候,AX是否会砍掉后面的部分字符呢?那么又有这样的写法'A..E' ,如此,一般需要再接收端写个方法来处理这样的特别字符.
我的处理方法:
尽量尝试用传递整个Query对象,如此一来,传递的发送方,可以按标准的做法AddRage(),而不必考虑用户选择的范围是什么字符串,在接收对象的一端,由于得到的是Query对象,那么便可使用while (queryRun.next())逐个分解出来.
从代码角度看,直观而简洁了许多,也比较符合OOP的观点..