How to dynamically and correctly change a query in Command Table for Crystal Reports file? - crystal-reports

I have many rpt files. I want to change the query for each report using C#. There are several ways to do this changes.
First way:
private void button_Test_Click(object sender, EventArgs e)
{
ReportDocument rptDoc = new ReportDocument();
rptDoc.Load("D:\\Temp_01\\Report1_Test.rpt");
rptDoc.SetDatabaseLogon("User", "Password", "ServName", "DBName");
CrystalDecisions.Shared.ConnectionInfo ConnInf;
ConnInf = rptDoc.Database.Tables[0].LogOnInfo.ConnectionInfo;
String strSQLQuery = "SELECT TOP(123) * FROM sys.all_objects";
String strTableName = rptDoc.Database.Tables[0].Name;
try
{
rptDoc.SetSQLCommandTable(ConnInf, strTableName, strSQLQuery);
rptDoc.VerifyDatabase();
}
catch (Exception ex) { rptDoc.Close(); }
rptDoc.SaveAs("D:\\Temp_02\\Report2_Test.rpt");
rptDoc.Close();
}
It is not the best way. The method SetSQLCommand does not work when the query has any parameters. Even if you set value for each parameter, SetSQLCommand does not work. The example with a parameter which does not work:
private void button_Test_Click(object sender, EventArgs e)
{
ReportDocument rptDoc = new ReportDocument();
rptDoc.Load("D:\\Temp_01\\Report1_Test.rpt");
rptDoc.SetDatabaseLogon("User", "Password", "ServName", "DBName");
CrystalDecisions.Shared.ConnectionInfo ConnInf;
ConnInf = rptDoc.Database.Tables[0].LogOnInfo.ConnectionInfo;
String strSQLQuery = "SELECT TOP(1) * FROM sys.all_objects WHERE name = {?strName}";
String strTableName = rptDoc.Database.Tables[0].Name;
try
{
rptDoc.SetParameterValue("strName", "Text");
rptDoc.SetSQLCommandTable(ConnInf, strTableName, strSQLQuery);
rptDoc.VerifyDatabase();
}
catch (Exception ex) { rptDoc.Close(); }
rptDoc.SaveAs("D:\\Temp_02\\Report2_Test.rpt");
rptDoc.Close();
}
It returns an error. This method does not work with parameters!
Second way:
private void button_Test_Click(object sender, EventArgs e)
{
ReportDocument rptDoc = new ReportDocument();
rptDoc.Load("D:\\Temp_01\\Report1_Test.rpt");
rptDoc.SetDatabaseLogon("User", "Password", "ServName", "DBName");
ISCDReportClientDocument rcd = null;
rcd = rptDoc.ReportClientDocument as ISCDReportClientDocument;
CommandTable rTblOld;
CommandTable rTblNew;
rTblOld = rcd.Database.Tables[0] as CommandTable;
rTblNew = rcd.Database.Tables[0].Clone(true) as CommandTable;
rTblNew.CommandText = "SELECT TOP(1) * FROM sys.all_objects";
try
{
rcd.DatabaseController.SetTableLocationEx(rTblOld, rTblNew);
rcd.VerifyDatabase();
}
catch (Exception ex) { rcd.Close(); }
rcd.SaveAs(rcd.DisplayName, "D:\\Temp_02\\", 1);
rcd.Close();
}
This is also not the best way. The method SetLocalTableEx does a struct of the report is bad. After run SetLocalTableEx, attribute ConnectionInf.UserId have value NULL also the Name of connection
After SetTableLocationEx:
rcd.DatabaseController.SetTableLocationEx(rTblOld, rTblNew);
String UserID;
UserID = rptDoc.Database.Tables[0].LogOnInfo.ConnectionInfo.UserID;
if (UserID == null) MessageBox.Show("UserID has NULL");
UserId has value NULL
Also, before run SetTableLocationEx, Connection Name is MSODBCSQL11
enter image description here
After run SetTableLocationEx, Connection Name is Command
enter image description here
So,
how do dynamic and correctly to change the query in CommandTable for Crystal Reports file?
Thanks,
Artem

