Data Entity Export from code

This post  explains how to implement the same data entity export functionality provided in the Data Management workspace in a form or a menu item.

Below is form dialog that I created to research how to create data entities and run the export functionality directly from X++ code and using standard DMF classes.

Creating an export data project

The first code sample is how I created the export data project. The definition group name is anything that you want. For the source name (data format EXCEL, CSV etc) you can use the standard lookup method DMFQuickImportExportFormHelper.buildSourceNameControlLookup(). For the entity name there is another standard lookup DMFUtil::lookupEntity(this).

/// <summary>
/// Create DMF Processing group to export 'Customer Groups'
/// </summary>
/// <param name = "_groupName">Definition group name</param>
/// <param name = "_sourceName">Export file type e.g. CSV</param>
/// <param name = "_entityName">Entity Name</param>
public static void createNewDefinitionGroup(DMFDefinitionGroupName _groupName, DMFSourceName _sourceName, DMFEntityName _entityName)
{
    DMFEntity dmfEntity = DMFEntity::find(_entityName);
    DMFDataSource dmfDataSource = DMFDataSource::find(_sourceName);

    if (dmfEntity &amp;&amp; dmfDataSource)
    {
        DMFDefinitionGroupName dmfDefinitionGroupName = _groupName;
        Description description = _groupName;

        //Create data project
        DMFEntityBase::addEntityForProcessingV3(dmfDefinitionGroupName,
                                            description,
                                            dmfEntity.EntityName,
                                            dmfDataSource.SourceName,
                                            "", //Sample file
                                            "@SYS6047", //"All fields"
                                            NoYes::Yes, //Skip staging
                                            NoYes::Yes, //Export to File. Set Yes to create a definition group of operation type Export
                                            "", //Sheet lookup
                                            NoYes::No, //Truncate Entity Data
                                            DMFRefreshType::FullPush);
    }
}

Exporting the data definition group

To export the definition group we use the DMFPackageExporter class after creating a new DMF Definition Group Execution.

DMFDefinitionGroup definitionGroup = DMFDefinitionGroup::find("My demo export"); 

if (definitionGroup)
{
    DMFExecutionId dmfExecutionId = DMFUtil::setupNewExecution(definitionGroup.DefinitionGroupName);
    Description description = strFmt('Execution - %1 for Definition Group - %2', dmfExecutionId, definitionGroup.DefinitionGroupName);
            
    ttsbegin;

    //Create new dmf execution group for the new execution
    if (DMFDefinitionGroupExecution::insertOrDisplay(definitionGroup, dmfExecutionId, description, false))
    {                
        dmfDefinitionGroupExecution = DMFDefinitionGroupExecution::find(definitionGroup.DefinitionGroupName, dmfDefinitionGroupEntity.Entity, dmfExecutionId);
                
        if (dmfDefinitionGroupExecution)
        {
            DMFExportImportDataContract dmfDataContract = new DMFExportImportDataContract();
                    
            DMFPackageExporter packageExporter = new DMFPackageExporter();
            packageExporter.exportToPackageV2(definitionGroup.DefinitionGroupName,
                                '',
                                _dmfDefinitionGroupName,
                                dmfExecutionId,
                                dmfDataContract.parmReExecute(),
                                curext(),
                                dmfDataContract.parmGenerateDataPackage());

            //Download file for the newly created dmf execution group
            ETBDataEntityHelper::downloadFile(dmfDefinitionGroupExecution);
        }
    }

    ttscommit;
}

Download file

To send the file to the user from the DMF Definition Group Execution table we use DMFEntityExportDetails to get the download URL.

public static void downloadFile(DMFDefinitionGroupExecution dmfDefinitionGroupExecution)
{
    DMFEntityExportDetails  exportDetails;
    DMFEntityName           entityName;
    DMFEntity               dMFEntity = DMFEntity::find(dmfDefinitionGroupExecution.Entity);
            
    if (dMFEntity.ParentEntityName != '')
    {
        entityName = dMFEntity.ParentEntityName;
    }
    else
    {
        entityName = dmfDefinitionGroupExecution.Entity;
    }

    select firstonly1 SampleFilePath, DefinitionGroup from exportDetails where
                exportDetails.DefinitionGroup == dmfDefinitionGroupExecution.DefinitionGroup &amp;&amp;
                exportDetails.ExecutionId == dmfDefinitionGroupExecution.ExecutionId &amp;&amp;
                exportDetails.Entity == entityName;

    if (exportDetails.RecId &amp;&amp; exportDetails.SampleFilePath)
    {
        str downloadUrl = DMFDataPopulation::getAzureBlobReadUrl(str2Guid(exportDetails.SampleFilePath));
            System.IO.Stream stream = File::UseFileFromURL(downloadUrl);
            File::SendFileToUser(stream, strFmt('%1-%2.%3', exportDetails.DefinitionGroup, exportDetails.Entity, DMFDataPopulation::getFileExtensionFromURL(downloadUrl)));
    }
    else
    {
        warning(strFmt("@DMF:DMFNoExportFileFoundForEntity", dmfDefinitionGroupExecution.Entity, dmfDefinitionGroupExecution.ExecutionId));
    }
}

Changing the query on the export definition group

Another useful class is the DMFFormBrowser. This opens the entity query dialog and lets the user add filters. You can also code your own ranges on the query and then package it to attached to the DMF Group Execution. You would use this code before calling the exportToPackageV2 method shown previously.

container   queryData;

if (dmfDefinitionGroupEntity)
{
    queryData = DMFUtil::getDefaultQueryForEntityV3(dmfDefinitionGroupEntity.Entity, dmfDefinitionGroupEntity.DefinitionGroup);
    //Show query dialog
    queryData = DMFFormBrowser::showQuery(queryData);
}
            
//Update Query filter on DMF Definition Group
if(queryData != connull())
{
    dmfDefinitionGroupExecution.selectForUpdate(true);
    dmfDefinitionGroupExecution.QueryData = queryData;
    dmfDefinitionGroupExecution.write(); 
                       
    if (dmfDefinitionGroupEntity)
    {
        //Save updated query for next time
        dmfDefinitionGroupEntity.selectForUpdate(true);
        dmfDefinitionGroupEntity.QueryData = queryData;
        dmfDefinitionGroupEntity.write();
    }
}