Switching DataSources in ReportViewer in WinForms - c#

I have created a winform for the users to view view the many reports I am creating for them. I have a drop down list with the report name which triggers the appropriate fields to display the parameters. Once those are filled, they press Submit and the report appears. This works the first time they hit the screen. They can change the parameters and the ReportViewer works fine. Change to a different report, and the I get the following ReportViewer error:
An error occurred during local report processing.
An error has occurred during the report processing.
A data source instance has not been supplied for the data source "CgTempData_BusMaintenance".
As far as the process I use:
I set reportName (string) the physical RDLC name.
I set the dataSource (string) as the DataSource Name
I fill a generic DataTable with the data for the report to run from.
Make the ReportViewer visible
Set the LocalReport.ReportPath = "Reports\\" = reportName;
Clear the LocalReport.DataSources.Clear()
Add the new LocalReport.DataSources.Add(new ReportDataSource(dataSource, dt));
RefreshReport() on the ReportViewer.
Here is the portion of the code that setups up and displays the ReportViewer:
/// <summary>
/// Builds the report.
/// </summary>
private void BuildReport()
{
DataTable dt = null;
ReportingCG rcg = new ReportingCG();
if (reportName == "GasUsedReport.rdlc")
{
dataSource = "CgTempData_FuelLog";
CgTempData.FuelLogDataTable DtFuelLog = rcg.BuildFuelUsedTable(fromDate, toDate);
dt = DtFuelLog;
}
else if (reportName == "InventoryCost.rdlc")
{
CgTempData.InventoryUsedDataTable DtInventory;
dataSource = "CgTempData_InventoryUsed";
DtInventory = rcg.BuildInventoryUsedTable(fromDate, toDate);
dt = DtInventory;
}
else if (reportName == "VehicleMasterList.rdlc")
{
dataSource = "CgTempData_VehicleMaster";
CgTempData.VehicleMasterDataTable DtVehicleMaster = rcg.BuildVehicleMasterTable();
dt = DtVehicleMaster;
}
else if (reportName == "BusCosts.rdlc")
{
dataSource = "CgTempData_BusMaintenance";
dt = rcg.BuildBusCostsTable(fromDate, toDate);
}
// Setup the DataSource
this.reportViewer1.Visible = true;
this.reportViewer1.LocalReport.ReportPath = "Reports\\" + reportName;
this.reportViewer1.LocalReport.DataSources.Clear();
this.reportViewer1.LocalReport.DataSources.Add(new ReportDataSource(dataSource, dt));
this.reportViewer1.RefreshReport();
}
Any ideas how to remove all of the old remaining data? Do I dispose the object and recreate it?

I figured it out. I needed to add: reportViewer1.Reset(); to the beginning of the method.

Related

How to set database name dynamically for a crystal report using C#?

I have a C# windows application in which there are many crystal reports.I call and show them using the following piece of code :
rptDDCollection rpt = new rptDDCollection();
rpt.SetDatabaseLogon(Connect.sDatabaseUserName, DLL.Connect.sDatabasePassword, "", Connect.sCurrentDatabase);
rpt.RecordSelectionFormula = "";
frmReports frm = new frmReports();
frm.crViewer1.DisplayGroupTree = false;
frm.crViewer1.ReportSource = rpt;
frm.crViewer1.SelectionFormula = rpt.RecordSelectionFormula;
frm.crViewer1.Show();
frm.Show();
Now, the issue is that I have 2 databases to work on.Things work fine with one database.I have to use the same report but very often I need to view data from the other database.The database engine is SQL server.While searching on the net and on stack overflow, I found suggestions to set the database name dynamically through code.What should be done to achieve what I want in this case?
I worked this around by setting database name for the tables in the report.I made one change in the actual code above.I created a method called ApplyLogonInfo and passed the report object to it.Inside the method I wrote the code for setting database name for the report tables dynamically.This is the modified code:
rptDDCollection rpt = new rptDDCollection();
rpt.SetDatabaseLogon(Connect.sDatabaseUserName, DLL.Connect.sDatabasePassword, "", Connect.sCurrentDatabase);
ApplyLogOnInfo(rpt);
rpt.RecordSelectionFormula = "";
frmReports frm = new frmReports();
frm.crViewer1.DisplayGroupTree = false;
frm.crViewer1.ReportSource = rpt;
frm.crViewer1.SelectionFormula = rpt.RecordSelectionFormula;
frm.crViewer1.Show();
frm.Show();
Below is the newly created method:
public static void ApplyLogOnInfo(ReportClass rpt)
{
TableLogOnInfo info = new TableLogOnInfo();
info.ConnectionInfo.DatabaseName = Connect.sCurrentDatabase;
for (int i = 0; i < rpt.Database.Tables.Count; i++)
{
rpt.Database.Tables[i].ApplyLogOnInfo(info);
}
}
sCurrentDatabase is the name of the database that has been currently selected for viewing.
This enabled me to set the database name dynamically, and now I can work with 2 (or in general multiple) databases and view the data from whichever database I wish to see.

