Passing parameter programmatically and displaying in crystal reports - c#

I have a crystal report in which I set the datasource and parameter programmatically. This works when I just display regular data in the report. However, when I try to show the parameter value in the report header (it's a date), I get prompted to enter the parameter.
Any ideas as to what's causing this? I'm new to crystal reports so this might be a very simple problem.
Here's my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Data.SqlClient;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
namespace CrystalReportsTestApp
{
public partial class ReportForm : Form
{
ReportDocument report = new ReportDocument();
public ReportForm()
{
InitializeComponent();
}
private void ConfigureCrystalReports()
{
string reportPath = "mypath\\CrystalReport1.rpt";
report.Load(reportPath);
}
private void RunReportButton_Click(object sender, EventArgs e)
{
DateTime date = dateTimePicker1.Value;
DataSet reportData = new DataSet();
SqlConnection conn = null;
SqlDataAdapter da = null;
try
{
conn = new SqlConnection(connectionString);
conn.Open();
da = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand("cms.GetActiveEntityAccounts", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#EndDate", SqlDbType.DateTime).Value = date;
da.SelectCommand = cmd;
da.Fill(reportData, "DataTable1");
}
finally
{
if (conn != null)
{
conn.Close();
}
}
report.SetDataSource(reportData);
report.SetParameterValue("#EndDate", date);
crystalReportViewer1.ReportSource = report;
crystalReportViewer1.RefreshReport();
}
private void ReportForm_Load(object sender, EventArgs e)
{
ConfigureCrystalReports();
}
}
}

The problem was the following line towards the end:
crystalReportViewer1.RefreshReport();
This caused the report parameters to refresh and not just the report data.

You need to pass the Parameters to CrystalReportViewer control.
Use the below code after report.SetDataSource(reportData);.
CrystalDecisions.Shared.ParameterField parameterField = new CrystalDecisions.Shared.ParameterField();
parameterField.Name = "#EndDate";
//Create a new Discrete Value
CrystalDecisions.Shared.ParameterDiscreteValue parameterDiscreteValue = new CrystalDecisions.Shared.ParameterDiscreteValue();
parameterDiscreteValue.Value = date;
//Add the value
parameterField.CurrentValues.Add( parameterDiscreteValue );
//Add the parameter field
crystalReportViewer1.ParameterFields.Add( parameterField );
crystalReportViewer1.ReportSource = report;
crystalReportViewer1.RefreshReport();

Related

Error when editing a datagridview with a connected MySQL database. An error appears when trying to save

When trying to edit the datagridview, an error appears "The CommandText property has not been properly initialized.". I read that some other stored procedure is needed, which as input parameters it takes the first name, last name and patronymic and phone number of the user and returns his id, if so, how to implement it on mysql link to the source: https://metanit.com/sharp/adonet/2.11.php , https://metanit.com/sharp/adonet/3.5.php
Program code:
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SD = System.Data;
namespace DBredaction
{
public partial class Form1 : Form
{
DataSet ds;
MySqlDataAdapter adapter;
MySqlCommandBuilder commandBuilder;
string connectionString = "Server=localhost;Database=catalog;Uid=root;pwd=;charset=utf8;";
string sql = "SELECT * FROM employee";
public Form1()
{
InitializeComponent();
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.AllowUserToAddRows = false;
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
adapter = new MySqlDataAdapter(sql, connection);
ds = new DataSet();
adapter.Fill(ds);
dataGridView1.DataSource = ds.Tables[0];
// делаем недоступным столбец id для изменения
dataGridView1.Columns["Id"].ReadOnly = true;
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
//public MySqlConnection mycon;
//public MySqlCommand mycom;
//public string connect = "Server=localhost;Database=catalog;Uid=root;pwd=;charset=utf8;";
//public SD.DataSet ds;
//public MySqlCommand mycon2;otchestvo
private void button1_Click(object sender, EventArgs e)
{
try {
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
adapter = new MySqlDataAdapter(sql, connection);
commandBuilder = new MySqlCommandBuilder(adapter);
adapter.InsertCommand = new MySqlCommand("", connection);
adapter.InsertCommand.CommandType = CommandType.StoredProcedure;
adapter.InsertCommand.Parameters.Add(new MySqlParameter("#imia", MySqlDbType.VarChar, 50, "Имя"));
adapter.InsertCommand.Parameters.Add(new MySqlParameter("#familia", MySqlDbType.VarChar, 50, "Фамилия"));
adapter.InsertCommand.Parameters.Add(new MySqlParameter("#otchestvo", MySqlDbType.VarChar, 50, "Отчество"));
adapter.InsertCommand.Parameters.Add(new MySqlParameter("#telephon", MySqlDbType.VarChar, 11, "Телефон"));
MySqlParameter parameter = adapter.InsertCommand.Parameters.Add("#id", MySqlDbType.Int16, 0, "Id");
parameter.Direction = ParameterDirection.Output;
adapter.Update(ds);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void button4_Click(object sender, EventArgs e)
{
try
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
MessageBox.Show("DB CONNECT");
connection.Close();
}
}
catch
{
MessageBox.Show("Connection lost");
}
}
private void button3_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
dataGridView1.Rows.Remove(row);
}
}
private void button5_Click(object sender, EventArgs e)
{
DataRow row = ds.Tables[0].NewRow();
ds.Tables[0].Rows.Add(row);
}
}
}
It doesn't work quite like that; if you're assigning a command builder to an adapter you don't then also set the XxxCommand DML properties yourself; the command builder does that from looking at the SelectCommand, working out the table schema and writing the queries.
I'd have the adapter at class level in a dedicated repository class, where the select, connstr and command builder are set:
//in the constructor of the repo class
_myDataAdapter = new MySqlDataAdapter("SELECT here", "connstr here");
_commandBuilder = new MySqlCommandBuilder(_myDataAdapter);
the fill code runs:
//in a GetData method of the repo class
DatTable dt = new DataTable();
_myDataAdapter.Fill(dt);
return dt;
and the relevant I/U/D commands can be triggered:
//in a SaveChanges(DataTable) method of the repo class
_myDataAdapter.Update(dt);
See https://www.devart.com/dotconnect/mysql/docs/Devart.Data.MySql~Devart.Data.MySql.MySqlCommandBuilder.html for more background info on the CB; their example code is based on a complete programmatic "fill, change, save" workflow so it's all in one method, but your workflow is essentially interrupted by the user needing to do the changes in the grid, hence breaking it up.
If you want to do it in one method, you can make your adapter, make your command builder and then set the I/U/D commands on the adapter by calling the relevant GetXxx on the command builder
Note that the command builder doesn't use stored procedures; that thing you've read about needing to make a stored procedure to update/insert data isn't the only way to save data to a db, and if you have created a sproc and are hoping to use it, forget a command builder; you'll have to do the command setup yourself

Pass table from DataSet as parameter

I'm really new with C# and ASP.Net, I can say that i'm learning over the road. What i need to do is run an stored procedure and create an Excel file with the response. This is my code so far of the controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using ConfigurationSettings = System.Configuration.ConfigurationManager;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace NewSalesReport.Controllers
{
public class NewSalesReportController : Controller
{
class Program
{
static void Main()
{
string inline = ConfigurationSettings.AppSettings["ConectionString"];
using (SqlConnection toConect = new SqlConnection(inline))
{
using (SqlCommand cmd = new SqlCommand("DaReport", toConect))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#StartDate", SqlDbType.DateTime));
cmd.Parameters.Add(new SqlParameter("#EndDate", SqlDbType.DateTime));
using (SqlDataAdapter adp = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
adp.Fill(ds);
/*if (ds != null)
{
//Console.Write("It is not Empty");
} */
}
}
}
}
private void SetDataExcel(object result)
{
GridView grid = new GridView();
grid.DataSource = result;
StringWriter strwritter = new StringWriter();
HtmlTextWriter htmltextwrtter = new HtmlTextWriter(strwritter);
grid.RenderControl(htmltextwrtter);
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=reportExcel.xls");
Response.ContentType = "application/ms-excel";
Response.Output.Write(strwritter.ToString());
Response.Flush();
Response.End();
strwritter.Dispose();
htmltextwrtter.Dispose();
}
public ActionResult GetAprovedForPay(DateTime? fi = null, DateTime? ff = null)
{
var result = _repo.GetAprovedForPay(fi, ff);
SetDataExcel(result);
return null;
}
}
}
}
Someone is helping me with a few advices, and he told me that i need to pass the first table as a parameter: ds.Tables[0], but he didn't explain how.
Also, when i run the compiler shows an error which says that i need a
reference object for the field, method or property Controller.Response.
Someone can help me, please with this two issues? As i said, i'm new with this hole thing of .Net.
Thanx in advance
An object reference is required for the non-static field, method or property error occurred because you're calling Controller.Response from a method which has return type of void instead of ActionResult.
First, remove inner class Program and rename Main() method to other name (also remove static if necessary). Sounds like the code includes Main() method previously used in console/WinForms application, and you should change it to avoid confusion.
Second, remove Response usage and use FileResult to return file for download as in example below:
public FileResult SetDataExcel(object obj)
{
GridView grid = new GridView();
grid.AutoGeneratedColumns = true; // automatically generate all columns from data source
grid.DataSource = result;
StringWriter strwritter = new StringWriter();
HtmlTextWriter htmltextwrtter = new HtmlTextWriter(strwritter);
grid.RenderControl(htmltextwrtter);
string path = Server.MapPath("~/path/to/filename.xls");
using (var sw = new StreamWriter(path))
{
sw.Write(strwriter.ToString());
}
var savedFile = new FileStream(path, FileMode.Open);
return File(savedFile, "application/ms-excel");
}
Finally, you can use redirection to call SetDataExcel which returns the file:
public ActionResult GetAprovedForPay(DateTime? fi = null, DateTime? ff = null)
{
var result = _repo.GetAprovedForPay(fi, ff);
return RedirectToAction("SetDataExcel", new { obj = result });
}
Note: Regarding data binding for GridView, if AutoGeneratedColumns set to true then you can use ds.Tables[0] as data source (see the reference here):
string inline = ConfigurationSettings.AppSettings["ConectionString"];
using (SqlConnection toConect = new SqlConnection(inline))
{
using (SqlCommand cmd = new SqlCommand("DaReport", toConect))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#StartDate", SqlDbType.DateTime));
cmd.Parameters.Add(new SqlParameter("#EndDate", SqlDbType.DateTime));
using (SqlDataAdapter adp = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
adp.Fill(ds);
grid.DataSource = ds.Tables[0];
grid.DataBind();
}
}
}

