Document handling via X++

In my previous post  Document handling In Dynamics ax , I post step by step tutorial to use base functionality of document handling. Today i Shared dirty code for document handling via X++ code.
Well Document handling a great feature of Axapta; It really just depends on what your application requires. For instance, one application was based upon the sales order having certain document attached to a sales order based on upon a custom enumeration.  So the button has name like invoice declaration for instance. 
If the button is clicked two menu options appear 
– Add document or 
- View document; 

*If the add document button is clicked
The select file dialog appears and the user selects a file and clicks OK. At this point the file is written to the document handling table with the custom enumeration marked as “Invoice declaration”. 

*If the view document option is selected and there is a file to view, 
The standard documentation form will appear and the document will automatically be launched for viewing. 

What I decided to do is was find the lasted record with the enumeration set as the button that is being clicked. I pass RecId of this record using args to the Document handling form so when the form is launched I have access to the recId of the record I want to see. I set a class declaration variable of type Int64 to the recId of being passed in so I have access to the variable all over the form. This way I can use the variable in conditional statements to determine if I want to execute code. Below I will demonstrate how to insert a record in the document handling form and how I view a document of selection from the document handling form from the calling form.

Loading a document from the sales order to the document handling table

    Args                            args = new args();
    formrun                         FormRun;
    filenameSave                    filename;
    Args                            args1 = new args();
    wfsEMSalesOrderDocumentation    wfsEMSalesOrderDocumentation;
    docuref                         docuref;
    form                            form2;
    FilenameFilter                  _conFilter;
    filename                        file;
    recid                           docuvaluerecid;
    docuvalue                       docuvalue;
    int                             hwnd;//wfs ctodd 6/21/2012
    ;

    if(SalesTable)
    {
        _conFilter = ['All FIles','*.*'];
         hWnd = element.hWnd();
        file = WinAPI::getOpenFileName(infoLog.hWnd(),_conFilter,'','Select Document Path');
        if(file)
        {
            ttsbegin;
            docuref.TypeId = "File";
            docuref.Name   = "Commercial Invoice";
            docuref.Notes  = docuRef.Notes;
            docuRef.Restriction  = DocuRestriction::External;
            docuref.RefCompanyId = SalesTable.dataAreaId;
            docuref.WfsExportType = wfsexporttype::CommercialInv;
            docuref.RefTableId   = tablenum(SalesTable);
            docuref.RefRecId     = SalesTable.RecId;
            docuref.insert();

           docuvalue.initValue();
           docuvalue.insert();
           docuref.ValueRecId = docuvalue.RecId;
           docuref.update();
           docuvaluerecid = docuvalue.RecId;

           select forupdate docuvalue where docuvalue.recid == docuvaluerecid;
           docuvalue =  docuvalue::writeDocuValue(docuref,file);
           ttscommit;
      }

Viewing a file to the document handling table from the sales order table

     Args                            args = new args();
    formrun                         FormRun;
    filenameSave                    filename;
    Args                            args1 = new args();
    wfsEMSalesOrderDocumentation    wfsEMSalesOrderDocumentation;
    docuref                         docuref;
    form                            form2;
    FilenameFilter                  _conFilter;
    filename                        file;
    recid                           docuvaluerecid;
    docuvalue                       docuvalue;
    ;

    if(SalesTable)
    {
        args = new Args();
        args.name(formstr(docuview));
        select reverse docuRef  order by createdDateTime 
where Docuref.RefTableId == salesTable.TableId 
     && docuRef.RefRecId == salesTable.RecId 
     && docuRef.WfsExportType == wfsExportType::CommercialInv;

        args.record(docuRef);
        args.parm(int642str(docuRef.RecId));
        args.caller(this);

        FormRun = classfactory.formRunClass(args);
        FormRun.init();
        FormRun.run();
        FormRun.wait();

        salesTable_ds.reread();
        salesTable_ds.refresh();
    }


When viewing my document I want to pass in the record I want to see from the document handling form
//This is the document handling form init method

void init()
{
    #define.ctrlBuildAdd('ctrlAdd')
    DocuType                            docuType;
    FormBuildMenuButtonControl          menuCtrl;
    FormBuildFunctionButtonControl      itemButtonCtrl;

    if (! infolog.parmDocuHandlingActive())
    {
        throw(error("@SYS60737"));
    }
    if (infolog.parmDocu().isDocuViewSet())
    {
        infolog.parmDocu().setActive();
        throw Exception::Info;
    }
    optionView = new DocuOptionView();
    optionView.getLast();

    DocuType::createDefaults();
    docuTypeIdFile = DocuType::typeFile();

    menuCtrl = this.form().design().control(#ctrlBuildAdd);
    while select docuType
        index TypeIdx
    {
        itemButtonCtrl = menuCtrl.addControl(FormControlType::MenuFunctionButton,docuType.TypeId);
        itemButtonCtrl.menuItemType(MenuItemType::Action);
        itemButtonCtrl.menuItemName(menuitemactionstr(DocuActionNew));
        itemButtonCtrl.text(docuType.TypeId);
    }

//Here I set my variable exportRecId to the recId of the parameter I passed in using args
    if(element.args().caller().name() == formstr(wfsEMExportSales)) // dms
 {
 exportRecId = str2int64(element.args().parm());
 }
    super();
    link.enabled(false);
    multiPaste.enabled(false);

    formSplitter_Y = new SysFormSplitter_Y(grpSplit,grpRefGrid,this);
}

Here is the init method on the datasource DocuRef I need to create a query range

void init()
{
    Query           q;
    QueryBuildDataSource qB;
    super();

    q = new Query();
    qB = q.addDataSource(tablenum(DocuRef));
    criteriaRefCompanyId    = qB.addRange(fieldnum(DocuRef,RefCompanyId));
    criteriaRefTableId      = qB.addRange(fieldnum(DocuRef,RefTableId));
    criteriaRefRecId        = qB.addRange(fieldnum(DocuRef,RefRecId));
    criteriaCreatedBy       = qB.addRange(fieldnum(DocuRef,CreatedBy));

    I create a range for the recId of the record being passed in. This is checked with a condition
 We don't want to create the range if no value exists in exportRecId

    if(exportRecId)
 {
 recIdRange = qB.addRange(fieldnum(DocuRef,recId));
 }
    element.setRangeCreateId(optionView.parmShowAllUser());
    this.query(q);

    this.cacheAddMethod(tablemethodstr(DocuRef, isValueAttached));
}

The executeQuery of DocuRef which will perform the query execution of the form for that datasource

void executeQuery()
{
    if (element.isActualFound())
    {
        criteriaRefCompanyId.value(queryValue(actualCompanyId));
        criteriaRefTableId.value(queryValue(actualTableId));
        criteriaRefRecId.value(queryValue(actualRecId));
    }
    else
    {
        criteriaRefCompanyId.value(queryValue(naStr()));
        criteriaRefTableId.value(queryValue(naInt()));
        criteriaRefRecId.value(queryValue(naInt()));
    }

    If my variable has a value then we pass that value to the range I created in the 
 in the init method
   
 if(exportRecId)
 {
 recIdRange.value(SysQuery::value(exportRecId));
 }

    super();
}

Again I use the variable exportRecId to determine if the document should automatically
be viewed when launching from the sales order form. So basically if I have the recId
from a caller I want the document to be automatically launched

void run()
{
    element.setCaption("@SYS26830");

    filter.selection(optionView.parmShowAllUser());
    showOnlyRef.value(optionView.parmShowOnlyRef());
    showImage.value(optionView.parmShowImage());
    this.setShowRef();
    this.setShowImage();
    if(exportRecId)
 {
 showImage.value(1);
 this.setShowImage();
 }
    super();
}
-Harry


Comments

Popular posts from this blog

Connecting to Databases through X++ PART -I

X++ code for document attachment

Multiple Tables In Query