Why does my CR SetParameterValue seem to not work - c#

I have a small Winforms project. .NetFramework 4.5, CR 13.0.14. In a ReportForm:
public partial class ReportForm : Form
{
private readonly string _batchNumber;
public ReportForm(string batchNumber)
{
_batchNumber = batchNumber;
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
APGreenSheets report = new APGreenSheets();
DataSet data = AccountsPayableController.FillDataSet();
report.SetDataSource(data);
report.SetParameterValue("BatchRef", _batchNumber);
crystalReportViewer1.ReportSource = report;
crystalReportViewer1.RefreshReport();
base.OnLoad(e);
}
}
In my CR report I have a Parameter Field “BatchRef” defined as a string.
My Record Selection Formula is: {AP_HistoryHeader.strBatchRef} = {?BatchRef}
When ReportForm loads (passing in the Batch Number reference) the report still prompts me before it will load. I can type it in manually and that will work. But I have Set the Parameter after I set the DataSource to avoid that. Thanks in advance.

Don Williams at SAP provided me the correct answer after a few other code checks:
Simply remove the line crystalReportViewer1.RefreshReport();
This did the trick. Apparently the refresh part wants to renew the passed Parameter. It turns out, I didn't need it to display the report in the first place.
Thanks to Don!

Related

Access stored procedure value within XtraReport

In my Form I have this code to open my report on a click of Button:
private void btnGroupOther_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
LayoutControl lc = new LayoutControl();
lc.Dock = DockStyle.Fill;
DateEdit FirstDate = new DateEdit();
DateEdit LastDate = new DateEdit();
lc.AddItem(Resources.firstdate, FirstDate).TextVisible = true;
lc.AddItem(Resources.seconddate, LastDate).TextVisible = true;
lc.Height = 70;
this.Controls.Add(lc);
this.Dock = DockStyle.Top;
if (DevExpress.XtraEditors.XtraDialog.Show(lc, " ", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
RepProductionGroupOther report = new RepProductionGroupOther();
report.DataSource = paint.RepProductionGroupOther(Convert.ToDateTime(FirstDate.EditValue).ToString("MM/dd/yyyy"),
Convert.ToDateTime(LastDate.EditValue).ToString("MM/dd/yyyy"));
report.ShowRibbonPreviewDialog();
}
}
In my header report I have two xrLabel; the first one txtFirstDate and the second one txtLastDate. I want to show the value of FirstDate DateEdit control in txtFirstDate and the value of LastDate DateEdit control in txtLastDate.
How can I do that, the DataSource of the report is sql stored procedure.
It has two Parameters: #FirstDate and #LastDate.
Thanks in advance
I suggest you to go through XtraReport documentation:
Request and Pass Report Parameter Values
private void button1_Click(object sender, EventArgs e) {
// Create a report instance.
XtraReport1 report = new XtraReport1();
// Obtain a parameter and set its value.
report.Parameters["parameter1"].Value = 30;
// Hide the Parameters' UI from end-users (if you did not hide it at design time).
report.Parameters["parameter1"].Visible = false;
// Show the report's print preview depending on your target platform.
// ...
}
Check the "Custom Parameter Editors" section in above documentation
Custom editor implementation for parameters varies depending on your application's platform:
Windows Forms
In Windows Forms applications, you can provide custom parameter editors in the XtraReport.ParametersRequestBeforeShow event handler.
For a code sample, see Provide Custom Editors for Report Parameters.
Below are similar implementation as you are trying to do.. Check these, hope this will help you resolve the issue.
How to pass parameters to devexpress XtraReport from combobox
DevExpress XtraReport Setting a DateTime Parameter to Today
Passing parameters to Xtrareports repx file

RDLC Reporting using C#

