Print SSRS report from C# code outside of Epicor

Also, you are using SubmitToAgent and then immediately checking for the report, instead of waiting for it.
Use RunDirect. Then it should be available when RunDirect Completes.

1 Like

And if you keep using the dlls, you’ll need to remember to update them at every client update!

There is a few things more wrong with that code above too. :thinking:

I do this via REST.

private static bool TryDownloadingJobSSRS(string jobNum, int numCopies, string reportStyleID, string printerName, string suffix)
        {
            var reportGUID = Guid.NewGuid().ToString();
            var pData = new
            {
                ds = new
                {
                    JobTravParam = new[]
                    {
                        new
                        {
                            PrntAllMassPrnt = false,
                            Jobs = jobNum,
                            Assembly = "0",
                            ReportStyleNum = reportStyleID,
                            AutoAction = "SSRSPREVIEW",
                            SSRSRenderFormat = "PDF",
                            TaskNote = reportGUID,
                            ShpSchd = true,
                            BarCodes = true,
                        },
                    },
                },
            };
            var pdfFileName = $@"{Settings.Default.TempPDFLocation}{jobNum}{suffix}.pdf";
            EpicorRest.DynamicPost("Erp.RPT.JobTravSvc", "RunDirect", pData);
            if (EpicorRest.LastCallResult != System.Net.HttpStatusCode.OK)
            {
                Log.Error($"[{jobNum}] FAILED TO GENERATE REPORT. See error:");
                Log.Error(EpicorRest.LastCallErrorMessage);
                critialErrors += 1;
                return false;
            }

            var reports = EpicorRest.DynamicGet("BaqSvc", "Production-DownloadTravRpt", new Dictionary<string, string>() { { "GUID", reportGUID } });
            if (EpicorRest.LastCallResult != System.Net.HttpStatusCode.OK)
            {
                Log.Error($"[{jobNum}] FAILED TO DOWNLOAD REPORT. See error:");
                Log.Error(EpicorRest.LastCallErrorMessage);
                critialErrors += 1;
                return false;
            }
            else if (reports["value"].Count <= 0)
            {
                Log.Error($"[{jobNum}] ERROR: BAQ 'Production-DownloadTravRpt' returned no results, so no report could be downloaded.");
                critialErrors += 1;
                return false;
            }

            try
            {
                File.WriteAllBytes(pdfFileName, Convert.FromBase64String(reports["value"].Last.SysRptLst_RptData.ToString()));
                return true;
            }
            catch (Exception e)
            {
                Log.Error($"[{jobNum}]: Could not save report pdf. File path: {pdfFileName}");
                Log.Error($"[{jobNum}]: Error: {e}");
                critialErrors += 1;
                return false;
            }
        }

BAQ is simple:

2 Likes

You’re code is formatted like Picasso having a stroke, but it’s clean and I like it. :rofl:

1 Like

I think it just didn’t copy from visual studio well, if you mean the indentation.

Our prod server has a self-signed SSL certificate so it’s not ready for REST. I was working on that on our test server and in the process of converting this entire WinForms app to REST when this new request came up. I will see if I can get one of the other suggestions working but this will be the final solution.
Thanks for your time, Mark!
Kelly

I’ve just about got your original code fixed up.

I will try your suggestions and report back.
Thanks Kevin!

If you hold on, I fixed it for you :rofl:

Thanks Evan for sharing your code! I will definitely come back to this when we get our prod server REST ready.
Kelly

