How to stop printing error pages in ReportViewer using C# - c#

I have a master report file and a sub report file.
Master report file calls sub report file.
Let's have a look at the code first.
private void CreatePDF(string fileName)
{
try
{
// Variables
Warning[] warnings;
string[] streamIds;
string mimeType = string.Empty;
string encoding = string.Empty;
string extension = string.Empty;
string _strGijunMonth = DateTime.Parse(GijunMonth).ToString("yyyyMM");
byte[] bytes = null;
// Setup the report viewer object and get the array of bytes
ReportViewer viewer = new ReportViewer();
viewer.LocalReport.DataSources.Clear();
viewer.ProcessingMode = ProcessingMode.Local;
viewer.LocalReport.ReportEmbeddedResource = "MasterReport.rdlc";
viewer.LocalReport.EnableExternalImages = true;
DataTable _dt = base.GetDataTable(
"my_procedure"
, _strMainNo
);
_intTotalPage = _dt.Rows.Count * 2;
ReportDataSource _ds = new ReportDataSource();
_ds.Value = _dt;
_ds.Name = "SetData";
viewer.LocalReport.DataSources.Add(_ds);
// sub report event
viewer.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
// print
viewer.RefreshReport();
bytes = viewer.LocalReport.Render("PDF", null, out mimeType, out encoding, out extension, out streamIds, out warnings);
System.IO.FileStream newFile1 = new System.IO.FileStream(fileName, System.IO.FileMode.Create);
newFile1.Write(bytes, 0, bytes.Length);
newFile1.Close();
}
catch
{
throw;
}
}
void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
{
try
{
string MAINT_NO = e.Parameters["MAINT_NO"].Values[0];
string _strGijunMonth = DateTime.Parse(GijunMonth).ToString("yyyyMM");
// get sub report procedure
DataSet _dsCust_Info = base.GetDataSet(
"my_sub_procedure"
, MAINT_NO
, _strGijunMonth
);
----> by somehow, it should throw error. If so, I should not print error page to pdf.
}
catch (Exception err)
{
}
}
My application calls "CreatePDF" method with file name argument.
Let's say that I have to print to PDF 5 pages.
While calling LocalReport_SubreportProcessing event, some of sub reports have error value in data. So, I throw an error in LocalReport_SubreportProcessing event.
For example, when I say that there are 5 pages and only 1, 2, 3 and 5 pages are okay and the number 4 page should not be printed as PDF.
I wonder how I can delete PDF page which is already created by ReportViewer.
As you can see, LocalReport_SubreportProcessing event comes after creating PDF file.
Anyone has any idea to fix this problem?

Maybe reportViewer.CancelRendering(0);
when you detect an error?

Related

How to create PDF Report with data from code in list form, not directly from database with Microsoft Report Viewer