I am completely new to reporting in visual studio C#..I tried searching for some tutorials for beginners but i was unsuccessful..I just found code examples that didn't really explain the basics...I wrote some code which complies and runs fine but it DOES NOT SHOW ANYTHING in the report viewer control in Visual Studio 2013..My code is as follows:
// This method is in a class named Customers.
// When the user clicks the first column of the datagrid view(I have placed a button
// in the first column of the datagrid) a new form opens (ReportForm) and i pass
// the DataSet called dsReport to its constructor.
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 0 )
{
DataSet dsReport = new DataSet();
DataTable tbl = dsReport.Tables.Add();
tbl.Columns.Add("CustomerName", typeof(string));
tbl.Columns.Add("CustomerAddress", typeof(string));
tbl.Columns.Add("MaritalStatus", typeof(string));
tbl.Columns.Add("CustomerType", typeof(string));
tbl.Columns.Add("ImagePath", typeof(string));
foreach (Customer cust in customerList)
{
DataRow dr = dsReport.Tables[0].NewRow();
dr["CustomerName"] = cust.Name;
dr["CustomerAddress"] = cust.Address;
dr["MaritalStatus"] = cust.MaritalStatus;
dr["CustomerType"] = cust.CustomerType;
dr["ImagePath"] = cust.ImagePath;
dsReport.Tables[0].Rows.Add(dr);
}
ReportForm report = new ReportForm(dsReport);
report.Show();
}
}
//Following is the code for the ReportForm Class
//I do not get any results in the report viewer
//I just see the message "The source of the report definition has not been specified"
public ReportForm(DataSet dsReport)
{
InitializeComponent();
this.reportViewer1.LocalReport.DataSources.Clear();
this.reportViewer1.LocalReport.DataSources.Add(myReportSource);
this.reportViewer1.ProcessingMode = ProcessingMode.Local;
this.reportViewer1.LocalReport.Refresh();
this.reportViewer1.RefreshReport();
}
private void ReportForm_Load(object sender, EventArgs e)
{
this.reportViewer1.RefreshReport();
}
/* Please note that I have run the code in the debugger and the dataset is being
populated properly and so is the reportViewer1.LocalReport..Also I HAVE NOT
Added any datasources to the project AND I HAVE NOT ADDED ANY Report files(.rdl) files
to the Project */
Lastly can anyone PLEASE answer the following questions:
Q1. Do i absolutely have to include a datasource to work with the report
viewer tool??
Q2. Do i have to include a .rdl file in the project to display a report??
Q3. Is the report viewer tool and a .rdl file one in the same or are they
different??
The ReportViewer is a control that knows how to render a report. It just handles the drawing and some other background tasks, it isn't the actual report. The actual report is the .rdl file (Report Definition Language). It contains all the instructions for generating the report, but it doesn't contain the actual data. The DataSource contains the data that the report operates on.
So to answer your questions specifically:
yes (unless your report is completely static and doesn't use any data).
no, but you need get the .rdl to the ReportViewer somehow. If you don't want to include it as a file you can embed it as a resource in your application, or even hard code it as a string. The ReportViewer has a method that accepts a Stream also, so anything that can provide a stream can act as the source for the .rdl.
They are different, as I explained at the very start.

Programatically change display of the sort icon in datagrid column header

I asked this question previously and did not get an answer but now I have more detail.
Basically I want to programatically display the column sort icon in a wpf datagrid column.
I have the following code to do this:
private void dtgMain_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
dtgMain.Columns[0].SortDirection = ListSortDirection.Ascending;
}
This seems to set the sort order of the column but when the grid is drawn the icon does not show.
When I add a message box into the method it works fine. My question is twofold. Why would the message box cause the method to work? And how can I get it to work without the use of a messagebox?
This is the method working with the messagebox in it:
private void dtgMain_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
MessageBox.Show("Here");
dtgMain.Columns[0].SortDirection = ListSortDirection.Ascending;
}
edit
Here is the method that is setting the datacontext of the datagrid
public void processLoad(string response)
{
XmlDataProvider provider = new XmlDataProvider();
if (provider != null)
{
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.LoadXml(response);
provider.Document = doc;
provider.XPath = "/moo/response/data/load/panel";
dtgMain.DataContext = provider;
}
}
Please let me know if you need anymore information.
OK, I suspect what is happening is that the data layout changes caused by the DataContext update are being completed after your call to set the direction arrow, and it is therefore being erased after you set it. Interestingly, in my case it failed to work even when I put the messagebox in, perhaps because that was hanging up the UI thread while it displayed.
Could you try replacing the line that sets the sort direction with a similar call put on the dispatcher queue:
dtgMain.Dispatcher.BeginInvoke(new Action(() =>
{
dtgMain.Columns[0].SortDirection = ListSortDirection.Ascending;
}), DispatcherPriority.ApplicationIdle);
and see if that works?

How to hold a table of data for user edition (before saving in the the database)?