private void PrintDD250(int packNum, int styleNum)
{
    try
    {
		//Easy to find
		string reportTaskNote = Guid.NewGuid().ToString();

        PackingSlipPrintAdapter adpPackSlip = new PackingSlipPrintAdapter(EpiUser.EpiLaunch);
        adpPackSlip.BOConnect();

        adpPackSlip.GetNewParameters();

		Erp.Rpt.PackingSlipPrintDataSet.PackingSlipParamRow psParam = adpPackSlip.ReportData.PackingSlipParam[0];

        psParam.PackNum = packNum;
        psParam.AutoAction = "SSRSPREVIEW";
        psParam.SSRSRenderFormat = "PDF";
        psParam.AgentID = "System Task Agent";
        psParam.ReportStyleNum = styleNum;
        psParam.ProcessTaskNum = 0;
        psParam.RowMod = "A";
		psParam.TaskNote = reportTaskNote; //Magic

        adpPackSlip.RunDirect();

        SysMonitorAdapter adpSysMonitor = new SysMonitorAdapter(EpiUser.EpiLaunch);
        adpSysMonitor.BOConnect();

		//Find the one with our reporTaskNote from above
        SearchOptions opts = new SearchOptions(SearchMode.AutoSearch);
		opts.NamedSearch.WhereClauses.Add("SysTask", "TaskNote = '" + reportTaskNote + "'");

		using (ReportMonitorAdapter adpRptMon = new ReportMonitorAdapter(EpiUser.EpiLaunch))
		{
			adpRptMon.BOConnect();

			SysMonitorTasksDataSet sysMonitorData = null;
	        if (adpRptMon.GetRowsKeepIdleTimeWithBallonInfo(opts, false, out sysMonitorData))
	        {
	            if (adpRptMon.ReportMonitorData.SysRptLst.Count > 0)
	            {
	                Byte[] returnRpt = adpRptMon.GetReportBytes(adpRptMon.ReportMonitorData.SysRptLst[0].SysRowID);
					if(returnRpt.Length > 0)
					{
						//PRINT HERE (The returnRpt Bytes is the pdf)
						MessageBox.Show(returnRpt.Length.ToString());
					}
	                
					adpRptMon.ReportMonitorData.SysRptLst[0].LastAction = "PREVIEW";
	                adpRptMon.Update();
	            }
	            else
	            {
	                Misc.TraceLog.Write(string.Format("ReportMonitor didn't find Rpt for PackNumber [{0}].", packNum));
	            }
	        }
	        else
	        {
	            Misc.TraceLog.Write(string.Format("ReportMonitor didn't find Rpt for PackNumber [{0}].", packNum));
	        }
		}
    }
    catch (Exception ex)
    {
        Misc.TraceLog.Write(string.Format("Exception caught trying to print DD 250 form for PackNumber [{0}]. Exception: {1}", packNum, ex.ToString()));
    }
}

TaskNote idea from @josecgomez

2 Likes

Thanks Kevin!
I’m still working on the PRINT HERE part. :wink:
I’ll report back soon.
Kelly

Kevin, I can’t thank you enough!
I saw your presentation at Insights this year in Vegas. Had I known you were going to rescue me with this golden code, I would have bought you that cigar you needed to complete your alter identity! :wink:
Thanks again,
Kelly

I just put together the pieces of what the greats before me have done :slight_smile:

To be honest, I’ve been needing to do this for a while for some stuff here at work, and
kept putting off learning it all. Your post was the push I needed to do that.

And those cigars were expensive, I would have appreciated it, but been a little miffed! :rofl:

Edit: How did you end up printing it? (Curiosity!)

Just to quickly test out the rest of the code, I used LPR. Need to discuss with my manager if we want to stick with that or use Adobe or an open source option.

                            Byte[] returnRpt = adpRptMon.GetReportBytes(adpRptMon.ReportMonitorData.SysRptLst[0].SysRowID);
                            if (returnRpt.Length > 0)
                            {
                                System.IO.File.WriteAllBytes(@"C:\Temp\report.pdf", returnRpt);
                                //Print Here
                                var command = @"%WINDIR%\Sysnative\lpr -S 10.31.45.4 -P ""DD250"" ""C:\Temp\report.pdf""";
                                ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", "/C " + command);
                                procStartInfo.RedirectStandardOutput = true;
                                procStartInfo.UseShellExecute = false;
                                procStartInfo.RedirectStandardError = true;
                                procStartInfo.CreateNoWindow = true;
                                Process proc = new Process();
                                proc.StartInfo = procStartInfo;
                                proc.Start();
                                proc.WaitForExit();
                                string cmdError = proc.StandardError.ReadToEnd();
                                string cmdOutput = proc.StandardOutput.ReadToEnd();
                                Misc.TraceLog.Write(string.Format("Report size: [{0}].", returnRpt.Length.ToString()));
                                Misc.TraceLog.Write(string.Format("cmdError: [{0}].", cmdError));
                                Misc.TraceLog.Write(string.Format("cmdOutput: [{0}].", cmdOutput));
                            }

Later when you upgrade, if you want to actually have Epicor print it, we could modify it to send it to the Edge Agent (Server Side), and have it take care of it.

I’m not familiar with that. I’ll have to do some research.

Hey @Evan_Purdy . Just want you to know how helpful your code is as I’m starting to convert this WinForms app to REST. My REST calls are slightly different since I need async but I definitely would’ve struggled more if I didn’t have your example to follow. I’m a bit of a lone ranger Epicor developer at my company so this forum has been invaluable to me. It’s pretty awesome that I got two solutions out of one question!
Thanks again for sharing your knowledge!
Kelly

2 Likes

main-qimg-9e040c60fdb3375f8cfaa77823a93589