I am using Microsoft.Report.Viewer for generate PDF in my ASP .NET WEB API application. So far when my report get the data directly from database, there is no problem. The problem is, when I try to create a report with subreport within and the subreport data is got from code in a list form, I didn't get the expected result. What I do is create a report with subreport from this tutorial. But when I generate the PDF, what I get is this message .
Here is my code :
My Web API to generate the PDF :
[Route("GeneratePDFForDailyProgram")]
[HttpGet]
[AllowAnonymous]
public async Task<IHttpActionResult> GeneratePDFForDailyProgram(int id) {
string guid = Guid.NewGuid().ToString();
string fileName = string.Concat("Booking_No" + Convert.ToString(id) + "_" + guid.ToUpper() + ".pdf");
string filePath = HttpContext.Current.Server.MapPath("~/Content/Temp/" + fileName);
string name = Request.RequestUri.GetLeftPart(UriPartial.Authority) + System.Configuration.ConfigurationManager.ConnectionStrings[System.Configuration.ConfigurationManager.AppSettings["CUSTOMPORT"]];
string name2 = Request.GetRequestContext().VirtualPathRoot;
List<TourDestination> destination = new List<TourDestination>();
TourTransactionSummaryViewModel summaryViewModel = new TourTransactionSummaryViewModel();
try {
//summaryViewModel = await CalcSummaryViewModel(transaction, summaryViewModel, db);
summaryViewModel.DailyPrograms = DailyProgram(id);
destination = TourDestination(summaryViewModel.DailyPrograms);
List < Movement > movementList = summaryViewModel.DailyPrograms.FirstOrDefault().Movements.ToList();
Reports.ReportGenerator.GeneratePDFForDailyProgram(summaryViewModel.DailyPrograms, destination, filePath);
//await Reports.ReportGenerator.GeneratePDFForMovement(movementList, filePath);
HttpResponseMessage result = null;
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(filePath, FileMode.Open));
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = fileName;
result.Dispose();
string convertedFilePath = filePath.Replace(#"\\", #"\");
} catch (Exception ex) {
return BadRequest(ex.Message);
}
return Ok(name + name2 + "/Content/Temp/" + fileName);
}
As you can see from the code above, I use GeneratePDFForDailyProgram method to generate the PDF.
Here my GeneratePDFForDailyProgram method :
public static bool GeneratePDFForDailyProgram(TourTransactionSummaryViewModel.DailyProgram[] dailyPrograms, List<TourDestination> destination , string filePath) {
try {
string binPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "bin");
var assembly = Assembly.Load(System.IO.File.ReadAllBytes(binPath + "\\TripPlannerAPI.dll"));
using (Stream stream = assembly.GetManifestResourceStream(DailyProgramReport)) {
var viewer = new ReportViewer();
viewer.LocalReport.EnableExternalImages = true;
viewer.LocalReport.LoadReportDefinition(stream);
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string filenameExtension;
viewer.LocalReport.SubreportProcessing += new Microsoft.Reporting.WebForms.SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
viewer.LocalReport.DataSources.Add(new ReportDataSource("DailyProgram", dailyPrograms));
byte[] bytes = viewer.LocalReport.Render(
"PDF", null, out mimeType, out encoding, out filenameExtension,
out streamids, out warnings);
using (FileStream fs = new FileStream(filePath, FileMode.Create)) {
fs.Write(bytes, 0, bytes.Length);
fs.Flush();
}
stream.Flush();
}
} catch (Exception ex) {
return false;
}
return true;
}
To run the SubReport, I use the eventhandler code :
private static void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e) {
DateTime movementDate = Convert.ToDateTime(e.Parameters[0].Values[0]);
TourTransactionsController controller = new TourTransactionsController();
var movement = controller.Movements();
List<Movement> movementList = new List<Movement>();
movementList.Add(new Movement {
Destination = "TEST",
MovementDescription = "TEST",
DateTime = Convert.ToDateTime("2017-09-25") //HARDCODE FOR TEST
});
e.DataSources.Clear();
e.DataSources.Add(new Microsoft.Reporting.WebForms.ReportDataSource() {
Name = "DSMovements",
Value = movementList
});
//throw new NotImplementedException();
}
What I did try :
Check the sub report name, and change it from report name to report file url. Still get the same message.
Generate the Sub Report directly, not from the main report. The subreport is successfully generated.
PS : When I debug my code, and put a breakpoint in my event handler LocalReport_SubreportProcessing the breakpoint is not hitting while debugging
My Questions are :
Why my breakpoint on the eventhandler is not hitting while debugging ?
Is it possible that eventhandler which is not hitting while debugging, could be the reason I got the message The subreport 'MovementReport' could not be
found at the specified location MovementReport.
Please verify that the subreport has been
published and that the name is correct. ?
Is there any other way for me to create a main report with data from db, and the subreport with data from code in list form ?
Any help is appreciated.

Displaying Images(from folder) and tables(from database) In the same Crystal Report