How do you pass data source to a local report when you use Navigation-> Go to report?

We are moving from Reporting Services remote to local,for this i've been converting the rdl files to rdlc successfully and changing the reportviewers to local processing and passing the data source via code like this:
ReportDataSource data = new ReportDataSource("PARAGAINSA", new InventarioRptCs().Selecciona_Saldos_Articulo(locid,
BodId,depid,FamId,NBid,imId,desde,hasta));
ReportViewer1.LocalReport.DataSources.Clear();
ReportViewer1.LocalReport.DataSources.Add(data);
ReportViewer1.LocalReport.Refresh();
Works great, i've also encounter some reports that have some subreports to pass the data source to the sub reports i've been doing it like this:
ReportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(SubReporteHandler);
private void SubReporteHandler(object sender, SubreportProcessingEventArgs e)
{
int im_id = Convert.ToInt32(e.Parameters[1].Values[0].ToString());
int loc_id = Convert.ToInt32(e.Parameters[0].Values[0]);
e.DataSources.Add(new ReportDataSource("PARAGAINSA", new InventarioRptCs().Selecciona_Saldos_Articulo_Det(loc_id,im_id)));
}
it also worked great, so i happily continue until i find a Report that has a subreport and the subreport has this in one of the fields:
when i click on the field that acts as the navigation link to the other report i get this
A data source instance has not been supplied for the data source 'datasource'.
so my question is: is there anyway i can pass the data source to the report inside the sub report that is been call via navigation -> go to report? if so how?
I am using VS 2013, with SQL server 2012
Thank you for reading, pardon my english not my first languague
Since i was not able to find another way to solve this i did the following to try and simulate the navigation between reports that is only available(to my knowledge) in processing mode remote,
First in the rdlc file i added 'Ver mas informacion' in the title property of the column that was acting as the link to the other report and set the Color to blue to give it a link style
i had to add the tooltip(rendes to title attribute) because i was not able to find another way to be able to select those specific cells that i wanted
then a css style to set the Cursor to pointer
[title="Ver mas informacion"] {
cursor:pointer;
}
then a script using jquery to handle the click event geting the values that i need as a parameter to the other report, navigate to the other report and pass the parameter via URL
$(window).load(function () {
$(document).on('click', '[title="Ver mas informacion"]', function () {
var locId = $('[id$="ddLocal"]').val();
var Fecha = $(this).parent().parent()[0].childNodes[2].childNodes[0].innerHTML;
var TT_Id = $(this).parent().parent()[0].childNodes[9].childNodes[0].innerHTML;
var Ap_Id = $(this).parent().parent()[0].childNodes[10].childNodes[0].innerHTML;
window.open(window.location.origin + config.base + '/Reportes/RptSubViewer.aspx?Sub=Doc&Loc=' + locId + '&Fecha=' + Fecha + '&AP=' + Ap_Id + '&TT_Id=' + TT_Id);
});
});
then over the other webform i only added a reportviewer and on the code behind
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (Request.QueryString["Sub"] == "Doc")
{
string _loc = Request.QueryString["Loc"];
string _fecha = Request.QueryString["Fecha"];
string _Ap_Id = Request.QueryString["AP"];
string _TT_Id = Request.QueryString["TT_Id"];
int loc_id = 0, TT_id = 0, Ap_Id = 0;
CultureInfo provider = new CultureInfo("en-US");
DateTime Fecha = DateTime.Now;
if (!string.IsNullOrEmpty(_loc))
loc_id = Convert.ToInt32(_loc);
if (!string.IsNullOrEmpty(_fecha))
Fecha = DateTime.ParseExact(_fecha,"dd/MMM/yyyy",provider);
if (!string.IsNullOrEmpty(_Ap_Id))
Ap_Id = Convert.ToInt32(_Ap_Id);
if (!string.IsNullOrEmpty(_TT_Id))
TT_id = Convert.ToInt32(_TT_Id);
if (TT_id == 14 || TT_id == 15 || TT_id == 21)
{
List<ReportParameter> paramList = new List<ReportParameter>();
paramList.Add(new ReportParameter("LocId", _loc));
paramList.Add(new ReportParameter("Fecha", Fecha.ToShortDateString()));
paramList.Add(new ReportParameter("TT_Id", _TT_Id));
paramList.Add(new ReportParameter("TT_Doc", _Ap_Id));
ReportDataSource data = new ReportDataSource("ARACLDS", new InventarioRptCs().Selecciona_Saldos_Articulo_Doc(loc_id, Fecha, TT_id, Ap_Id).ToList());
RVSubNav.LocalReport.ReportPath = "Rdlcs\\ReporteKardexDoc.rdlc";
RVSubNav.Visible = true;
RVSubNav.LocalReport.SetParameters(paramList);
RVSubNav.LocalReport.DataSources.Clear();
RVSubNav.LocalReport.DataSources.Add(data);
RVSubNav.LocalReport.Refresh();
}
}
}
}
not sure if the best way but it got the job done

