Tuesday, November 6, 2018

X++ | d365FO - import and export data via XML (Part 2 - Import)

From part 1 X++ | d365FO - import and export data via XML (Part 1 - Export). Now assume that we are on the test system with the exported file 'TestTblParm.xml'.

Before the next step, delete all records on the test table, then you can be sure the new insert lines come from the importing code.












So it's time to import..

Again write and run this below code.
 class Example_Job_XMLimport  
 {      
   public static void main(Args _args)  
   {  
     FileUploadTemporaryStorageResult result;  
     str               xml;  
     XmlDocument xmlDocument;  
     XmlNodeList xmlRecords;  
     XmlNode          xmlRecord;  
     XmlNode          tableName;  
     XmlNodeList xmlFields;  
     XmlNode          xmlField;  
     XmlNode          xmlFieldName;  
     XmlNode          xmlFieldValue;  
     BinData          binData;  
     container     binDataCon;  
     DictTable           dictTable;  
     common                record;  
     Map                     mapTables = new Map(Types::String,Types::Integer);  
     SysDataTableCtrl sysDataTableCtrl;  
     void initRecord(str _tableName)  
     {  
       ;  
       dictTable = new DictTable(tableName2Id(_tableName));  
       if(dictTable != null)  
       {  
         record = dictTable.makeRecord();  
         record.clear();  
         // if not yet in the map, then delete records  
         if(!mapTables.exists(_tableName))  
         {  
           sysDataTableCtrl = new SysDataTableCtrl(dictTable);  
           sysDataTableCtrl.deleteTable();  
         }  
         // keep table name in the map  
         mapTables.insert(_tableName, 0);  
       }  
     }  
     void setFieldValue(str _fieldName, str _fieldValue)  
     {  
       int           fieldId = fieldName2Id(dictTable.id(), _fieldName);  
       DictField dictField;  
       ;  
       if(fieldId==0)  
         return;  
       dictField = dictTable.fieldObject(fieldId);  
       if(!dictField)  
         return;  
       if(dictField.isSystem())  
         return;  
       switch(dictField.baseType())  
       {  
         case Types::String:  
         case Types::VarString:  
           record.(fieldId) = _fieldValue;  
           break;  
         case Types::Integer:  
           record.(fieldId) = str2int(_fieldValue);  
           break;  
         case Types::Int64:  
           record.(fieldId) = str2int64(_fieldValue);  
           break;  
         case Types::Real:  
           record.(fieldId) = str2num(_fieldValue);  
           break;  
         case Types::Date:  
           record.(fieldId) = str2date(_fieldValue, 123);  
           break;  
         case Types::Enum:  
           record.(fieldId) = str2int(_fieldValue);  
           break;  
         case Types::Guid:  
           record.(fieldId) = str2guid(_fieldValue);  
           break;  
         case Types::Container:  
           break;  
         case Types::UtcDateTime:  
           record.(fieldId) = str2datetime(_fieldValue, 123);  
           break;  
         default:  
           info(strFmt('Type %1 not imported', dictField.baseType()));  
           break;  
       }  
     }  
     void insertRecord()  
     {  
       record.insert();  
     }  
     ;  
     result = File::GetFileFromUser(classStr(FileUploadTemporaryStorageStrategy));  
 
     if(result && result.getUploadStatus())  
     {  
       using(System.IO.MemoryStream stream = result.openResult() as System.IO.MemoryStream)  
         using(System.IO.StreamReader sreader = new System.IO.StreamReader(stream, System.Text.Encoding::UTF8, true))  
       {  
         xml = sreader.ReadToEnd();  
       }  
       // process file content  
       xmlDocument = new XmlDocument();  
       xmlDocument.loadXml(xml);  
       info(xmlDocument.root().name());  
       xmlRecords = xmlDocument.root().childNodes();  
       xmlRecord = xmlRecords.nextNode();  
       while(xmlRecord)  
       {  
         ttsbegin;  
         tableName = xmlRecord.attributes().getNamedItem('table');  
         initRecord(tableName.value());  
         if(dictTable != null)  
         {  
           xmlFields = xmlRecord.childNodes();  
           xmlField = xmlFields.nextNode();  
           while(xmlField)  
           {  
             xmlFieldName = xmlField.attributes().getNamedItem('name');  
             xmlFieldValue = xmlField.firstChild();  
             binDataCon = BinData::loadFromBase64(xmlFieldValue.value());  
             binData = new BinData();  
             binData.setData(binDataCon);  
             setFieldValue(xmlFieldName.value(), binData.getStrData());  
             xmlField = xmlFields.nextNode();  
           }  
           insertRecord();  
         }  
         ttscommit;  
         xmlRecord = xmlRecords.nextNode();  
       }  
       // inform success  
       info("Parameter is imported.");  
     }  
     // inform if upload failed  
     else  
     {  
       error("Upload failed");  
     }  
   }  
 }  


When running

















You will see that by this way you can move data across ax environment very easy!

Until the next post!

4 comments:

  1. Hello,
    Thanks for writing this. It has helped me a lot. I have only one issue. The import and export is working only for a single record. Is there anyway to make it work for importing multiple file and exporting multiple records?

    ReplyDelete
    Replies
    1. Hi, it works actually multiple files and records. You can see it again part I and II together. Let test it and let me know if you have some issues.

      Delete
  2. HI, Its giving me null value error on this
    initRecord(tableName.value());

    ReplyDelete
    Replies
    1. Hi, you can check the previous statement.. tableName = xmlRecord.attributes().getNamedItem('table');

      and also run the code from the part 1 of this article. That should help you.

      You can check this too. https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmlnamednodemap.getnameditem?view=net-6.0

      Delete