I am using VS2010(winform), and Access database ,In my crystal report I am successfully showing tables from database by creating DataSetPatient.xsd file and using below code ,now I want to display Images from the particular folder/folder path into same report ,as I am new to crystal reports please can anyone show me step by step how can I do this
public partial class ViewR : Form
{
DBHandling db=new DBHandling();
public ViewR()
{
InitializeComponent();
}
private void ViewR_Load(object sender, EventArgs e)
{
CrystalReportP objRpt;
// Creating object of our report.
objRpt = new CrystalReportP();
DataSetPatient ds = new DataSetPatient(); // .xsd file name
DataTable dt = DBHandling.GetPatient();
ds.Tables[0].Merge(dt);
objRpt.SetDataSource(ds);
crystalReportViewer1.ReportSource = objRpt;
}
}
Try this way
First: created a New Column name ("Image") in a datatable of the dataset and change the DataType to System.Byte()
second: Read Image File Convert into Binary array and store it into your data table,
third : now you data table has Data from database and Image data from Path image , assign this datatable to database, and Report Source :
code:
private void ViewR_Load(object sender, EventArgs e)
{
CrystalReportP objRpt;
// Creating object of our report.
objRpt = new CrystalReportP();
DataSetPatient ds = new DataSetPatient(); // .xsd file name
DataTable dt = DBHandling.GetPatient();
dt = GetImageRow(dt, "YourImageName.Jpg");
ds.Tables[0].Merge(dt);
objRpt.SetDataSource(ds);
crystalReportViewer1.ReportSource = objRpt;
}
//By this Function You can Append Your Image to Datatable
private DataTable GetImageRow(DataTable dt, string ImageName)
{
try
{
FileStream fs;
BinaryReader br;
if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + ImageName))
{
fs = new FileStream(AppDomain.CurrentDomain.BaseDirectory + ImageName, FileMode.Open);
}
else
{
// if phot does not exist show the nophoto.jpg file
fs = new FileStream(AppDomain.CurrentDomain.BaseDirectory + "nophoto.jpg", FileMode.Open);
}
// initialise the binary reader from file streamobject
br = new BinaryReader(fs);
// define the byte array of filelength
byte[] imgbyte = new byte[fs.Length + 1];
// read the bytes from the binary reader
imgbyte = br.ReadBytes(Convert.ToInt32((fs.Length)));
dt.Rows[0]["Image"] = imgbyte;
br.Close();
// close the binary reader
fs.Close();
// close the file stream
}
catch (Exception ex)
{
// error handling
MessageBox.Show("Missing " + ImageName + "or nophoto.jpg in application folder");
}
return dt;
// Return Datatable After Image Row Insertion
}
Note: first: Here I take path as Application Statrup path , you can take any path you want.
Second: this is runTime Image loading ,
third: here i also Explain how to convert image into byte array so, it will useful when you want to store your image in database

Multithreading RDLC report not refreshing

