Upload CSV file through SysOperation Framework

 In this blog I will discuss how can we import records from CSV file in custom table in D365FO.

Create Classes

  • Contract Class 
  • Controller Class
  • Service Class
  • UIBuilder Class
Contract Class

[
    DataContractAttribute, 
    SysOperationContractProcessingAttribute(classStr(Ax_SysOprUIBuilder))
]
class Ax_SysOprContract 
{
    System.IO.Stream            stream;
    Filename                           filename;
    
    /// <summary>
    /// set <c>System.Io.Stream</c>
    /// </summary>
    /// <param name = "_stream">for file uploading</param>
    /// <returns><c>Stream</c></returns>
    public System.IO.Stream parmStream(System.IO.Stream  _stream = stream)
    {
        stream = _stream;
        return stream;
    }


    /// <summary>
    /// set <c>filename</c>
    /// </summary>
    /// <param name = "_filename">for file name</param>
    /// <returns><c>filename</c></returns>
    public Filename parmFilename(Filename _filename = filename)
    {
        filename = _filename;
        return filename;
    }

}


Controller Class

class Ax_SysOprController extends SysOperationServiceController
{

    /// <summary>
    /// calling process operation
    /// </summary>
    protected void new()
    {
        super();
        this.parmClassName(classStr(Ax_SysOprService));
        this.parmMethodName(methodStr(Ax_SysOprService, processOperation));
    }

   /// <summary>
    /// To construct Ax_SysOprController class
    /// </summary>
    /// <param name = "_executionMode">_executionMode</param>
    /// <returns>controller</returns>
    public static Ax_SysOprController construct(SysOperationExecutionMode _executionMode = SysOperationExecutionMode::Synchronous)
    {
        Ax_SysOprController controller;
        controller = new Ax_SysOprController();
        controller.parmExecutionMode(_executionMode);
        return controller;
    }

    /// <summary>
    /// Main method of Ax_SysOprController class
    /// </summary>
    /// <param name = "_args">_args</param>
    public static void main(Args _args)
    {
        Ax_SysOprController controller = Ax_SysOprController::construct();
        controller.parmArgs(_args);
        controller.startOperation();
    }    

}


Service Class

class Ax_SysOprService extends SysOperationServiceBase
{
    Ax_SysOprTable           ax_SysOprTable;
            
    public void processOperation(Ax_SysOprContract  _contract)
    {
        container                           currentLine, record;
        CommaTextStreamIo       localStream;

        localStream = CommaTextStreamIo::constructForRead(_contract.parmStream());

        if (localStream.status() != IO_Status::Ok)
        {
            throw error(strfmt('Is not possible to open the file. Error %1',enum2str(localStream.status())));
        }

        if (localStream)
        {
            currentLine = localStream.read();
            while (localStream.status() == IO_Status::Ok)
            {
                currentLine = localStream.read();
                record = currentLine;

                if (conLen(currentLine))
                {
                    ax_SysOprTable.clear();

                    ax_SysOprTable.PurchId = conPeek(record, 1);
                    ax_SysOprTable.OrderAccount = conPeek(record, 2);
                    ax_SysOprTable.DeliveryName = conPeek(record, 3);
                    ax_SysOprTable.Email = conPeek(record, 4);

                    ax_SysOprTable.insert();

                    Info("Records are Updated in a table!");
                }
            }
        }
    }

}


UIBuilder Class

class Ax_SysOprUIBuilder extends SrsReportDataContractUIBuilder
{
    Ax_SysOprContract       contract;    
    str                                    FileUploadName = 'FileUpload';
    private const str               OKButtonName = 'CommandButton';   
    FileUploadBuild             dialogFileUpload;
    Dialog                              dlg;


    public void Build()
    {
        contract = this.dataContractObject() as Ax_SysOprContract;        
        dlg = this.dialog();
        FormBuildControl formBuildControl = dlg.curFormGroup(dlg.mainFormGroup());
        dialogFileUpload = formBuildControl.addControlEx(classstr(FileUpload), FileUploadName);
        dialogFileUpload.style(FileUploadStyle::MinimalWithFilename);
        dialogFileUpload.fileTypesAccepted('.csv');
        dialogFileUpload.baseFileUploadStrategyClassName(classstr(FileUploadTemporaryStorageStrategy));
        dialogFileUpload.fileNameLabel("Select file");
    }

    /// <summary>
    /// dialog field for form run
    /// </summary>
    public void postRun()
    {
        FormRun formRun = this.dialog().dialogForm().formRun();
        this.dialogEventsSubscribe(formRun);
        this.setDialogOkButtonEnabled(formRun, false);
    }

    /// <summary>
    /// working for browse the file
    /// </summary>
    /// <param name = "_formRun">form run dialog</param>
    private void dialogEventsSubscribe(FormRun _formRun)
    {
        FileUpload fileUpload = _formRun.control(_formRun.controlId(FileUploadName));
        fileUpload.notifyUploadCompleted += eventhandler(this.uploadCompleted);
        fileUpload.notifyUploadAttemptStarted += eventhandler(this.uploadStarted);
        _formRun.onClosing += eventhandler(this.dialogClosing);
    }

    /// <summary>
    /// working on file uploader
    /// </summary>
    /// <param name = "_formRun">form run dialog</param>
    private void dialogEventsUnsubscribe(FormRun _formRun)
    {
        FileUpload fileUpload = _formRun.control(_formRun.controlId(FileUploadName));
        fileUpload.notifyUploadCompleted -= eventhandler(this.uploadCompleted);
        fileUpload.notifyUploadAttemptStarted -= eventhandler(this.uploadStarted);
        _formRun.onClosing -= eventhandler(this.dialogClosing);
    }

    /// <summary>
    ///   After the file has been uploaded, the Ok button is enabled.
    /// </summary>
    protected void uploadCompleted()
    {
        var formRun = this.dialog().dialogForm().formRun();
        FileUpload fileUpload = formRun.control(formRun.controlId(FileUploadName));
        var fileStream = fileUpload.getUploadedFile(true);
        if (!fileStream)
        {
            error("Azure storage file not imported");
        }
        else
        {
            contract.parmStream(fileStream);
            contract.parmFilename(fileUpload.fileName());
            this.setDialogOkButtonEnabled(formRun, true);
        }
    }

    /// <summary>
    ///   Enables or disables the dialog Ok button.
    /// </summary>
    /// <param name = "_formRun">The <c>FormRun</c> object.</param>
    /// <param name = "_isEnabled">Indicates to enable or disable the Ok button.</param>
    protected void setDialogOkButtonEnabled(FormRun _formRun, boolean _isEnabled)
    {
        FormControl okButtonControl = _formRun.control(_formRun.controlId(OkButtonName));
        if (okButtonControl)
        {
            okButtonControl.enabled(_isEnabled);
        }
    }

    /// <summary>
    /// button enable when file is load
    /// </summary>
    private void uploadStarted()
    {
        var formRun = this.dialog().dialogForm().formRun();
        this.setDialogOkButtonEnabled(formRun, false);
    }

    /// <summary>
    /// close button
    /// </summary>
    /// <param name = "sender">form sender</param>
    /// <param name = "e">form event arguments</param>
    [SuppressBPWarningAttribute('BPParameterNotUsed', 'This is event parameter not required to use')]
    private void dialogClosing(xFormRun sender, FormEventArgs e)
    {
        this.dialogEventsUnsubscribe(sender as FormRun);
    }

}

Below are the attachment for file uploading.
















Comments

Popular posts from this blog

Assembly reference containing type is not referenced, Object 'CLRObject' could not be created

Send email using .Net framework

Extract data of PO from the System in Ax 2012