System.IndexOutOfRangeException due to parameter & variables

With C# & ASP.net, I have a master page and a content page. On a content page, I have a text box, where the user can input a value and then hit a button. This button runs a stored SQL procedure, and uses the user input as a parameter, then puts the results into an html table to display.
My webpage will launch, but the error is thrown after hitting the button with a user input. I think my issue is related to the parameter (#PN), the parameter variable (param), user input to variable (inputX). Error message reads
System.IndexOutOfRangeException was unhandled by user code
Message=An SqlParameter with ParameterName '#PN' is not contained by
this SqlParameterCollection.
C# Code as follows
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
using System.Text;
using System.Configuration;
namespace NSV3
{
public partial class Fancy : System.Web.UI.Page
{
private string inputX = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
Label1.Attributes.Add("onClick", "CallMe();");
}
public void btnTemp_Click(object sender, EventArgs e)
{
string inputX = TextBox1.Text.ToString();
Label2.Text = "You've selected " + inputX;
SqlParameter param = new SqlParameter();
param.ParameterName = "#PN";
param.Value = inputX;
DataTable dt = this.GetData();
StringBuilder html = new StringBuilder();
html.Append("<table border = '1'>");
html.Append("<tr>");
foreach (DataColumn column in dt.Columns)
{
html.Append("<th>");
html.Append(column.ColumnName);
html.Append("</th>");
}
html.Append("</tr>");
foreach (DataRow row in dt.Rows)
{
html.Append("<tr>");
foreach (DataColumn column in dt.Columns)
{
html.Append("<td>");
html.Append(row[column.ColumnName]);
html.Append("</td>");
}
html.Append("</tr>");
}
html.Append("</table>");
PlaceHolder1.Controls.Add(new Literal { Text = html.ToString() });
}
public DataTable GetData()
{
string constr = "editted";
string sql = #"EXEC [ERP_Reports].[dbo].[udsp_WhereUsed]
#IMA_ItemID_INPUT = #PN,
#IMA_RecordID_INPUT = NULL,
#RecursionLevel = NULL,
#FetchSequence = NULL,
#QtyPerAssy_PrevLevel = NULL";
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand(sql))
{
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
cmd.Parameters["#PN"].Value = inputX;
sda.SelectCommand = cmd;
using (DataTable dt = new DataTable())
{
sda.Fill(dt);
return dt;
}
}
}
}
}
}
}
In GetData method, inside the SqlDataAdapter 'using', try the following:
...
cmd.Connection = con;
cmd.Parameters.AddWithValue("#PN", inputX);
sda.SelectCommand = cmd;
...
The problem is that cmd.Parameters["#PN"] does not exist when you set its Value so you get the exception.
You need to add the Param to the sqlCommand
cmd.Parameters.AddWithValue("#PN", inputx);
You also don't need this code in your btnTemp_Click method
SqlParameter param = new SqlParameter();
param.ParameterName = "#PN";
param.Value = inputX;