I've been using this programming style, that I've seen in an example and just started using it, because it does the job... I would like to know other programmers' opinion about it...
So the situation is when you have a GridView, or a control based on it like the RadGrid, and you want to keep track of a data table while you are adding, editing, reordering and deleting rows.
Using the session to hold the data table (or list of data) may not be the best solution, because the user may open two identical web pages… Using the ViewState to hold the data may be and option... I have been using an approach like the following:
public partial class DefaultPage : System.Web.UI.Page
{
protected DataLine DefaultDataLine()
{
DataLine dl = new DataLine();
dl = new DataLine();
dl.Number = 0;
dl.Title = "";
dl.Text = "";
return dl;
}
protected class DataLine
{
public int Number { get; set; }
public string Title { get; set; }
public string Text { get; set; }
}
protected static List<DataLine> tempLines;
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
tempLines = RadGridBindStartUpData();
}
}
protected void RadGrid1_NeedDataSource(object source, Telerik.Web.UI.GridNeedDataSourceEventArgs e)
{
RadGrid1.DataSource = tempLines;
}
protected void RadGrid1_InsertCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
{
GridEditableItem editedItem = e.Item as GridEditableItem;
List<DataLine> table = tempLines;
DataLine newRow = new DataLine ();
RadTextBox rtb;
rtb = (RadTextBox)editedItem.FindControl("RadTextBoxTitle");
newRow.Title = rtb.Text;
rtb = (RadTextBox)editedItem.FindControl("RadTextBoxDescription");
newRow.Description = rtb.Text;
RadNumericTextBox number = (RadNumericTextBox)editedItem.FindControl("RadNumericTextBoxNumber");
newRow.Number = number.Value.HasValue ? Convert.ToInt32(number.Value.Value) : 0;
table.Add(newRow);
}
// ...
So using a static List variable, of a custom object (class), declared in the code-behind of the Aspx page, and updating it whenever the data is edited.
What are your thoughts about this approach? Is it okay? How do you hold your table-format data for edition (prior to saving it in the database)?
Not exactly sure what you're going for, but using a static variable is probably not what you want to do. Static properties are shared across all user/threads, so all concurrent users would be editing the same data.
If you are just looking to persist a small data set across post-backs to the same page, use the ViewState instead. Just be mindful of potential performance issues if you plan on cramming lots of data into it.
It depends on what you're wanting to achieve
Viewstate will keep the data on that page - it won't be available on any other pages (or tabs, or windows)
Session will keep the data on the server, this means it will be available for any page the user is looking at (on your site) and it will keep it until the session times out.
Theres a lot of advtanges/disadvantages to either method, therefore you need to research your situation, here is a start.
You mentioned storing in the session, and how this could cause issues if the user opens up multiple copies of the page, etc...
We had a similar issue so I made a property in code behind on the page and on first page load (if not postback blah blah) I generate a new guid. Then I use the guid value as my session key and I know it'll be unique per page.
You could make a spify property like this...
Public ReadOnly Property SessionDataKey() As String
Get
If ViewState("SessionDataKey") Is Nothing Then
ViewState("SessionDataKey") = Guid.NewGuid()
End If
Return ViewState("SessionDataKey").ToString()
End Get
End Property
But in short, I just use the session.
Thank you very much for your replies! With your help, and some research, I see that both approaches, storing in session or using the static variable are indeed wrong, at least for the purpose I was using them... All your answers were helpful, and although I can only mark one as correct, I would like to leave my appreciation.
Well, for anyone stumbling across the same problem, here’s what I’ve implemented in my pages:
public partial class ScriptAdd : System.Web.UI.Page
{
private List<MyItem> tempMyItems
{
get
{
//if (ViewState["tempMyItemsList"] == null)
// ViewState["tempMyItemsList"] = new List<MyItem>();
return (List<MyItem>)ViewState["tempMyItemsList"];
}
set
{
ViewState.Add("tempMyItemsList", value);
}
}
protected void Page_Load(object sender, EventArgs e)
{
// ...
}
}
And then use it whenever I want to add / insert / update lines to my temporary list:
List<MyItem> table = tempMyItems;
table.RemoveAt(idx);
MyItem newRow = new MyItem ();
// ...
table.Insert(idx, newRow);
Finally, if intended, I store all the items in the database.

Crystal Report: Missing Parameter Values

