Tuesday, February 22, 2022

Create custom number sequence using x++.

Hi guys, I got a requirement like I need to add new field in standard table and I need to set that field as Index field. I have already some custom data in my machine. I get few errors while I set sync. So I need to fill some dummy data in that field, so I have done that by using below code.

static void getNumberSeq(Args _args) { Mytable mytable; Name id, myId = 'Test00'; //CustGroup custGroup; int myIdNum; void getId(int _id) { str addZero = '00000'; for (int i = 1; i<=5 ; i++) { if (strLen(int2Str(_id)) == i) { addZero = subStr(addZero, 0, (strLen(addZero) - i)); break; } } id = addZero + int2Str(_id); } ttsbegin; while select forupdate crosscompany mytable where !mytable.field1 { myIdNum++; getid(myIdNum); changecompany(mytable.dataareaid) { mytable.field1 = myId + id; mytable.doupdate(); } } ttscommit; /*while select forupdate crossCompany custGroup { org++; getId(org); changeCompany(custGroup.dataAreaId) { info(strFmt('cutGroup- %1, Id -%2',custGroup.CustGroup,myId + id)); } }*/ }


 Please check. For your reference I have used custGroup table and that output I have shown in info. This example I have done in 2012 and D365FO. Only 2012 Output I am giving.



Keep daxing!!


How to Setup number sequence in standard or custom form In D365FO using x++

 How to Setup number sequence in form In D365FO X++.

Create number sequence for new field : Link 

  • After creation of new number sequence we need to setup in one form. I got a requirement to setup new number sequence in standard from.
  • For this I have used the extensions(COC). Please check.
  • If you need for custom form just copy the below methods and pasted in you'r form.
  • The below code is for both custom and standard forms.  

On Form data source.

   [ExtensionOf(formDataSourceStr(MyForm, MyTable))]

final class MyFormDataSource_Extension { void write() { next write();//COC //super(_append); element.numberSeqFormHandler().formMethodDataSourceWrite(); } void delete() { element.numberSeqFormHandler().formMethodDataSourceDelete(); next delete();//COC //super(_append); } void create(boolean _append) // If created externally { element.numberSeqFormHandler().formMethodDataSourceCreatePre(); next create(_append);//COC //super(_append); element.numberSeqFormHandler().formMethodDataSourceCreate(); // this.object(fieldNum(MyTable, Field1)).modified(); // If any modified method is written in data source field level // By the above line we can call, } // In standard they are added below 2 methods. public void linkActive() { element.numberSeqFormHandler().formMethodDataSourceLinkActive(); next linkActive();//COC //super(); } public boolean validateWrite() { boolean ret; MyTable myTable;//COC myTable = this.cursor();//COC if (!myTable.Field1) { element.numberSeqFormHandler().formMethodDataSourceCreate(true); } ret = next validateWrite();//COC //ret = super(); ret = element.numberSeqFormHandler().formMethodDataSourceValidateWrite(true) && ret; return ret; } } On Form.
[ExtensionOf(formStr(MyForm))] final class MyFormDataSource_Extension { public NumberSeqFormHandler numberSeqFormHandler;// global variable public NumberSeqFormHandler numberSeqFormHandler() { if(!numberSeqFormHandler) { numberSeqFormHandler = NumberSeqFormHandler::newForm( myParameters::numRefMyID().NumberSequenceId, this, this.MyTable_ds, fieldNum(MyTable, Field1)); } return numberSeqFormHandler; } void close() { if (numberSeqFormHandler) { numberSeqFormHandler.formMethodClose(); } next Close();//COC //super(); } }

Reference: 

Keep Daxing!!

Get selected records in grid from caller data source in sys operation in D365FO.

Hi guys, Today we see how how to get the selected records from grid in sys operation using x++ in D365FO. 

Just check below code. Main code I have written in controller class.


Contract class: 

[DataContractAttribute] public class TestrContract { List refRecId; [ DataMemberAttribute("refRecID"), AifCollectionTypeAttribute("_refRecID", Types::Int64), SysOperationControlVisibilityAttribute(false)// Hide control ] public List parmrefRecID(List _refRecID = refRecID) { refRecID = _refRecID; return refRecID; } } ---------------------------------------------------------------------------

Controller class:  class TestController extends SrsReportRunController { public void new() { /*super(classStr(TestSysOperationService), methodStr(TestSysOperationService, process), SysOperationExecutionMode::Synchronous);*/ super(); this.parmClassName(classStr(TestSysOperationService)); this.parmMethodName(methodStr(TestSysOperationService, process)); this.parmDialogCaption("Dialog Title"); } public ClassDescription caption() { return "Task Description"; } public static void main(Args _args) { TestController controller = new TestSysOperationController();

        //controller.captionIsSet = false;    // controller.parmDialogCaption(isExcelUp ? "ExcelUpload" :"Manual"); controller.initFromCaller(); controller.refreshCallerRecord(); controller.startOperation(); } private void initFromCaller() { TestCustomer testCustomerLoc; FormDataSource testCustomer_DS; TestrContract contract; List myList; #define.dataContractKey('_contract') contract = this.getDataContractObject(#dataContractKey) contract.parmCallerTableId(this.parmCallerRecord().TableId); if(this.parmargs().dataset() == tableNum(TestCustomer)) { testCustomer_DS = FormDataUtil::getFormDataSource(this.parmCallerRecord()); myList = new List(Types::Int64); for (testCustomerLoc = getFirstSelection(testCustomer_DS); testCustomerLoc; testCustomerLoc = testCustomer_DS.getNext()) { myList.addStart(testCustomerLoc.RecId); } contract.parmrefRecID(myList); } } --------------------------------------------------------------------------------------

Service Class : public class TestSysOperationServiceClass extends SysOperationServiceBase { public void process(TestContractClass _contract) { info("Running"); List list = _contract.parmVendorList(); ListEnumerator enumerator = list.getEnumerator(); while(enumerator.moveNext()) { // your code. Info(strFmt('%1- recid', enumerator.current()); } } }


If u need for report please check my old post.

Get Multi records in report


Keep Daxing!!

Thursday, February 17, 2022

Computed column in data entity in D365FO

Hi guys, I got a requirement like I need to send all warehouses of the selected site while exporting using data entity.

Way 1: Computed column:

Step 1: Create a computed column in the Data entity.

Step 2: Create an extension class for Entity.

[ExtensionOf(dataentityviewstr(MyEntity))] public final class MyEntity_Extension { }

Step 3: create a static method in that class.

Write the below logic.

public static str getWarehouse() { //The FOR XML PATH is creates a concatenated string from a result set. TableName entityName = tableStr(MyEntity); DataSourceName dataSourceName = dataEntityDataSourceStr(MyEntity, MyDataSource); FieldName fieldName = fieldStr(MyTable, MYField); SysDictTable myTestTable = new SysDictTable(tableNum(MyTestTable)); str Warehouse = myTestTable.fieldObject(fieldNum(MyTestTable, Field1)).name(DbBackend::Sql); str site = myTestTable.fieldObject(fieldNum(MyTestTable, Field2)).name(DbBackend::Sql); str testTablaName = myTestTable.name(DbBackend::Sql); str entityField = SysComputedColumn::returnField(dataentityviewstr(MyEntity), dataEntityDataSourceStr(MyEntity, MyDataSource), fieldStr(MyTable, MYField)); // we can use like this //entityField = SysComputedColumn::returnField(entityName, dataSourceName, fieldName); return 'SELECT STUFF((SELECT ' + SysComputedColumn::returnLiteral(DirUtility::ListDelimiter) + '+ RTRIM(EL.' + Warehouse +')'+ ' FROM ' + testTablaName + ' EL' + ' WHERE EL.' + site +' = ' + entityField + //' AND EL.' + Field2 + ' = ' + //SysComputedColumn::returnField(entityName, dataSourceName, fieldName) + ' ORDER BY EL.' + Warehouse + ' FOR XML PATH(' + SysComputedColumn::returnLiteral('') + ')),1,1,'+ SysComputedColumn::returnLiteral('') + ')'; // This is retun 'Warehouse' based on site value. }
// return SysComputedColumn::returnLiteral(''); // Retuns empty value.

Step 4: Add in fields properties.


Value : MyClass::getWarehouse



Standard Reference(In D365):

Entity : InventOperationalSitePostalAddressEntity;
Field : AddressLocationRoles
Class: LogisticsEntityLocationMapInterface
Method:concatenatedLocationRolesComputedFieldDefinition


Way 2: Non-Computed column(virtual Field):

Step 1: Create a field in the Data entity.
Step 2: Set is computed fields property to No.


Step 3: Create an extension class for Entity.

[ExtensionOf(dataentityviewstr(MyEntity))] public final class MyEntity_Extension { }

Step 4: Write the postload method

public void postload() { str wareHouse; next postload(); while select InventLocation where InventLocation.inventSiteId == this.OperationalSiteId { wareHouse += InventSite.InventlocationId + DirUtility::ListDelimiter; } this.warehouse = wareHouse; }

OutPut:

Similar output we get




Keep Daxing!!

Get the data from unmapped field into entity.

 Hi Guys, I added a new unmapped field in the Data entity. I need to get the data from user input(excel or XML).

Data : WHS1;WHS2;WHS3.

Entity methods:

public boolean insertEntityDataSource(DataEntityRuntimeContext _entityCtx, DataEntityDataSourceRuntimeContext _dataSourceCtx) { boolean ret; ret = next insertEntityDataSource(_entityCtx, _dataSourceCtx); if (ret && _dataSourceCtx.name() == dataEntityDataSourceStr(MyEntity, MYDataSource) && this.MyField) { this.operation(_dataSourceCtx); } return ret; } public boolean updateEntityDataSource(DataEntityRuntimeContext _entityCtx, DataEntityDataSourceRuntimeContext _dataSourceCtx) { boolean ret; ret = next updateEntityDataSource(_entityCtx, _dataSourceCtx); if (ret && _dataSourceCtx.name() == dataEntityDataSourceStr(MyEntity, MYDataSource) && this.MyField) { this.operation(_dataSourceCtx); } return ret; } private void operation(DataEntityDataSourceRuntimeContext _dataSourceCtx) { MyClass myClass = MyClass::construct(_dataSourceCtx);// my class myClass.getData(this.MyField); }

My custom class:

public class MyClass
{
Common     common;

public static MyClass construct(DataEntityDataSourceRuntimeContext _dataSourceCtx)
{
    return new MyClass(_dataSourceCtx);// getting entity data source
}

protected void new(DataEntityDataSourceRuntimeContext _dataSourceCtx)
{
    common = _dataSourceCtx.getBuffer();
}

public void getData(Str    _Warehouse)
{
    Str         warehouse;
    container   pack = str2con(_Warehouse, DirUtility::ListDelimiter);
                         //ListDelimiter ';'

    for (int i = 1; i <= conLen(pack); i++)
    {
        warehouse = conPeek(pack, i);

        if (!warehouse)
        {
            continue;
        }
        // you're logic
    }
}
}
I am getting the data like this. The above code is used to get this type of data and do the
opration.

Keep Daxing!!

Wednesday, February 16, 2022

Data entity methods in d365fo

Data entity methods in d365fo.


  • mapEntityToDataSource

// This method is hitting while updating and inserting // we can assign datasource1 recid values to child data source. // public void mapEntityToDataSource(DataEntityRuntimeContext _entityCtx, DataEntityDataSourceRuntimeContext _dataSourceCtx) { if (_entityCtx.getDatabaseOperation() == DataEntityDatabaseOperation::Insert || _entityCtx.getDatabaseOperation() == DataEntityDatabaseOperation::Update) { if (_dataSourceCtx.name() == dataEntityDataSourceStr(MyEntity, MyDataSource)) { TestCustomer testCustomer = _entityCtx.getRuntimeContextByName( dataEntityDataSourceStr(MyEntity, TestCustomer)).getBuffer(); this.CustomerRecid = testCustomer.recid; } } super(_entityCtx, _dataSourceCtx); } -------------------------------------------------------------------------------------------------------------

  • postGetStagingData 

// After inserting into staging this method will trigger // Ref: LedgerJournalEntity public static void postGetStagingData(DMFDefinitionGroupExecution _dmfDefinitionGroupExecution) { MyStaging staging; ttsbegin; while select forupdate staging where staging.DefinitionGroup == _dmfDefinitionGroupExecution.DefinitionGroup && staging.ExecutionId == _dmfDefinitionGroupExecution.ExecutionId && staging.TransferStatus == DMFTransferStatus::NotStarted { staging.Field1 = staging.Field2 + '-' + staging.Field3; staging.Field4 = staging.Field5; staging.update(); }

    /*update_recordset staging     setting OperationalEntityId = curExt() where staging.DefinitionGroup == _dmfDefinitionGroupExecution.DefinitionGroup && staging.ExecutionId == _dmfDefinitionGroupExecution.ExecutionId && staging.TransferStatus == DMFTransferStatus::NotStarted;*/ ttscommit; } -------------------------------------------------------------------------------------------------------------

  • postTargetProcess 

//  Executes the logic once after processing the target data. public static void postTargetProcess(DMFDefinitionGroupExecution _dmfDefinitionGroupExecution) { if (_dmfDefinitionGroupExecution.StagingStatus == DMFBatchJobStatus::Finished) {  MyStaging staging;     ttsbegin;        while select forupdate staging         where staging.DefinitionGroup == _dmfDefinitionGroupExecution.DefinitionGroup     && staging.ExecutionId == _dmfDefinitionGroupExecution.ExecutionId     && staging.TransferStatus == DMFTransferStatus::Completed     {     staging.Field1 = staging.Field2 + '-' + staging.Field3;     staging.Field4 = staging.Field5;     staging.update();     }

    /*update_recordset staging     setting OperationalEntityId = curExt() where staging.DefinitionGroup == _dmfDefinitionGroupExecution.DefinitionGroup && staging.ExecutionId == _dmfDefinitionGroupExecution.ExecutionId && staging.TransferStatus == DMFTransferStatus::Completed;*/     ttscommit; }

---------------------------------------------------------------------------------

  • validateWrite

// Validate the each line. // LedgerJournalEntity public boolean validateWrite() { boolean isValid = super(); // Your logic return isValid; } -------------------------------------------------------------------------------------------------------------

  • validateDelete 

// Validate the each line. // LedgerJournalEntity public boolean validateDelete() { boolean isValid = super(); // Your logic return isValid; } -------------------------------------------------------------------------------------------------------------

  • persistEntity 

//Skip validate field code written in this method //Reference : LogisticsPostalAddressElectronicContactV2Entity public void persistEntity(DataEntityRuntimeContext _entityCtx) { _entityCtx.getEntityRecord().skipDataSourceValidateField( fieldNum(ElectronicContactsEntity, Location), true); super(_entityCtx); } -------------------------------------------------------------------------------------------------------------

  • initValue 

// Assign default values // WE can assign number sequence also. // SMMContactPersonV2Entity public void initValue() { if (!this.skipNumberSequenceCheck()) { NumberSeqRecordFieldHandler::enableNumberSequenceControlForField( this, fieldNum(PIDInvestigatorContactPersonEntity, ContactPersonId), ContactPerson::numRefContactPersonId()); } this.ContactForParty = Parameters::find().ContactForParty; super(); } -------------------------------------------------------------------------------------------------------------

  • initializeEntityDataSource

// Assign values to some fields based on some field values. //Reference : LogisticsPostalAddressElectronicContactV2Entity public void initializeEntityDataSource(DataEntityRuntimeContext _entityCtx, DataEntityDataSourceRuntimeContext _dataSourceCtx) { if (_dataSourceCtx.name() == dataEntityDataSourceStr(MyEntity, MyDataSource)) { ContactPerson contactPerson = ContactPerson::find(this.contactPersonId); if (this.LocationId == '') { DirPartyLocation dirPartyLocation = DirPartyLocation::findOrCreate( contactPerson.party, false); LogisticsLocation logisticsLocation = LogisticsLocation::find( dirPartyLocation.Location); this.LocationId = logisticsLocation.LocationId; this.Location = logisticsLocation.RecId; this.Party = contactPerson.party; _dataSourceCtx.setBuffer(logisticsLocation);//set buffer } } if (_dataSourceCtx.name() == dataEntityDataSourceStr(MyEntity, MyDataSource1)) { DirPartyLocation dirPartyLocationNew = DirPartyLocation::findByPartyLocation(this.Party, this.Location); _dataSourceCtx.setBuffer(dirPartyLocationNew); } super(_entityCtx, _dataSourceCtx); } -------------------------------------------------------------------------------------------------------------

  • insertEntityDataSource 

// While inserting into target //Reference :InventOperationalSiteV2Entity public boolean insertEntityDataSource(DataEntityRuntimeContext _entityCtx, DataEntityDataSourceRuntimeContext _dataSourceCtx) { boolean ret; if (_dataSourceCtx.name() == dataEntityDataSourceStr(InventOperationalSiteV2Entity, ReqSitePolicy)) { _dataSourceCtx.setDatabaseOperation(DataEntityDatabaseOperation::Insert); } ret = super(_entityCtx, _dataSourceCtx); return ret; } -------------------------------------------------------------------------------------------------------------

  • updateEntityDataSource:

// While updating into target //Reference :InventOperationalSiteV2Entity public boolean updateEntityDataSource(DataEntityRuntimeContext _entityCtx, DataEntityDataSourceRuntimeContext _dataSourceCtx) { boolean ret; ret = super(_entityCtx, _dataSourceCtx); return ret; }


Keep Daxing!!

Get email, phone, fax from worker/contact person in D365fo

 Hi guys, Today we see how to get an email, phone, fax from a worker/contact person in D365FO using x++.

In this post, I am using standard table methods to get the details. This will get primary details.

Email:

    public display Email email() { if(this.Worker) { return HcmWorker::findByPersonnelNumber(this.Worker).email(); } else if(this.ContactPersonId) { return ContactPerson::find(this.ContactPersonId).email(); } return nullValueFromType(Types::String); }

Fax: public display TeleFax fax() { if(this.Worker) { return DirParty::primaryElectronicAddress(                                              HcmWorker::findByPersonnelNumber(this.Worker).Person, LogisticsElectronicAddressMethodType::Fax).Locator;

} else if(this.ContactPersonId) { return DirParty::primaryElectronicAddress(                                                                           ContactPerson::find(this.ContactPersonId).Party, LogisticsElectronicAddressMethodType::Fax).Locator;

} return nullValueFromType(Types::String); }

Phone: display Phone phone() { if(this.Worker) { return HcmWorker::findByPersonnelNumber(this.Worker).phone(); } else if(this.ContactPersonId) { return ContactPerson::find(this.ContactPersonId).phone(); } return nullValueFromType(Types::String); }


Keep Daxing!!

Tuesday, February 15, 2022

Multithread in sysoperation framework in D365FO

 Hi guys, Today we see the multithread in sys operation. For sys operation we required 4 classes.

Here we need to create two more classes.

1. Controller class.

2. Service class.

From controller class we need to call service class like the same of sys operation. In service class we need to apply group in our table based on requirement and we are using standard classes to send our value to our contract and controller class.

For multithread Controller class we need to create action menu item.

Just check below code.

Multithread Controller class: 

class TestMultiThreadController extends SysOperationServiceController { public ClassDescription defaultCaption() { return 'order creation using multithread'; } public static void main(Args args) { TestMultiThreadController controller = new TestMultiThreadController(); controller.startOperation(); } public void new() { //super(classStr(TestMultiThreadService), //methodStr(TestMultiThreadService, processOperation), //SysOperationExecutionMode::Synchronous); super(); this.parmClassName(classStr(TestMultiThreadService)); this.parmMethodName(methodStr(TestMultiThreadService, processOperation)); this.parmDialogCaption("Batch operation"); } }

--------------------------------------------------------------------------

Multithread Service Class :


class TestMultiThreadService extends SysOperationServiceBase { public void processOperation()//TestContract _contract) { TestCustomer testCustomer;//My table TestMyController controller;//my controller TestMyContract contract;//my contarct BatchHeader batchHeader; BatchInfo batchInfo; SysRecurrenceData sysRecurrenceData = SysRecurrence::defaultRecurrence(); batchHeader = BatchHeader::construct(); controller = new TestMyController(); while select testCustomer group by Filename // 'Filename' my custom field. where testCustomer.Processed == NoYes::No && testCustomer.ErrorInRecord == NoYes::No { sysRecurrenceData = sysRecurrence::setRecurrenceEndAfter(sysRecurrenceData, 1); batchInfo         = controller.batchInfo(); batchInfo.parmCaption(strFmt("order creation for File- %1", testCustomer.FileName)); contract = controller.getDataContractObject();//get my contract class. contract.parmFileName(testCustomer.FileName);// passing my field value. batchHeader.addTask(controller);//Passing my cotroller to the batch. batchHeader.parmRecurrenceData(sysRecurrenceData); batchHeader.save(); } } }

Keep Daxing!!

Create a simple dialog using x++ in D365fo

 Hi guys, Today we see how to create a simple dialog and how to override its methods. Instead of creating run base batch we can follow the below code. But this code is not run in the batch. For your reference I created the dialog with simple info process and I have override the 2 methods.

Check below.

class TestCustomers { container conSales; DialogField dialogField1, dialogField2, dialogField3; public static void main(Args _args) { CustTable custTable; TestCustomers customers = new TestCustomers(); custTable = _args.record(); if(_args && _args.dataset() == tableNum(CustTable)) { customers.rundialog(custTable); } } // creating dialog from this method public void rundialog(CustTable custTable) { Dialog dialog; dialog = new Dialog(); dialog.caption('Customer salesOrders'); dialogField1 = dialog.addField(ExtendedTypeStr(NoYesId)); dialogField2 = dialog.addField(ExtendedTypeStr(CustAccount)); dialogField3 = dialog.addField(ExtendedTypestr(SalesId)); dialogField2.value(custTable.AccountNum); //dialogField1.allowEdit(false); dialogField1.label('check'); // Override Lookup, modified methods. dialogField1.registerOverrideMethod(methodStr(FormStringControl, Modified), methodStr(TestCustomers, enableOnModified), this); dialogField3.registerOverrideMethod(methodStr(FormStringControl, lookup), methodStr(TestCustomers, salesOrderLookup), this); dialog.run(); if(dialog.closedOk()) { if(dialogField1.value()) { info(strFmt('%1 - %2', dialogField2.value(), dialogField3.value())); //FormDataUtil::getFormDataSource(custTable).refresh(); } else { checkFailed("Value should be mandatory"); } } } private void salesOrderLookup(FormStringControl _control) { Query query; QueryBuildDataSource qbds; query = new Query(); qbds = query.addDataSource(tableNum(SalesTable)); qbds.fields().clearFieldList(); qbds.addSelectionField(fieldNum(SalesTable, SalesId)); qbds.addSelectionField(fieldNum(SalesTable, CustAccount));         // In D365 // SysLookupMultiSelectGrid::lookup( query, _control, _control,_control,conSales); SysLookupMultiSelectGrid::lookup(query, _control, _control,conSales); // In 2012 } public boolean enableOnModified(FormCheckBoxControl _control) { // The below decleration is to access all methods of control. FormStringControl salesOrder = dialogField3.control(); NoYesId check = _control.checked(); dialogField2.enabled(check); salesOrder.enabled(check); salesOrder.mandatory(check); return true; } }


Keep Daxing!!

Monday, February 14, 2022

Set Cursor on First field while creating the new Record in D365FO

Hi guys, Today we see how to set the cursor on the first field while creating the new record in D365FO using x++.

In my form, I have 2 data sources when I am trying to create a new record in form It automatically selects 1st form data source field. But as per my requirement, I have added the 2nd form data source field at first.
For achieving this we have 2 ways.

Way 1:
        Go to from data source field properties. we need to set skip property to yes. 
Path:
\Form\Myfrom\Data Sources\my datasouce\Fields\myfield
        


Way 2:
We can write in an active method from the data source.
first, we need set AutoDeclaration property is set to yes. (Selected field)

 public int active() {     int ret;     ret = super();     FormControlName.setFocus(); 

        return ret;

} 

Keep Daxing!!

Get multiple records from caller data source while generating report in D365FO.

 Get multiple records from caller data source in report.

Contract class: 

[DataContractAttribute] public class TestrContract { List refRecId; [ DataMemberAttribute("refRecID"), AifCollectionTypeAttribute("_refRecID", Types::Int64) ] public List parmrefRecID(List _refRecID = refRecID) { refRecID = _refRecID; return refRecID; } }

------------------------------------------------------------------------ Controller class:  class TestController extends SrsReportRunController { public static TestController construct() { return new TestController(); } public static void main(Args _args) { TestController controller = TestController::construct(); controller.parmReportName(ssrsReportStr(TestReport, Report)); controller.parmArgs(_args); controller.parmShowDialog(false); controller.startOperation(); } protected void prePromptModifyContract() { TestCustomer testCustomer, testCustomerLoc; FormDataSource testCustomer_DS; TestrContract contract; List myList; contract = this.parmReportContract().parmRdpContract(); if(this.parmargs().dataset() == tableNum(TestCustomer)) { testCustomer = this.parmargs().record(); testCustomer_DS = FormDataUtil::getFormDataSource(testCustomer); //whsLoadTable.dataSource(); myList = new List(Types::Int64); for (testCustomerLoc = getFirstSelection(testCustomer_DS); testCustomerLoc; testCustomerLoc = testCustomer_DS.getNext()) { myList.addStart(testCustomerLoc.RecId); } contract.parmrefRecID(myList); } } }

------------------------------------------------------------------------ Dp class:  [ SrsReportQueryAttribute(queryStr(TestQuery)), SrsReportParameterAttribute(classStr(TestContract)) ] class TestDP extends SRSReportDataProviderBase { TestTmp testTmp; [ SrsReportDataSetAttribute(tableStr(TestTmp)) ] public TestTmp getTestTmp() { select testTmp; return testTmp; } public void processReport() { Query query; QueryBuildDataSource qbds; QueryRun qr; TestContract contract; TestCustomer testCustomer; container pack, testcon; List myList; ListIterator listterator; query = this.parmQuery(); qbds = query.dataSourceTable(tableNum(TestCustomer)); contract = this.parmDataContract() as TestContract; myList = contract.parmrefRecID(); listterator = new ListIterator(myList); pack = myList.pack();//convert to container for (int i = 1 ; i <= conLen(pack) ; i++) { if (TestCustomer::findByRecId(conPeek(pack, i)).RecId) { testcon += conPeek(pack, i); } } if (testcon != conNull()) { qbds.addrange(fieldnum(TestCustomer, RecId)).value(con2Str(testcon)); } qr = new QueryRun(query); while(qr.next()) { testCustomer = qr.get(tableNum(TestCustomer)); this.insertIntoTmp(testCustomer); } }

------------------------------------------------------------------------

Keep Daxing!!