Showing posts with label Document Handling. Show all posts
Showing posts with label Document Handling. Show all posts

March 07, 2013

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 a certain document attached to a sales order based on upon a custom enumeration.  So the button has a name like an 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


October 20, 2012

Document Handling in Microsoft Dynamics AX

Document Handling in Microsoft Dynamics AX 2009 and 2012





Document Handling is very useful to attach files related to AX data to forms. It’s possible to add data at any form. It is also useful to attache any reference document to any record in Form.
To use Document Handling you have to activate it by follow these steps...

To activate this feature follow the next steps:


1. Go to BasicSetupDocument management:


image
image
2. Setup Parameters:

image

Active directory is the default path where allocate the files to attach.
Check Use Active document tables has to be activated.


image

Number sequence to numerate the attachments.
3. Define Document types:

image

For each type it’s necessary define the location folder:

image

4. Select in which forms it’s possible to attach documents in Active document tables:

image


5. Now, we can attach documents in the above forms. For example in Employees form:

image
image


For this example, we are going to attach a Photo:
image

Select the photo and click open:

image


With the check Show file activated we can see the photo/document:

image

Also, we can open the document with the right button Open.

-Harry