I am new to Crystal report, application is in ASP.net 3.5 and MySQL 5.1, going to develop report between dates like from date and to date, first page of report is shown good but when i tried to navigate on another page i got error like Missing Parameter Values same error i got in Printing and Export action
Thanks in advance
public partial class BookingStatement : System.Web.UI.Page
{
//DAL is my Data Access Layer Class
//Book is ReportClass
DAL obj = new DAL();
Book bkStmt = new Book();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//crvBooking is Crystal Report Viewer
//reportFill method is to fill Report
reportFill();
crvBooking.EnableViewState = true;
crvBooking.EnableParameterPrompt = false;
}
/* Also try reportFill() out side !IsPostBack but didn't work */
//Check if the parmeters have been shown.
/* if ((ViewState["ParametersShown"] != null) && (ViewState["ParametersShown"].ToString() == "True"))
{
bkStmt.SetParameterValue(0, "20/04/2010");
bkStmt.SetParameterValue(1, "20/04/2010");
}*/
}
protected void crvBooking_navigate(object sender, CrystalDecisions.Web.NavigateEventArgs e)
{
// reportFill();
}
protected void reportFill()
{
//bkStmt.rpt is Report file
//bookingstatment is View
//bkStmt is ReportClass object of Book
string rptPath = "bkStmt.rpt";
string query = "select * from bookingstatment";
crvBooking.RefreshReport();
crvBooking.Height = 600;
crvBooking.Width = 900;
bkStmt.ResourceName = rptPath;
String dtFrm = bkStmt.ParameterFields[0].CurrentValues.ToString();
obj.SetCommandType(CommandType.Text);
obj.CommText = query;
DataTable dtst = obj.GetDataTable();
crvBooking.ParameterFieldInfo.Clear();
ParameterDiscreteValue discretevalue = new ParameterDiscreteValue();
discretevalue.Value = "20/04/2010"; // Assign parameter
ParameterValues values = new ParameterValues();
values.Add(discretevalue);
bkStmt.SetDataSource(dtst);
ViewState["ParametersShown"] = "True";
crvBooking.EnableViewState = true;
bkStmt.DataDefinition.ParameterFields[0].ApplyCurrentValues(values);
bkStmt.DataDefinition.ParameterFields[1].ApplyCurrentValues(values);
crvBooking.ReportSource = bkStmt;
}
}
The problem seems to occur because Crystal Reports does not persist its parameter values in its ViewState when a postback occurs. So when the CrystalReportViewer attempts to load up the ReportClass it used as its ReportSource again, the parameter values are no longer there.
A solution which we've used successfully is to save the ReportClass (i.e. your Crystal Report object) into Session after all its parameter values have been set & then load this into the CrystalReportViewer upon each PostBack in the Page_Init event. An example:
// instantiate the Crystal Report
var report = new DeliveryLabelsSingle();
// set the required parameters
report.DataSourceConnections[0].SetConnection("DBServer", "DatabaseName", "DatabaseUser", "DatabasePassword");
report.SetParameterValue("#Param1", "val1");
report.SetParameterValue("#Param2", "val2");
// set the data source of the viewer
crvLabels.ReportSource = report;
// save the report object in session for postback binding
Session["rptDeliveryLabels"] = report;
Then the Page_Init event for the page looks like the following:
protected void Page_Init(object sender, EventArgs e)
{
if (IsPostBack) {
if (Session["rptDeliveryLabels"] != null) {
// cast the report from object to ReportClass so it can be set as the CrystalReportViewer ReportSource
// (All Crystal Reports inherit from ReportClass, so it serves as an acceptable data type through polymorphism)
crvLabels.ReportSource = (ReportClass)Session["rptDeliveryLabels"];
}
}
}
In this way, we will always set a report object for the viewer, which has already been initialized with the appropriate values.
Something to keep in mind with this approach is that you will potentially fill up your server memory very quickly, especially if you have lots of users generating lots of different reports. So some housekeeping is in order. We've done this through implementing a base class for all our ASP.NET pages that contain a report (and thus this report loading code). In this base class, we set all possible Session variables that are reports to null. Like so:
// class definition for ASP.NET page containing CrystalReportViewer & associated report(s)
public partial class DeliveryLabelPrint : BaseReport
Then the definition for BaseReport is as follows:
public class BaseReport : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
if (!IsPostBack) {
for (var i = 0; i < Session.Count; i++) {
var sv = Session[i];
// if this session variable contains a Crystal Report, destroy it
if (sv is ReportClass) {
sv = null;
}
}
base.OnLoad(e);
}
}
}
In this way, you ensure that any user only ever has one report in memory at any given time.
If memory is a concern, even with this approach, an alternative could be to store the individual variable values in Session & to then instantiate a new report in Page_Init & repopulate it with the saved values before assigning it to CrystalReportViewer.ReportSource. But in our case, with 40 users pulling 50+ different reports on a daily basis, this implementation of storing of the ReportClass object & the accompanying housekeeping, we haven't run into any memory problems since the application went live 3 years ago. I would still suggest doing appropriate load testing & monitoring before pushing this solution to production, as the results may vary depending on the specific implementation.
When I am writing SQL for a Crystal report, the code for the parameters in SQL is like this:
--Date Range
(
(table.datetime >= '{?Start Date}')
and table.datetime < '{?End Date}')
)
--Location
('{?Facility}'= 'All' OR '{?Facility}' = table.location))
Of course you always have the option of programming the parameters straight into Crystal. This approach is not as efficient but sometimes easier.
I had to use explicit ReportDocument type instead of ReportClass because that raised an invalid cast for some reason, but otherwise, works EXACTLY as advertised AFAICT.
viz.
...
...
if (Session["<some identifier>"] != null)
{
switch (Session["<some identifier>"])
{
case ReportClass rc:
crystalReportViewer1.ReportSource = rc;
break;
case ReportDocument rd:
crystalReportViewer1.ReportSource = rd;
break;
default:
return;
}
}

Categories

Resources