Gurus
We are developing a win forms application in .NET 4.0, that generate PDF reports using RDLC control. As the report generation takes lot of time, we decided to implement Parallel for each.. With the following code , it generates the PDF for first record after that, system just hangs.. Do help us...
public void generatereport()
{
button1.Enabled = false;
button4.Enabled = false;
DataTable dtBranch = new DataTable();
dtBranch = getBranchNo(); -- we might get around 300 rows here
try
{
Parallel.ForEach(dtBranch.AsEnumerable(), drow =>
{
// Shows the ReportData along with the branch code
reportdate = drow["reportdate"].ToString();
string branchName = drow["BranchNo"].ToString();
ProcessReport(branchName);
});
reportViewer2.Visible = false;
button1.Enabled = true;
button4.Enabled = true;
lblMsg.Text = "Branch Summary Generated at '" + #fullpath + "'";
}
catch (AggregateException e)
{
//Console.Write(e.Data + e.Message);
//Console.ReadLine();
}
}
private void ProcessReport(string branName)
{
if (reportViewer2.InvokeRequired)
{
ProcessReportCallBack d = new ProcessReportCallBack(ProcessReport);
Invoke(d, new object[] { branName });
}
else
{
log.Debug("branch" + DateTime.Now.ToString());
DataTable dt = new DataTable();
dt = getReportOrderNoBasedonBranchID(branName);//Get all the report order no as per the branch id
this.sp_getReportOrderNoTableAdapter.Fill(this.getRptNo.sp_getReportOrderNo, branName);
this.reportViewer2.LocalReport.SubreportProcessing += new Microsoft.Reporting.WinForms.SubreportProcessingEventHandler(this.reportViewer2_Subreport1);
this.reportViewer2.Clear();
this.reportViewer2.ProcessingMode = ProcessingMode.Local;
this.reportViewer2.LocalReport.ReportPath = #"Master.rdlc";
this.reportViewer2.Refresh();
Savepdf("reportViewer2", branName + "_" + reportdate);
}
}
In save PDF we are generating the PDF report..
byte[] bytes = null;
bytes = reportViewer2.LocalReport.Render(
"PDF", null, out mimeType, out encoding,
out extension,
out streamids, out warnings);
filename = BranchName + '_' + "Summary" + ".pdf";
using (FileStream fs = new FileStream(#fullpath + '\\' + filename, FileMode.Create))
{
fs.Write(bytes, 0, bytes.Length);
fs.Close();
}
bytes = null;
Kindly provide your feedback
you don't need a sample codes to Export to PDF, when the RDLC is already rendered to the ReportViewer try to find this icon from the ToolBars of ReportViewer Control:
EDIT:
Save RDLC reports as PDF programaticaly
public void Save(ReportViewer viewer, string savePath)
{
byte[] Bytes = viewer.LocalReport.Render("PDF", "", null, null, null, null, null);
using (FileStream Stream = new FileStream(savePath, FileMode.Create)) {
Stream.Write(Bytes, 0, Bytes.Length);
}
}

The report definition for report ' ' has not been specified

i am developing web application, in my app i have to print rdlc without preview.my code is following
LocalReport report = new LocalReport();
report.ReportEmbeddedResource = "TCESS.ESales.CommonLayer.Reports.HandlingBillReport.rdlc";
report.ReportPath="TCESS.ESales.CommonLayer.Reports.HandlingBillReport.rdlc";
SettlementOfAccountsDTO objSettlementOfAccountsDTO = ESalesUnityContainer.Container.Resolve<ISettlementOfAccountsService>().GetSettlementOfAccountsByAccId(32);
if (objSettlementOfAccountsDTO.Account_Id > 0)
{
SetReportParametersForBill(objSettlementOfAccountsDTO, AccountReportViewer, report);
}
Export(report);
m_currentPageIndex = 0;
Print();
private Stream CreateStream(string name, string fileNameExtension, Encoding encoding,
string mimeType, bool willSeek)
{
Stream stream = new FileStream(name + "." + fileNameExtension, FileMode.Create);
m_streams.Add(stream);
return stream;
}
private void Export(LocalReport report)
{
string deviceInfo =
"<DeviceInfo>" +
" <OutputFormat>EMF</OutputFormat>" +
" <PageWidth>8.5in</PageWidth>" +
" <PageHeight>11in</PageHeight>" +
" <MarginTop>0.25in</MarginTop>" +
" <MarginLeft>0.25in</MarginLeft>" +
" <MarginRight>0.25in</MarginRight>" +
" <MarginBottom>0.25in</MarginBottom>" +
"</DeviceInfo>";
Warning[] warnings;
m_streams = new List<Stream>();
report.Render("Image", deviceInfo, CreateStream, out warnings);
foreach (Stream stream in m_streams)
stream.Position = 0;
}
private void PrintPage(object sender, PrintPageEventArgs ev)
{
Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
ev.Graphics.DrawImage(pageImage, 0, 0);
m_currentPageIndex++;
ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
}
private void Print()
{
const string printerName = "\\\\193.168.0.20\\Printer_Q3";
if (m_streams == null || m_streams.Count == 0)
return;
PrintDocument printDoc = new PrintDocument();
printDoc.PrinterSettings.PrinterName = printerName;
if (!printDoc.PrinterSettings.IsValid)
{
string msg = String.Format("Can't find printer \"{0}\".", printerName);
Console.WriteLine(msg);
return;
}
int i=0;
foreach (Stream stream in m_streams)
{
Metafile pageImage = new Metafile(stream);
pageImage.Save(Server.MapPath("~/Images/"+i.ToString()+".jpg"));
i++;
}
//printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
//printDoc.Print();
}
i am getting error "The report definition for report ' ' has not been specified"
on line
report.Render("Image", deviceInfo, CreateStream, out warnings);
I just ran into this problem while instantiating a report to export and had to set this property like this:
wrvReport.LocalReport.ReportEmbeddedResource = "CommonLayer.Reports.SalesByPrice.rdlc";
The difference I see is the .LocalReport is the sub-property to set the embedded resource.
From MSDN:
An embedded report resource is a report definition that has been
stored as a resource in the calling assembly.
If the ReportPath property has been set, the ReportEmbeddedResource
property is ignored.
Therefore, setting the EmbeddedResource property is effectively doing nothing and your ReportPath is also failing because it expects a physical file system path.
I had the same problem. I solved it by setting "Copy to Output Directory = Copy if newer". Cheers.
I also had the same problem, that means that your code is not finding the rdlc file, you need to either use report.ReportEmbeddedResource or report.ReportPath. Looking at your code seems to me that you only need to use report.ReportEmbeddedResource, the other option is for a rdlc that is located in a specific location in your pc or in a network file system

Missing Subreports when RDLC is moved to server

I'm having a hard time getting a sub report to show up in my application using reportviewer. It works perfectly when debugging it locally. But when I upload it to the server, the sub reports are blank.
I've believe that SubreportProcessing event is not firing since I don't see the stored procedures getting fired from SQL Server Profiler. Here is my code that I'm using.
private void RunReport(string strFormat, int PlanID)
{
const string reportrdlc = "Reports\\Report_All_Sections.rdlc";
LocalReport report = new LocalReport {ReportPath = Server.MapPath(reportrdlc)};
report.SetBasePermissionsForSandboxAppDomain(new PermissionSet(PermissionState.Unrestricted));
report.DataSources.Clear();
report.SubreportProcessing += SetSubDataSource;
report.DataSources.Add(new ReportDataSource("DataSet_usp_GetSD", _wpt.Get_SD(PlanID).Copy()));
report.Refresh();
string mimeType;
string encoding;
string fileNameExtension;
string[] streams;
Warning[] warnings;
byte[] pdfContent = report.Render(strFormat, null, out mimeType, out encoding,
out fileNameExtension, out streams, out warnings);
System.IO.MemoryStream stream = new System.IO.MemoryStream(pdfContent);
Response.ContentType = strFormat == "EXCEL" ? "application/vnd.ms-excel" : "application/pdf";
Response.BinaryWrite(stream.ToArray());
Response.Flush();
Response.Close();
stream.Close();
}
public void SetSubDataSource(object sender, SubreportProcessingEventArgs e)
{
int PlanID = 1;
if (Request.QueryString["PlanID"] != null)
{
try
{
PlanID = Convert.ToInt32(Request.QueryString["PlanID"]);
}
catch (Exception Ex)
{
PlanID = 1;
}
}
switch (e.ReportPath)
{
case "Report_All_Mentor":
e.DataSources.Add(new ReportDataSource("DataSet_usp_GetMC", _wpt.Get_MC(PlanID).Copy()));
break;
case "Report_All_Intern":
e.DataSources.Add(new ReportDataSource("DataSet_usp_GetEA", _wpt.Get_EA(PlanID).Copy()));
break;
}
}
I seem to have the same issue. I believe that the problem is that when deployed reportPath contains the full path for the report, but when you are debugging locally it passes only the report name.
Is it possible that your SubreportProcessing event is indeed firing but in your switch statement non of the cases match the full path contained in the reportPath parameter.
I don't know how to resolve that but I think that might be the root cause.

Categories

Resources