{"id":1111,"date":"2023-02-09T16:11:05","date_gmt":"2023-02-09T15:11:05","guid":{"rendered":"http:\/\/daxvisionerp.com\/?p=1111"},"modified":"2025-10-22T14:31:33","modified_gmt":"2025-10-22T14:31:33","slug":"file-import-with-sysoperationframework-dialog-d365-fo","status":"publish","type":"post","link":"https:\/\/daxvisionerp.com\/home\/file-import-with-sysoperationframework-dialog-d365-fo\/","title":{"rendered":"File import with SysOperationFramework dialog &#8211; D365 FO"},"content":{"rendered":"\n<p>This code allows you to create customers by uploading a text\/csv file that contains a list of customers. And thanks to the encoding method, it also handles special characters without problems (you can set any character table in the processOperation method at the instantiation of &#8220;sr&#8221; variable.). This solution also handles UTF-8 and ANSI-encoded documents that contains special characters.<\/p>\n\n\n\n<p>Contract class:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ &lt;summary&gt;\n\/\/\/ Contract class of file uploader SysOperationFramework dialog.\n\/\/\/ &lt;\/summary&gt;\n&#91;DataContractAttribute,\n SysOperationContractProcessing(classStr(ImportDialogUIBuilder_DV))]\nfinal class ImportDialogContract_DV\n{\n    container custList;\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Parameter method which holds values of the packed variables from &lt;c&gt;FileUploadTemporaryStorageResult&lt;\/c&gt; class.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name = \"_wage\"&gt;Packed instance of &lt;c&gt;FileUploadTemporaryStorageResult&lt;\/c&gt; class&lt;\/param&gt;\n    \/\/\/ &lt;returns&gt;Container with packed values&lt;\/returns&gt;\n    &#91;DataMemberAttribute('FileUploadControl'),\n     SysOperationLabelAttribute(\"Customer list\")]\n    public container parmCustList(container _custList =  custList)\n    {\n        custList = _custList;\n        return custList;\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>UiBuilder class:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ &lt;summary&gt;\n\/\/\/ UI Builder class for file uploader SysOperationFramework dialog.\n\/\/\/ &lt;\/summary&gt;\nfinal class ImportDialogUIBuilder_DV extends SysOperationAutomaticUIBuilder\n{\n    ImportDialogContract_DV   contract;\n\n    #define.fileUpload('fileUpload')\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Overriden the &lt;c&gt;postBuild&lt;\/c&gt; method to add a &lt;c&gt;FileUpload&lt;\/c&gt; controls\n    \/\/\/ &lt;\/summary&gt;\n    public void postBuild()\n    {\n        DialogGroup      fieldGroup;\n        FormBuildControl fileUploadControl;\n        FileUploadBuild  fileUploadBuild;\n\n        super();\n\n        contract = this.dataContractObject();\n\n        fieldGroup = dialog.addgroup(\"Upload a customer list file.\");\n\n        fileUploadControl   = dialog.formBuildDesign().control(fieldGroup.name());\n        fileUploadBuild     = fileUploadControl.addControlEx(classstr(FileUpload), #fileUpload);\n\n        fileUploadBuild.style(FileUploadStyle::MinimalWithFilename);\n        fileUploadBuild.baseFileUploadStrategyClassName(classstr(FileUploadTemporaryStorageStrategy));\n        fileUploadBuild.fileTypesAccepted(\".txt, .csv\");\n        fileUploadBuild.fileNameLabel(\"Customer list\");\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Subscribes events.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name = \"_formRun\"&gt;Dialog form instance&lt;\/param&gt;\n    private void dialogEventsSubscribe(FormRun _formRun)\n    {\n        FileUpload custList                   = _formRun.control(_formRun.controlId(#fileUpload));\n        custList.notifyUploadCompleted        += eventhandler(this.uploadCompleted);\n        custList.notifyUploadAttemptStarted   += eventhandler(this.uploadStarted);\n        \n        _formRun.onClosing += eventhandler(this.dialogClosing);\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Unsubscribes the registered events.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name = \"sender\"&gt;xFormRun of dialog&lt;\/param&gt;\n    \/\/\/ &lt;param name = \"e\"&gt;FormEventArgs of dialog&lt;\/param&gt;\n    &#91;SuppressBPWarning('BPParameterNotUsed', \"Parameter required\")]\n    private void dialogClosing(xFormRun sender, FormEventArgs e)\n    {\n        this.dialogEventsUnsubscribe(sender as FormRun);\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Unsubscribes events from the dialog form.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name = \"_formRun\"&gt;The instance of the dialog form&lt;\/param&gt;\n    private void dialogEventsUnsubscribe(FormRun _formRun)\n    {\n        FileUpload custList       = _formRun.control(_formRun.controlId(#fileUpload));\n\n        custList.notifyUploadCompleted        -= eventhandler(this.uploadCompleted);\n        custList.notifyUploadAttemptStarted   -= eventhandler(this.uploadStarted);\n        \n        _formRun.onClosing                          -= eventhandler(this.dialogClosing);\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Executes additional logic once the upload of the file is completed.\n    \/\/\/ &lt;\/summary&gt;\n    private void uploadCompleted()\n    {\n        FormRun                             formRun                 = this.dialog().dialogForm().formRun();\n        FileUpload                          custList                = formRun.control(formRun.controlId(#fileUpload));\n        FileUploadTemporaryStorageResult    custListUploadResult    = custList.getFileUploadResult();\n\n        if (custListUploadResult != null &amp;&amp; custListUploadResult.getUploadStatus())\n        {\n            contract.parmCustList(custListUploadResult.pack());\n        }\n\n        this.setDialogOkButtonEnabled(formRun, true);\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Additional logic which is executed once the upload of the file has started.\n    \/\/\/ &lt;\/summary&gt;\n    private void uploadStarted()\n    {\n        FormRun formRun = this.dialog().dialogForm().formRun();\n        this.setDialogOkButtonEnabled(formRun, false);\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Enables or disables the OK button.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name = \"_formRun\"&gt;Dialog form instance&lt;\/param&gt;\n    \/\/\/ &lt;param name = \"_isEnabled\"&gt;True if OK button should be enabled, false if shouldn't.&lt;\/param&gt;\n    private void setDialogOkButtonEnabled(FormRun _formRun, boolean _isEnabled)\n    {\n        FormControl okButtonControl = _formRun.control(_formRun.controlId(\"CommandButton\"));\n\n        if (okButtonControl)\n        {\n            okButtonControl.enabled(_isEnabled);\n        }\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Adds event subscriptions.\n    \/\/\/ &lt;\/summary&gt;\n    public void postRun()\n    {\n        super();\n\n        FormRun formRun = this.dialog().dialogForm().formRun();\n        this.dialogEventsSubscribe(formRun);\n\n        this.setDialogOkButtonEnabled(formRun, false);\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>Controller class:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ &lt;summary&gt;\n\/\/\/ Controller class of file uploader dialog.\n\/\/\/ &lt;\/summary&gt;\nfinal class ImportDialogController_DV extends SysOperationServiceController\n{\n    protected void new()\n    {\n        super();\n     \n        this.parmClassName(classStr(ImportDialogService_DV));\n        this.parmMethodName(methodStr(ImportDialogService_DV, processOperation));\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Method which is run while calling the corresponding menu item\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name = \"args\"&gt;Arguments passed from the menu item&lt;\/param&gt;\n    public static void main(Args args)\n    {\n        ImportDialogController_DV controller;\n     \n        controller = new ImportDialogController_DV();\n        controller.parmLoadFromSysLastValue(false);\n\n        controller.startOperation();\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets the caption of the dialog\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name = \"_dialogCaption\"&gt;The caption to set for the dialog&lt;\/param&gt;\n    \/\/\/ &lt;returns&gt;The caption of the dialog&lt;\/returns&gt;\n    public LabelType parmDialogCaption(LabelType _dialogCaption = dialogCaption)\n    {\n        LabelType ret;\n    \n        ret = super(_dialogCaption);\n\n        ret = \"Customer list import\";\n        \n        return ret;\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>Service class:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ &lt;summary&gt;\n\/\/\/ Service class with file handling and data insertion logic.\n\/\/\/ &lt;\/summary&gt;\nfinal class ImportDialogService_DV extends SysOperationServiceBase\n{\n    #Define.separator(',')\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ The code that processes the file\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name = \"_contract\"&gt;Instance of the &lt;c&gt;ImportDialogContract_DV&lt;\/c&gt; class&lt;\/param&gt;\n    public void processOperation(ImportDialogContract_DV _contract)\n    {\n        FileUploadTemporaryStorageResult    fileUploadResult = new FileUploadTemporaryStorageResult();\n        System.IO.Stream                    readStream;\n        System.IO.StreamReader              sr;\n        CustTable                           custTable;\n        InteropPermission                   interopPermission;\n        str                                 srLine;\n        container                           line;\n        List                                lineList;\n        RecordInsertList                    recordInsertList;\n            \n        if (_contract.parmCustList() != conNull())\n        {\n            fileUploadResult.unpack(_contract.parmCustList());\n\n            readStream          = File::UseFileFromURL(fileUploadResult.getDownloadUrl());\n            sr                  = new System.IO.StreamReader(readStream, System.Text.Encoding::GetEncoding(1250));\n            lineList            = new List(Types::AnyType);\n\n            if(sr.Peek() == -1)\n            {\n                return;\n            }\n\n            interopPermission = new InteropPermission(InteropKind::ClrInterop);\n            interopPermission.assert();\n        \n            srLine      = sr.ReadLine();\n\n            while(!System.String::IsNullOrEmpty(srLine))\n            {\n                lineList    = strSplit(srLine, #separator);\n                line        = list2Con(lineList);\n\n                if(!line)\n                {\n                    continue;\n                }\n\n                custTable.clear();\n                custTable.AccountNum    = conPeek(line, 1);\n                custTable.CustGroup     = conPeek(line, 2);\n                custTable.Currency      = conPeek(line, 3);\n                custTable.insert(DirPartyType::None, conPeek(line, 4));\n                custTable.initValue();\n\n                srLine = sr.ReadLine();\n            }\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>With this code we will get a dialog window with a simple fileUpload control where the user can choose the txt\/csv file from his\/her local computer after clicking the &#8220;Browse&#8221; button.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/daxvisionerp.com\/home\/wp-content\/uploads\/2023\/02\/Dialog-1.png\"><img decoding=\"async\" src=\"https:\/\/daxvisionerp.com\/home\/wp-content\/uploads\/2023\/02\/Dialog-1.png\" alt=\"Picture of the file upload dialog.\" class=\"wp-image-1113\" style=\"width:579px;height:303px\"\/><\/a><figcaption class=\"wp-element-caption\">Result<\/figcaption><\/figure>\n\n\n\n<p>You can read more about SysOperationFramework on the following link: <a href=\"https:\/\/thedynamicsdrive.wordpress.com\/sysoperation-framework-in-d365-for-operations\/\" target=\"_blank\" rel=\"noreferrer noopener\">SysOperation FrameWork in D365 for Operations \u2013 TheDynamicsDrive (wordpress.com)<\/a>. <br><\/p>\n\n\n<div class=\"taxonomy-post_tag wp-block-post-terms\"><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/ansi\/\" rel=\"tag\">ANSI<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/csv\/\" rel=\"tag\">csv<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/customer-import\/\" rel=\"tag\">customer import<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/d365\/\" rel=\"tag\">D365<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/d365-fo\/\" rel=\"tag\">D365 Fo<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/dynamicsax\/\" rel=\"tag\">dynamicsax<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/encoding\/\" rel=\"tag\">Encoding<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/file-import\/\" rel=\"tag\">File import<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/file-upload\/\" rel=\"tag\">File upload<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/process-file\/\" rel=\"tag\">Process file<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/special-characters\/\" rel=\"tag\">Special characters<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/sysoperationframework\/\" rel=\"tag\">SysOperationFramework<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/txt\/\" rel=\"tag\">txt<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/daxvisionerp.com\/home\/tag\/utf-8\/\" rel=\"tag\">UTF-8<\/a><\/div>","protected":false},"excerpt":{"rendered":"<p>This code allows you to create customers by uploading a text\/csv file that contains a list of customers. And thanks to the encoding method, it also handles special characters without problems (you can set any character table in the processOperation method at the instantiation of &#8220;sr&#8221; variable.). This solution also handles UTF-8 and ANSI-encoded documents [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"1080","footnotes":""},"categories":[19],"tags":[173,175,177,179,181,35,183,185,187,189,191,193,195,197],"class_list":["post-1111","post","type-post","status-publish","format-standard","hentry","category-dynamics-365fo","tag-ansi","tag-csv","tag-customer-import","tag-d365","tag-d365-fo","tag-dynamicsax","tag-encoding","tag-file-import","tag-file-upload","tag-process-file","tag-special-characters","tag-sysoperationframework","tag-txt","tag-utf-8"],"_links":{"self":[{"href":"https:\/\/daxvisionerp.com\/home\/wp-json\/wp\/v2\/posts\/1111","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/daxvisionerp.com\/home\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/daxvisionerp.com\/home\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/daxvisionerp.com\/home\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/daxvisionerp.com\/home\/wp-json\/wp\/v2\/comments?post=1111"}],"version-history":[{"count":1,"href":"https:\/\/daxvisionerp.com\/home\/wp-json\/wp\/v2\/posts\/1111\/revisions"}],"predecessor-version":[{"id":1340,"href":"https:\/\/daxvisionerp.com\/home\/wp-json\/wp\/v2\/posts\/1111\/revisions\/1340"}],"wp:attachment":[{"href":"https:\/\/daxvisionerp.com\/home\/wp-json\/wp\/v2\/media?parent=1111"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/daxvisionerp.com\/home\/wp-json\/wp\/v2\/categories?post=1111"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/daxvisionerp.com\/home\/wp-json\/wp\/v2\/tags?post=1111"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}