Client Requirement is to get a single PDF file of random selection of invoices.
//Create a Project with C# class Library from VS and use below code
//Code for Uploading Merged PDFs to Azure blob
Note: Need to take reference of Azure storage to use Azure Libraries or else throws error.
Create new AX project
//Create Dialog for selecting Invoices, create Report Bytes and upload to Azure Blob
Note: Add reference from above project to Ax project using path - AXproject->add references->Select reference of above created class. Also you need to take PDFSharp library reference, which is used to merge PDFs.
Reference Links: http://www.meritsolutions.com/microsoft-dynamics-365/render-report-memory-stream-d365-aka-ax7/
http://axaptamasters.com/print-multiple-invoices-one-pdf-file-ax7/
https://dynamicsaxgyan.wordpress.com/?s=Tutorial_LookUpMultiSelectDialog
http://dev.goshoom.net/en/2016/03/file-upload-and-download-in-ax-7/
http://daxtechies.blogspot.in/2017/07/dynamics-365-for-operations-pack-your.html
//Create a Project with C# class Library from VS and use below code
//Code for Uploading Merged PDFs to Azure blob
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using System.IO;
//using
Microsoft.ServiceBus;
//using
Microsoft.ServiceBus.Messaging;
namespace InvoiceBatchCopyToBlob
{
public class UploadFileStream
{
public void
printPaymentFile(byte[]
fileStream, string
_blobReference)
{
CloudStorageAccount storageAccount =
CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=*****;AccountKey=********;EndpointSuffix=core.windows.net");
//CloudConfigurationManager.GetSetting("StorageConnectionString"));
// Create the
blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve a
reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference("filestore");
// Retrieve
reference to a blob named "myblob".
CloudBlockBlob blockBlob = container.GetBlockBlobReference(_blobReference);
// Create or
overwrite the "myblob" blob with contents from a local file.
blockBlob.UploadFromByteArray(fileStream, 0, fileStream.Length);
//this.triggerServiceBus();
}
}
}
Add reference path- C# Class library Project -> Add references -> Manage Nuget packages-> Microsoft Azure.Storage-> Install. Once you install it will create a dll file in your bin folder of project.
Note: Add reference from above project to Ax project using path - AXproject->add references->Select reference of above created class. Also you need to take PDFSharp library reference, which is used to merge PDFs.
using CGlInvoiceBatchCopyToBlob;
public class CGLInvoiceBatchProcess extends Runbase
{
DialogRunbase dialog;
DialogGroup dialogGrp;
AccountNum accountNum;
InvoiceId invoiceId;
FormBuildStringControl
fbCtrlCustAccount, fbCtrlInvoice;
FormStringControl
ctrlCustAccount, ctrlInvoice;
container conCustAccount, conInvoice;
SysLookupMultiSelectCtrl
msCustAccount, msInvoice;
///
<summary>
///
///
</summary>
///
<returns></returns>
public Object
dialog()
{
FormBuildControl
formBuildControl;
dialog =
super();
dialog.alwaysOnTop(true);
dialog.windowType(FormWindowType::Standard);
dialogGrp =
dialog.addGroup("Select Invoices");
formBuildControl =
dialog.formBuildDesign().control(dialogGrp.formBuildGroup().id());
fbCtrlInvoice = formBuildControl.addControl(FormControlType::String,
identifierStr(invoiceId));
fbCtrlInvoice.label("Invoices");
dialog.allowUpdateOnSelectCtrl(true);
this.dialogSelectCtrl();
return dialog;
}
///
<summary>
///
///
</summary>
/// <param name
= "dialog"></param>
public void
dialogPostRun(DialogRunbase _dialog)
{
FormRun formRun;
Query query;
QueryBuildDataSource qbds,
qbdsJ, qbdsT;
QueryBuildRange qbr;
SysTableLookup sysLookup
= new SysTableLookup();;
super(dialog);
CGLInvoiceBatchProcess process = new CGLInvoiceBatchProcess();
formRun =
_dialog.dialogForm().formRun();
if (formRun)
{
ctrlInvoice =
formRun.design().control(fbCtrlInvoice.id());
msInvoice =
SysLookupMultiSelectCtrl::construct(formRun, ctrlInvoice,
querystr(CglInvoiceBatchDialogInvQuery), false, [tableNum(CustInvoiceJour),
fieldNum(CustInvoiceJour, invoiceId)]);
}
}
///
<summary>
///
///
</summary>
///
<returns></returns>
public boolean
getFromDialog()
{
#Characters
conInvoice = msInvoice.getSelectedFieldValues();
info("Control 2 – " +
con2StrUnlimited(conInvoice,#SEMICOLON));
this.getReportBytes(conInvoice);
return true;
}
///
<summary>
///
///
</summary>
/// <param name
= "_args"></param>
public static void
main(Args _args)
{
CGLInvoiceBatchProcess
cglInvoiceBatchProcess = new CGLInvoiceBatchProcess();
//Select
Invoices dialog prompt
if(cglInvoiceBatchProcess.prompt())
{
cglInvoiceBatchProcess.run();
}
}
///
<summary>
///
///
</summary>
public void
getReportBytes(container _container)
{
DocuRef addedRecord;
Filename fileName =
"AbcTest.pdf";
SalesInvoiceController controller = new
SalesInvoiceController();
SalesInvoiceContract contract = new SalesInvoiceContract();
SRSPrintDestinationSettings
settings;
Array arrayFiles;
System.Byte[]
reportBytes = new System.Byte[0]();
System.Byte[]
reportBytesUpload = new System.Byte[0]();
SRSProxy srsProxy;
SRSReportRunService
srsReportRunService = new SrsReportRunService();
Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[] parameterValueArray;
Map
reportParametersMap;
SRSReportExecutionInfo
executionInfo = new SRSReportExecutionInfo();
Str strReport;
int i,j;
Container conBytes;
Args _args = new Args();
CustInvoiceJour
custInvoiceJour;
str blobReference;
//UploadFileStream uploadStream
= new UploadFileStream();
//Get report
bytes for selected invoices
for (i = 1;
i<=conLen(_container);i++)
{
// Provide
all the parameters to a contract
custInvoiceJour.clear();
select
InvoiceId, RecId from custInvoiceJour where custInvoiceJour.InvoiceId ==
conPeek(_container, i);//'6004785Z-1';
contract.parmRecordId(custInvoiceJour.RecId);
// Provide
details to controller and add contract
controller.parmArgs(_args);
controller.parmReportName(ssrsReportStr(SalesInvoice,
ReportCGL_OrgWithLogo));
controller.parmShowDialog(false);
controller.parmLoadFromSysLastValue(false);
controller.parmReportContract().parmRdpContract(contract);
// Provide
printer settings
settings =
controller.parmReportContract().parmPrintSettings();
settings.printMediumType(SRSPrintMediumType::File);
settings.fileName(fileName);
settings.fileFormat(SRSReportFileFormat::PDF);
// Below
is a part of code responsible for rendering the report
controller.parmReportContract().parmReportServerConfig(SRSConfiguration::getDefaultServerConfiguration());
controller.parmReportContract().parmReportExecutionInfo(executionInfo);
srsReportRunService.getReportDataContract(controller.parmreportcontract().parmReportName());
srsReportRunService.preRunReport(controller.parmreportcontract());
reportParametersMap =
srsReportRunService.createParamMapFromContract(controller.parmReportContract());
parameterValueArray =
SrsReportRunUtil::getParameterValueArray(reportParametersMap);
srsProxy =
SRSProxy::constructWithConfiguration(controller.parmReportContract().parmReportServerConfig());
// Actual
rendering to byte array
reportBytes =
srsproxy.renderReportToByteArray(controller.parmreportcontract().parmreportpath(),
parameterValueArray,
settings.fileFormat(),
settings.deviceinfo());
blobReference =
"Customer-" +custInvoiceJour.OrderAccount;
//Upload
report byte to Blob container
//uploadStream.printPaymentFile(reportBytes, blobReference);
strReport
= System.Convert::ToBase64String(reportBytes);
conBytes
+= strReport;
//info(strReport);
}
//Merge PDFs
this.mergePDFs(conBytes, blobReference);
}
///
<summary>
///
///
</summary>
public void mergePDFs(container _con, str
blobReference)
{
PdfSharp.Pdf.PdfDocument outPutPDFDocument = new PdfSharp.Pdf.PdfDocument();
PdfSharp.Pdf.PdfDocument
inputPDFDocument = new
PdfSharp.Pdf.PdfDocument();
PdfSharp.Pdf.PdfPages
pdfPages ;
PdfSharp.Pdf.PdfPage page;
System.IO.MemoryStream mergedFileStream = new System.IO.MemoryStream() ;
int i, j, pageCount;
FileName pdfFile;
InteropPermission
permission;
str errorMessage;
UploadFileStream
uploadStream = new UploadFileStream();
str tempDir = "K:\\tempDir";
try
{
permission
= new InteropPermission(InteropKind::ClrInterop);
permission.assert();
for (i =
1; i <= conLen(_con); i++)
{
System.Byte[]
reportByte;
System.IO.MemoryStream stream;
reportByte =
System.Convert::FromBase64String(conPeek(_con,i));
stream = new
System.IO.MemoryStream(reportByte);
//pdfFile = conPeek(_con,i);
inputPDFDocument = PdfSharp.Pdf.IO.PdfReader::Open(stream
,PdfSharp.Pdf.IO.PdfDocumentOpenMode::Import);
outputPDFDocument.set_Version(inputPDFDocument.get_Version());
pageCount =
inputPDFDocument.get_PageCount();
pdfPages =
inputPDFDocument.get_Pages();
if
(pageCount > 0)
{
for (j = 0 ; j < pageCount; j++)
{
page = pdfPages.get_item(j);
outputPDFDocument.AddPage(page);
}
}
}
//System.IO.Directory::CreateDirectory(tempDir);
outputPDFDocument.Save(mergedFileStream, false);
//System.Byte[] outBytes = mergedFileStream.ToArray();
//mergedFileStream = new System.IO.MemoryStream(outBytes);
CodeAccessPermission::revertAssert();
}
catch(Exception::CLRError)
{
// Get the
CLR error before any other CLR operation
errorMessage = AifUtil::getClrErrorMessage();
CodeAccessPermission::revertAssert();
throw
error(errorMessage);
}
//Upload
mergedFileStream to Azure Blob
uploadStream.printPaymentFile(mergedFileStream, blobReference);
/* If you want to store the file in local machine and for Popup to Open/Save/Saveas Option
/* If you want to store the file in local machine and for Popup to Open/Save/Saveas Option
str
fileUrl;
FileUploadTemporaryStorageStrategy fileUploadStrategy = new FileUploadTemporaryStorageStrategy();
FileUploadTemporaryStorageResult result = fileUploadStrategy.uploadFile(mergedFileStream, "Test", "", ".pdf") as FileUploadTemporaryStorageResult;
if (result && result.getUploadStatus())
{
fileUrl = result.getDownloadUrl();
info(fileUrl);
new Browser().navigate(fileUrl);
}
*/
}
}
Reference Links: http://www.meritsolutions.com/microsoft-dynamics-365/render-report-memory-stream-d365-aka-ax7/
http://axaptamasters.com/print-multiple-invoices-one-pdf-file-ax7/
https://dynamicsaxgyan.wordpress.com/?s=Tutorial_LookUpMultiSelectDialog
http://dev.goshoom.net/en/2016/03/file-upload-and-download-in-ax-7/
http://daxtechies.blogspot.in/2017/07/dynamics-365-for-operations-pack-your.html
This comment has been removed by the author.
ReplyDeleteHello,
ReplyDeleteI am getting error of io stream is not readable.
Please suggest.
Ax Technical: Render Report To Bytes/Memory Stream In D365, Merge Pdfs And Copy To Azure Or In Local Machine >>>>> Download Now
ReplyDelete>>>>> Download Full
Ax Technical: Render Report To Bytes/Memory Stream In D365, Merge Pdfs And Copy To Azure Or In Local Machine >>>>> Download LINK
>>>>> Download Now
Ax Technical: Render Report To Bytes/Memory Stream In D365, Merge Pdfs And Copy To Azure Or In Local Machine >>>>> Download Full
>>>>> Download LINK 1H