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 “sr” variable.). This solution also handles UTF-8 and ANSI-encoded documents that contains special characters.
Contract class:
/// <summary>
/// Contract class of file uploader SysOperationFramework dialog.
/// </summary>
[DataContractAttribute,
SysOperationContractProcessing(classStr(ImportDialogUIBuilder_DV))]
final class ImportDialogContract_DV
{
container custList;
/// <summary>
/// Parameter method which holds values of the packed variables from <c>FileUploadTemporaryStorageResult</c> class.
/// </summary>
/// <param name = "_wage">Packed instance of <c>FileUploadTemporaryStorageResult</c> class</param>
/// <returns>Container with packed values</returns>
[DataMemberAttribute('FileUploadControl'),
SysOperationLabelAttribute("Customer list")]
public container parmCustList(container _custList = custList)
{
custList = _custList;
return custList;
}
}
UiBuilder class:
/// <summary>
/// UI Builder class for file uploader SysOperationFramework dialog.
/// </summary>
final class ImportDialogUIBuilder_DV extends SysOperationAutomaticUIBuilder
{
ImportDialogContract_DV contract;
#define.fileUpload('fileUpload')
/// <summary>
/// Overriden the <c>postBuild</c> method to add a <c>FileUpload</c> controls
/// </summary>
public void postBuild()
{
DialogGroup fieldGroup;
FormBuildControl fileUploadControl;
FileUploadBuild fileUploadBuild;
super();
contract = this.dataContractObject();
fieldGroup = dialog.addgroup("Upload a customer list file.");
fileUploadControl = dialog.formBuildDesign().control(fieldGroup.name());
fileUploadBuild = fileUploadControl.addControlEx(classstr(FileUpload), #fileUpload);
fileUploadBuild.style(FileUploadStyle::MinimalWithFilename);
fileUploadBuild.baseFileUploadStrategyClassName(classstr(FileUploadTemporaryStorageStrategy));
fileUploadBuild.fileTypesAccepted(".txt, .csv");
fileUploadBuild.fileNameLabel("Customer list");
}
/// <summary>
/// Subscribes events.
/// </summary>
/// <param name = "_formRun">Dialog form instance</param>
private void dialogEventsSubscribe(FormRun _formRun)
{
FileUpload custList = _formRun.control(_formRun.controlId(#fileUpload));
custList.notifyUploadCompleted += eventhandler(this.uploadCompleted);
custList.notifyUploadAttemptStarted += eventhandler(this.uploadStarted);
_formRun.onClosing += eventhandler(this.dialogClosing);
}
/// <summary>
/// Unsubscribes the registered events.
/// </summary>
/// <param name = "sender">xFormRun of dialog</param>
/// <param name = "e">FormEventArgs of dialog</param>
[SuppressBPWarning('BPParameterNotUsed', "Parameter required")]
private void dialogClosing(xFormRun sender, FormEventArgs e)
{
this.dialogEventsUnsubscribe(sender as FormRun);
}
/// <summary>
/// Unsubscribes events from the dialog form.
/// </summary>
/// <param name = "_formRun">The instance of the dialog form</param>
private void dialogEventsUnsubscribe(FormRun _formRun)
{
FileUpload custList = _formRun.control(_formRun.controlId(#fileUpload));
custList.notifyUploadCompleted -= eventhandler(this.uploadCompleted);
custList.notifyUploadAttemptStarted -= eventhandler(this.uploadStarted);
_formRun.onClosing -= eventhandler(this.dialogClosing);
}
/// <summary>
/// Executes additional logic once the upload of the file is completed.
/// </summary>
private void uploadCompleted()
{
FormRun formRun = this.dialog().dialogForm().formRun();
FileUpload custList = formRun.control(formRun.controlId(#fileUpload));
FileUploadTemporaryStorageResult custListUploadResult = custList.getFileUploadResult();
if (custListUploadResult != null && custListUploadResult.getUploadStatus())
{
contract.parmCustList(custListUploadResult.pack());
}
this.setDialogOkButtonEnabled(formRun, true);
}
/// <summary>
/// Additional logic which is executed once the upload of the file has started.
/// </summary>
private void uploadStarted()
{
FormRun formRun = this.dialog().dialogForm().formRun();
this.setDialogOkButtonEnabled(formRun, false);
}
/// <summary>
/// Enables or disables the OK button.
/// </summary>
/// <param name = "_formRun">Dialog form instance</param>
/// <param name = "_isEnabled">True if OK button should be enabled, false if shouldn't.</param>
private void setDialogOkButtonEnabled(FormRun _formRun, boolean _isEnabled)
{
FormControl okButtonControl = _formRun.control(_formRun.controlId("CommandButton"));
if (okButtonControl)
{
okButtonControl.enabled(_isEnabled);
}
}
/// <summary>
/// Adds event subscriptions.
/// </summary>
public void postRun()
{
super();
FormRun formRun = this.dialog().dialogForm().formRun();
this.dialogEventsSubscribe(formRun);
this.setDialogOkButtonEnabled(formRun, false);
}
}
Controller class:
/// <summary>
/// Controller class of file uploader dialog.
/// </summary>
final class ImportDialogController_DV extends SysOperationServiceController
{
protected void new()
{
super();
this.parmClassName(classStr(ImportDialogService_DV));
this.parmMethodName(methodStr(ImportDialogService_DV, processOperation));
}
/// <summary>
/// Method which is run while calling the corresponding menu item
/// </summary>
/// <param name = "args">Arguments passed from the menu item</param>
public static void main(Args args)
{
ImportDialogController_DV controller;
controller = new ImportDialogController_DV();
controller.parmLoadFromSysLastValue(false);
controller.startOperation();
}
/// <summary>
/// Gets or sets the caption of the dialog
/// </summary>
/// <param name = "_dialogCaption">The caption to set for the dialog</param>
/// <returns>The caption of the dialog</returns>
public LabelType parmDialogCaption(LabelType _dialogCaption = dialogCaption)
{
LabelType ret;
ret = super(_dialogCaption);
ret = "Customer list import";
return ret;
}
}
Service class:
/// <summary>
/// Service class with file handling and data insertion logic.
/// </summary>
final class ImportDialogService_DV extends SysOperationServiceBase
{
#Define.separator(',')
/// <summary>
/// The code that processes the file
/// </summary>
/// <param name = "_contract">Instance of the <c>ImportDialogContract_DV</c> class</param>
public void processOperation(ImportDialogContract_DV _contract)
{
FileUploadTemporaryStorageResult fileUploadResult = new FileUploadTemporaryStorageResult();
System.IO.Stream readStream;
System.IO.StreamReader sr;
CustTable custTable;
InteropPermission interopPermission;
str srLine;
container line;
List lineList;
RecordInsertList recordInsertList;
if (_contract.parmCustList() != conNull())
{
fileUploadResult.unpack(_contract.parmCustList());
readStream = File::UseFileFromURL(fileUploadResult.getDownloadUrl());
sr = new System.IO.StreamReader(readStream, System.Text.Encoding::GetEncoding(1250));
lineList = new List(Types::AnyType);
if(sr.Peek() == -1)
{
return;
}
interopPermission = new InteropPermission(InteropKind::ClrInterop);
interopPermission.assert();
srLine = sr.ReadLine();
while(!System.String::IsNullOrEmpty(srLine))
{
lineList = strSplit(srLine, #separator);
line = list2Con(lineList);
if(!line)
{
continue;
}
custTable.clear();
custTable.AccountNum = conPeek(line, 1);
custTable.CustGroup = conPeek(line, 2);
custTable.Currency = conPeek(line, 3);
custTable.insert(DirPartyType::None, conPeek(line, 4));
custTable.initValue();
srLine = sr.ReadLine();
}
}
}
}
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 “Browse” button.
You can read more about SysOperationFramework on the following link: SysOperation FrameWork in D365 for Operations – TheDynamicsDrive (wordpress.com).