You are using command in Crystal Report which is the best way when doing and displaying a data from database to crystal report but unfortunately you do it in Code Behind.
My Question is:
Why don't you do it in Command of Crystal Report itself?
see this link for more info.

Related

C# programming with window forms

private void dataGridView1_RowHeaderMouseClick_1(object sender, DataGridViewCellMouseEventArgs e)
{
int ID = Convert.ToInt32(dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString());
txtName.Text = dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString();
txtFname.Text = dataGridView1.Rows[e.RowIndex].Cells[2].Value.ToString();
txtAddress.Text = dataGridView1.Rows[e.RowIndex].Cells[3].Value.ToString();
}
private void btnEdit_Click(object sender, EventArgs e)
{
SqlCommand cmd = new SqlCommand("Update student set name ='"+txtName.Text+"', fathername= '"+txtFname.Text+"', address= '"+txtAddress.Text+"' where id = ID", con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
Display();
MessageBox.Show("Record is Updated");
When i run this code then my whole database table is updated with the current values and i can't understand the problem
"where id = ID" condition is always true so all records are affected. You need to actually set a value for "ID". Perhaps you need to write
"where id =" + ID.ToString()

Unable to know how to link data between two tables

I'm learning RESTful webservices from javabrains website. Here there is a section named Comments and this is related to a message, But I'm unable to know How Can I link these both.
Below is my SQL Tables for Messages and comments.
Messages
Comments
Here Basically, both look pretty same(The table design), but the values differ. And I'm using the below method to send the data.
public Comment addComment(long messageId, Comment comment) throws Exception {
Properties properties = new Properties();
properties.load(getClass().getClassLoader().getResourceAsStream("/config.properties"));
String userName = properties.getProperty("user");
String password = properties.getProperty("pass");
String url = properties.getProperty("Sqldburl");
int key = 0;
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
Connection conn = DriverManager.getConnection(url, userName, password);
String query = "select count(*) from Comments";
PreparedStatement ps = conn.prepareStatement(query);
ResultSet rs = ps.executeQuery();
rs.next();
key = rs.getInt(1);
} catch (Exception e) {
System.out.println(e);
}
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
Connection conn = DriverManager.getConnection(url, userName, password);
String query = "insert into Comments(id, message, author) values(?,?,?)";
PreparedStatement ps = conn.prepareStatement(query);
ps.setInt(1, key);
ps.setString(2, comment.getMessage());
ps.setString(3, comment.getAuthor());
ps.executeQuery();
} catch (Exception e) {
System.out.println(e);
}
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
Connection conn = DriverManager.getConnection(url, userName, password);
String query = "select * from Comments where messageId=?";
PreparedStatement ps = conn.prepareStatement(query);
ps.setLong(1, messageId);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
comment.setAuthor(rs.getString("Author"));
comment.setId(rs.getInt("Id"));
comment.setMessage(rs.getString("message"));
}
} catch (Exception e) {
System.out.println(e + "b3");
}
return comment;
}
After writing this code, I've realized that Here I'm adding a comment for sure into Comments table, But it is no where linked to the Messages.
I know a way, that is I've create a new column in the Comments table and using join operation, I need to update the same messageId in comments table. But I want to know if there is a better way of getting this done, without using the concept of joins.
In MessageBean, there is a map declared as below.
private Map<Long, Comment> comments = new HashMap<>();
#XmlTransient
public Map<Long, Comment> getComments() {
return comments;
}
public void setComments(Map<Long, Comment> comments) {
this.comments = comments;
}
can I take any advantage of this to avoid join?

Crystal Report doesn't show data when generated

