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

Data cleanup in x++

Send email using .Net framework