Run all code within a page consecutively in C# (Using Visual Studio)

I have values from controls txtUser and txtAppNum on a page webform1.aspx. I am bringing those values to a page, Login.aspx. The code from Login.aspx is below. In the login.aspx page, I want to take the values from the controls txtUserand txtAppNum in webform1.aspx page, I want to check the values against a database, if the values are in the database, I want the page to redirect back to webform1.aspx.
My questions is, when I run the code, only Page_Load but not CheckRecord. Basically when I run the page, I can see the values carried over from the webform1.aspx page to login.aspx, but then that's it, nothing else happens.
What am I doing wrong? Any thoughts, I would greatly appreciate it, I have been stuck on this for a few days. Thanks!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient; //to communicate with the Server database
using System.Configuration;
using System.Data; //to use DataSet or DataTable
using System.Text; //for StringBuilder
namespace BLAA_3
{
public partial class login : System.Web.UI.Page
{
public void Page_Load(object sender, EventArgs e)
{
Page PreviousPage = Page.PreviousPage;
if (PreviousPage != null)
{
lblUserLogin.Text = ((TextBox)PreviousPage.FindControl("txtUser")).Text;
lblAppLogin.Text = ((TextBox)PreviousPage.FindControl("txtAppNum")).Text;
}
{
string _connStr = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
}
}
public void CheckRecord(object sender, EventArgs e)
{
//get the connection
using (SqlConnection conn = new SqlConnection(#"Data Source=ServerInfo"))
{
//write the sql statement to execute
string sql = "select username FROM BLAA_users WHERE username = #username";
//instantiate the command object to fire
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
//attatch the parameter to pass, if no parameter is in the sql no need to attatch
SqlParameter[] prms = new SqlParameter[1];
prms[0] = new SqlParameter("#username", SqlDbType.VarChar, 50);
prms[0].Value = lblUserLogin.Text.Trim();
cmd.Parameters.AddRange(prms);
conn.Open();
object obj = cmd.ExecuteScalar();
conn.Close();
if (obj != null)
{
Response.Redirect("~/WebForm1.aspx");
}
else
Response.Redirect("http://www.google.com");
}
}
}
}
}
Is CheckRecord an event handler? If not, you don't need the sender and eventArgs in your signature for CheckRecord it can be public void CheckRecord().
It's not being called because your load event isn't calling it. So, inside your Page_Load function.
public void Page_Load(object sender, EventArgs e)
{
Page PreviousPage = Page.PreviousPage;
if (PreviousPage != null)
{
lblUserLogin.Text = ((TextBox)PreviousPage.FindControl("txtUser")).Text;
lblAppLogin.Text = ((TextBox)PreviousPage.FindControl("txtAppNum")).Text;
}
{
string _connStr = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
}
CheckRecord();
}
public void CheckRecord()
{
//get the connection
using (SqlConnection conn = new SqlConnection(#"Data Source=ServerInfo"))
{
//write the sql statement to execute
string sql = "select username FROM BLAA_users WHERE username = #username";
//instantiate the command object to fire
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
//attatch the parameter to pass, if no parameter is in the sql no need to attatch
SqlParameter[] prms = new SqlParameter[1];
prms[0] = new SqlParameter("#username", SqlDbType.VarChar, 50);
prms[0].Value = lblUserLogin.Text.Trim();
cmd.Parameters.AddRange(prms);
conn.Open();
object obj = cmd.ExecuteScalar();
conn.Close();
if (obj != null)
{
Response.Redirect("~/WebForm1.aspx");
}
else
Response.Redirect("http://www.google.com");
}
}
}

Close firefox webpage and debug

My following code has two problems.
1- It doesn't go to the next row in dataset (when I run it, it just run firefox for 2916 times). I change this it from
var test = url.Replace("<userid>", Convert.ToString(row[userID]));
to
var test = url.Replace("<userid>", Convert.ToString(row["userID"]));
but it shows an error (Column 'userid' does not belong to table).
2- I want to close the firefox webpage page at the end of each loop and for next loop it runs again(because of performance issue)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using System.Net;
namespace test2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
OleDbConnection conn = new OleDbConnection();
conn.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\hidden.accdb";
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = "Select * from hidden";
DataTable dt = new DataTable();
//To read data from dataset
OleDbDataAdapter adapter = new OleDbDataAdapter();
adapter.SelectCommand = cmd;
//Store the userID
adapter.Fill(dt);
int userid=0,trackid=0;
int counter=0;
foreach(DataRow row in dt.Rows)
{
string url = "http://abcd/<userid>?groups=<userid>";
var test = url.Replace("<userid>", Convert.ToString(row[userid]));
System.Diagnostics.Process.Start(url);
string client = (new WebClient()).DownloadString("http://abcd/userid?groups=userid");
if (client.ToLower() == (Convert.ToString(trackid).ToLower()))
{
counter++;
}
int ave = counter / 2916;
MessageBox.Show("Average = " + counter);
}
conn.Close();
}
}
}
string url = "http://abcd/<userid>?groups=<userid>";
var test = url.Replace("<userid>", Convert.ToString(row["userid"])); // You need ""
System.Diagnostics.Process.Start(test); // You should use variable test, which contains your url with <userid> replaced.

Categories

Resources