dataGridView Row Filteration using NAV web services

I am trying to create a filterable data view of data which I get it through a web service in NAV 2009.
I created a windows form and pulled the essential data from a NAV page, created an array and showed in a dataGridView using web services.
What I need now, is to filter by row the data which I have in my dataGridView.
My code would be
private void LoadDataGrid()
{
WS_GLEntry_Service GLEntryService = new WS_GLEntry_Service();
GLEntryService.UseDefaultCredentials = true;
WS_GLEntry[] Entries = GLEntryService.ReadMultiple(null,null,0);
dataGridView1.DataSource = Entries;
(dataGridViewFields.DataSource as DataTable).DefaultView.RowFilter = string.Format("Field = '{0}'", textBox1.Text);
}
But in the last line of my code which contains dataGridViewFields is not in the context. If I want to modify my coding how should I do?
Thank you.
If you want to read filtered data why don't you use first parameter filterArray of ReadMultiple function which reads a filtered set of records
List<Customer_Filter> filterArray = new List<Customer_Filter>();
Customer_Filter nameFilter = new Customer_Filter();
nameFilter.Field = Customer_Fields.Name;
nameFilter.Criteria = "S*";
filterArray.Add(nameFilter);
Customer[] custList = service.ReadMultiple(filterArray.ToArray(), null, 100);
In other way, while publishing the page you can set the filter in page's SourceTableView property. This will gives only those fields which are follow the filter criteria.

How to Bind rdlc report using business object?