When I generate it on runtime, it doesn't show any data. But it does when I check on the 'Main Report Preview' of VS 2010. I have also checked my stored procedure, it does produce data when I execute it. What seems to be the problem?
This is my code in page_load:
protected void Page_Load(object sender, EventArgs e)
{
string municipio = Request.QueryString["municipio"];
string ano = Request.QueryString["ano"];
string cnpj = Server.UrlDecode(Request.QueryString["cnpj"]);
DataTable dt;
string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
using (SqlConnection cnn = new SqlConnection(CS))
{
cnn.Open();
//stored procedure
SqlCommand cmd = new SqlCommand("spConsultaRelatorioCompleto", cnn);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#ano", ano);
cmd.Parameters.AddWithValue("#municipio", municipio);
cmd.Parameters.AddWithValue("#cnpj", cnpj);
//read access to the database
SqlDataReader dr = cmd.ExecuteReader();
SqlDataAdapter da = new SqlDataAdapter(cmd);
//datatable with data
dt = new DataTable("dt");
//datatable with datareader's data
dt.Load(dr);
da.Fill(dt);
}
ReportDocument MeuRelatorio = new ReportDocument();
MeuRelatorio.Load(Server.MapPath("RelatorioConvenio.rpt"));
MeuRelatorio.SetDataSource(dt);
CrystalReportViewer1.ReportSource = MeuRelatorio;
}
}
}
I give some values in another webform when I click the button below:
protected void btnExport_Click(object sender, EventArgs e)
{
Response.Redirect("RelatorioGerado.aspx?municipio=" + ddlmunicipioconvenente.Text + "&cnpj=" + Server.UrlEncode(tbcnpjconvenente.Text) + "&ano=" + tbAno.Text);
}

Populate a combobox from an array list populated from an SQL statment

I am trying to populate a ComboBox with a list that is populated by a SQL statement.
I tried this:
public void buildData(){
ObservableList<ComboBox> data = FXCollections.observableArrayList();
Connection conn = db.makeConnection();
try{
String SQL = "Select Feature from FeaturesTable Order By Feature";
ResultSet rs = conn.createStatement().executeQuery(SQL);
while(rs.next()){
ComboBox cb = new ComboBox();
cb.featureCombo.set(rs.getString("Feature"));
featureCombo.add(cb);
}
featureCombo.setItems(data);
}
catch(Exception e){
e.printStackTrace();
System.out.println("Error on Building Data");
}
}
I'm getting an error under cb.featureCombo.set of "featureCombo cannot be resolved or is not a field" but featureCombo exists as:
#FXML
private ObservableList<ComboBox> featureCombo;
and then another error under featureCombo.setItems(data); probably because of the same problem.
I'm not set on this method if someone has a better way to do this.
If you desire a ComboBox named featureCombo, you are going to have to declare it as a ComboBox and not as private ObservableList<ComboBox> featureCombo; which is making an ObservableList
Something like
#FXML
ComboBox<String> featureCombo;
Then in your method, you need to make a list of String to populate the ComboBox (you currently have a list of ComboBox)
public void buildData(){
ObservableList<String> data = FXCollections.observableArrayList(); //List of String
Connection conn = db.makeConnection();
try{
String SQL = "Select Feature from FeaturesTable Order By Feature";
ResultSet rs = conn.createStatement().executeQuery(SQL);
while(rs.next()){
data.add(rs.getString("Feature")); //add the String to the list
}
featureCombo.setItems(data); //Set the list of String as the data for your combo box
}
catch(Exception e){
e.printStackTrace();
System.out.println("Error on Building Data");
}
}

How update DB table with DataSet

I am begginer with ADO.NET , I try update table with DataSet.
O client side I have dataset with one table. I send this dataset on service side (it is ASP.NET Web Service).
On Service side I try update table in database, but it dont 't work.
public bool Update(DataSet ds)
{
SqlConnection conn = null;
SqlDataAdapter da = null;
SqlCommand cmd = null;
try
{
string sql = "UPDATE * FROM Tab1";
string connStr = WebConfigurationManager.ConnectionStrings["Employees"].ConnectionString;
conn = new SqlConnection(connStr);
conn.Open();
cmd=new SqlCommand(sql,conn);
da = new SqlDataAdapter(sql, conn);
da.UpdateCommand = cmd;
da.Update(ds.Tables[0]);
return true;
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (conn != null)
conn.Close();
if (da != null)
da.Dispose();
}
}
Where can be problem?
It is better to look how really ADO.Net dataset works.
http://support.microsoft.com/kb/308507