i have business object called "TeamMaster",
in which i define three properties,Id,Name & Flg.
in my .rdlc report i apply TeamMaster object as a data source,
now i write the following code in page load event of form in which i add report viewer control and i define my report as a local report.
using (RDLC_DEMO_DBEntities objdatabase = new RDLC_DEMO_DBEntities())
{
lstTeamMstr = objdatabase.TeamMasters.ToList();
}
this.TeamMasterBindingSource.DataSource = lstTeamMstr;
this.reportViewer1.RefreshReport();
when i check this code using debugging i get 6 records in TeamBindingSource,
but in windows report only displays six blank rows,
what is the problem?
Follow this code : >>
string path = HttpContext.Current.Server.MapPath(Your Report path);
ReportViewer1.Reset(); //important
ReportViewer1.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Local;
// Add sub report even handler if you need
***ReportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(MySubreportProcessingEventHandler);***
LocalReport objReport = ReportViewer1.LocalReport;
objReport.ReportPath = path;
// Add Parameter If you need
List<ReportParameter> parameters = new List<ReportParameter>();
parameters.Add(new ReportParameter("Name", Value));
ReportViewer1.LocalReport.SetParameters(parameters);
ReportViewer1.ShowParameterPrompts = false;
ReportViewer1.ShowPromptAreaButton = false;
ReportViewer1.LocalReport.Refresh();
//Add Datasourdce
ReportDataSource reportDataSource = new ReportDataSource();
reportDataSource.Name = "Datasource Name Used due to report design";
reportDataSource.Value = DataSourceValue(Your object data-source);
objReport.DataSources.Add(reportDataSource);
objReport.Refresh();
Here Subreport Even handler code
private void MySubreportProcessingEventHandler(object sender, SubreportProcessingEventArgs e)
{
//You can get parameter from main report
int paramname = int.Parse(e.Parameters[0].Values[0].ToString());
//You can also add parameter in sub report if you need like main report
//Now add sub report data source
e.DataSources.Add(new ReportDataSource("DataSource Name",DataSourceValue)));
}
If you need to create Drillthrough report than follow this link Click here for Drillthrough report

Unable to display report in ASP.Net page

I have created a dataset and using it in my crystal report. Issue is that at design time i am able to display the data but when I execute it using ASP.Net page its showing a blank page. Below is my code that i am using to display the report programatically:
/// <summary>
/// Displays batch report
/// </summary>
/// <param name="agreementId"></param>
private void ShowStatements(string agreementId)
{
var crvStatements = new CrystalReportViewer();
var reportDocument = new ReportDocument();
reportDocument.Load(Server.MapPath("Statements.rpt"));
crvStatements.ReportSource = reportDocument;
var dt1 = new dsStatements.usp_GetBillDetailsByAgreementIdDataTable();
var dt2 = new dsStatements.usp_GetTransactionTypesByAgreementIdForBillDataTable();
var adapter1 = new usp_GetBillDetailsByAgreementIdTableAdapter();
var adapter2 = new usp_GetTransactionTypesByAgreementIdForBillTableAdapter();
adapter1.Fill(dt1, agreementId);
adapter2.Fill(dt2, agreementId);
//var statements = new dsStatements();
//statements.Tables.Add(dt1);
//statements.Tables.Add(dt2);
// reportDocument.SetDataSource(dsStatements);
crvStatements.RefreshReport();
}
Please note that i haven't used any control on the page. I am adding report viewer , report source and dataset programatically. Please help me out. I need it ASAP. I am using VS2010 with CR 2010
Can you provide the reason why you are creating the Crystal Report Viewer at runtime and not simply creating the control on the page? Some people do this so that they can export without displaying, but I don't see any code for that.
I haven't tested this, but I believe the below would work if you had a viewer control on your page.
private void ShowStatements(string agreementId)
{
//var crvStatements = new CrystalReportViewer(); //created on the page
ReportDocument reportDocument = new ReportDocument();
reportDocument.Load(Server.MapPath("Statements.rpt"));
crvStatements.ReportSource = reportDocument;
System.Data.DataTable dt1 = new dsStatements.usp_GetBillDetailsByAgreementIdDataTable();
System.Data.DataTable dt2 = new dsStatements.usp_GetTransactionTypesByAgreementIdForBillDataTable();
System.Data.DataSet statements = new System.Data.DataSet();
statements.Tables.Add(dt1);
statements.Tables.Add(dt2);
reportDocument.SetDataSource(dsStatements);
crvStatements.DataBind();
}
I'm assuming that the report is set up with these tables linked in the report, and you may have to give the datatables a name so that Crystal knows how to map each datatable to the corresponding table within the report. If possible you may try to limit the report to accepting a single table until you have the loading logic worked out.
If each of these datatables represent the data for a subreport then you'll have to iterate through those reports and set the datasources manually.
I hope this helps, but I answered this off the top of my head so there are probably things I've missed. If it doesn't work you just provide a comment and we can probably work through any issues.
The RefreshReport(); makes the Report appearing Empty. try it before loading the Datasets.

Categories