on 08-26-2008 10:31 AM
I'm working on a CR 2008 Add-in.
Usage of this add-in is: Let the user choose from a list of predefined datasets, and create a totally empty report with this dataset attached to is. So the user can create a report based on this dataset.
I have a dataset in memory, and want to create a new report in cr2008.
The new report is a blank report (with no connection information).
If I set the ReportDocument.SetDataSource(Dataset dataSet) property, I get the error:
The report has no tables.
So I must programmatically define the table definition in my blank report.
I found the following article: https://boc.sdn.sap.com/node/869, and came up with something like this:
internal class NewReportWorker : Worker
{
public NewReportWorker(string reportFileName)
: base(reportFileName)
{
}
public override void Process()
{
DatabaseController databaseController = ClientDoc.DatabaseController;
Table table = new Table();
string tabelName = "Table140";
table.Name = tabelName;
table.Alias = tabelName;
table.QualifiedName = tabelName;
table.Description = tabelName;
var fields = new Fields();
var dbField = new DBField();
var fieldName = "ID";
dbField.Description = fieldName;
dbField.HeadingText = fieldName;
dbField.Name = fieldName;
dbField.Type = CrFieldValueTypeEnum.crFieldValueTypeInt64sField;
fields.Add(dbField);
dbField = new DBField();
fieldName = "IDLEGITIMATIEBEWIJS";
dbField.Description = fieldName;
dbField.HeadingText = fieldName;
dbField.Name = fieldName;
dbField.Type = CrFieldValueTypeEnum.crFieldValueTypeInt64sField;
fields.Add(dbField);
// More code for more tables to add.
table.DataFields = fields;
//CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo info =
// new CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo();
//info.Attributes.Add("Databse DLL", "xxx.dll");
//table.ConnectionInfo = info;
// Here an error occurs.
databaseController.AddTable(table, null);
ReportDoc.SetDataSource( [MyFilledDataSet] );
//object path = @"d:\logfiles\";
//ClientDoc.SaveAs("test.rpt", ref path, 0);
}
}
}
The object ClientDoc referes to a ISCDReportClientDocument in a base class:
internal abstract class Worker
{
private ReportDocument _ReportDoc;
private ISCDReportClientDocument _ClientDoc;
private string _ReportFileName;
public Worker(string reportFileName)
{
_ReportFileName = reportFileName;
_ReportDoc = new ReportDocument();
// Load the report from file path passed by the designer.
_ReportDoc.Load(reportFileName);
// Create a RAS Document through In-Proc RAS through the RPTDoc.
_ClientDoc = _ReportDoc.ReportClientDocument;
}
public string ReportFileName
{
get
{
return _ReportFileName;
}
}
public ReportDocument ReportDoc
{
get
{
return _ReportDoc;
}
}
public ISCDReportClientDocument ClientDoc
{
get
{
return _ClientDoc;
}
}
But I get an "Unspecified error" on the line databaseController.AddTable(table, null);
What am i doing wrong? Or is there another way to create a new report based on a DataSet in C# code?
/*****************************************************************
* the following two string values can be modified to reflect your system
************************************************************************************************/
string mdb_path = "C:\\program files\\crystal decisions\\crystal reports 9\\samples\\en\\databases\\xtreme.mdb"; // path to xtreme.mdb file
string xsd_path = "C:\\Crystal\\rasnet\\ras9_csharp_win_datasetreport\\customer.xsd";
OleDbConnection m_connection;
OleDbDataAdapter m_adapter;
System.Data.DataSet m_dataset; /
ReportClientDocument m_crReportDocument; Field m_crFieldCustomer;
Field m_crFieldCountry;
void CreateData()
{
m_connection = new OleDbConnection();
m_connection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + mdb_path;
m_adapter = new OleDbDataAdapter("select * from Customer where Country='Canada'", m_connection);
m_dataset = new System.Data.DataSet();
m_adapter.Fill(m_dataset, "Customer");
// create a schema file
m_dataset.WriteXmlSchema(xsd_path);
}
void AddDataSourceUsingDataSet( ReportClientDocument rcDoc, System.Data.DataSet data)
{
DataSetConverter.AddDataSource(rcDoc, data);
}
void AddDataSourceUsingSchemaFile( ReportClientDocument rcDoc, string schema_file_name, string table_name, System.Data.DataSet data)
{
PropertyBag crLogonInfo; PropertyBag crAttributes; ConnectionInfo crConnectionInfo; CrystalDecisions.ReportAppServer.DataDefModel.Table crTable;
// create logon property
crLogonInfo = new PropertyBag();
crLogonInfo["XML File Path"] = schema_file_name;
// create logon attributes
crAttributes = new PropertyBag();
crAttributes["Database DLL"] = "crdb_adoplus.dll";
crAttributes["QE_DatabaseType"] = "ADO.NET (XML)";
crAttributes["QE_ServerDescription"] = "NewDataSet";
crAttributes["QE_SQLDB"] = true;
crAttributes["QE_LogonProperties"] = crLogonInfo;
// create connection info
crConnectionInfo = new ConnectionInfo();
crConnectionInfo.Kind = CrConnectionInfoKindEnum.crConnectionInfoKindCRQE;
crConnectionInfo.Attributes = crAttributes;
// create a table
crTable = new CrystalDecisions.ReportAppServer.DataDefModel.Table();
crTable.ConnectionInfo = crConnectionInfo;
crTable.Name = table_name;
crTable.Alias = table_name;
// add a table
rcDoc.DatabaseController.AddTable(crTable, null);
// pass dataset
rcDoc.DatabaseController.SetDataSource(DataSetConverter.Convert(data), table_name, table_name);
}
void CreateReport()
{
int iField;
// create ado.net dataset
CreateData();
// create report client document
m_crReportDocument = new ReportClientDocument();
m_crReportDocument.ReportAppServer = "127.0.0.1";
// new report document
m_crReportDocument.New();
AddDataSourceUsingSchemaFile(m_crReportDocument, xsd_path, "Customer",
m_dataset);
iField = m_crReportDocument.Database.Tables[0].DataFields.Find("Customer Name", CrFieldDisplayNameTypeEnum.crFieldDisplayNameName, CeLocale.ceLocaleUserDefault);
m_crFieldCustomer =
(Field)m_crReportDocument.Database.Tables[0].DataFields[iField];
iField = m_crReportDocument.Database.Tables[0].DataFields.Find("Country", CrFieldDisplayNameTypeEnum.crFieldDisplayNameName, CeLocale.ceLocaleUserDefault);
m_crFieldCountry = (Field)m_crReportDocument.Database.Tables[0].DataFields[iField];
m_crReportDocument.DataDefController.ResultFieldController.Add(-1, m_crFieldCustomer);
m_crReportDocument.DataDefController.ResultFieldController.Add(-1, m_crFieldCountry);
// view report
crystalReportViewer1.ReportSource = m_crReportDocument;
}
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
// Create Report
CreateReport();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Alphonse Kouassi,
I think a'm almost there...
I've implemented some code based on your snippet, and now i'm getting an InvalidCastException:
System.InvalidCastException: Specified cast is not valid.
at CrystalDecisions.ReportAppServer.Controllers.DatabaseControllerClass.AddDataSource(Object DataSource)
at CscReportDesigner.NewReportWorker.Process()
at CscReportDesigner.AddInCommandLibrary.doCommand(Int32 CmdID, Object[] arguments)
Is it a big question to ask you for the code of the 'DataSetConverter' that is used in your snippet?!?
I looked into this a little more. Here's working code from my machine, including the cast I think you need:
private void AddTableFromDataSet(ref CrystalDecisions.CrystalReports.Engine.ReportDocument rpt, System.Data.DataSet ds)
{
ISCDReportClientDocument rasReport = rpt.ReportClientDocument;
// Convert the DataSet to an ISCRDataset object (something the ISCDReportClientDocument can understand)
CrystalDecisions.ReportAppServer.DataDefModel.ISCRDataSet rasDS;
rasDS = CrystalDecisions.ReportAppServer.DataSetConversion.DataSetConverter.Convert(ds);
// Add the dataset as a data source to the report
rasReport.DatabaseController.AddDataSource((object)rasDS);
// Add a field to the report canvas
// Note: This is quick and dirty. No positioning, resizing, formatting, etc.
CrystalDecisions.ReportAppServer.Controllers.ISCRResultFieldController rfc;
CrystalDecisions.ReportAppServer.DataDefModel.ISCRTable crTable;
CrystalDecisions.ReportAppServer.DataDefModel.ISCRField crField;
rfc = rasReport.DataDefController.ResultFieldController;
crTable = rasReport.Database.Tables[0];
crField = crTable.DataFields[2]; // Hardcoded field "Customer Name" in the Customer table from Xtreme Sample Database
rfc.Add(-1, crField);
// Save the report template to disk (without data)
//object path = @"c:\documents and settings\administrator\desktop\";
//rasReport.SaveAs("test.rpt", ref path, 0);
//MessageBox.Show("Done!");
}
Let us know whether you're able to get it working.
OK, here is my code until now:
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CrystalDecisions.ReportAppServer.ClientDoc;
using CrystalDecisions.ReportAppServer.Controllers;
using CrystalDecisions.ReportAppServer.DataDefModel;
using CrystalDecisions.ReportAppServer.DataSetConversion;
namespace CscReportDesigner
{
internal class NewReportWorker : Worker
{
public override void Process()
{
NewReportForm newReportForm = new NewReportForm();
newReportForm.ReportFileName = ReportFileName;
newReportForm.ShowDialog();
ReportDataSet = newReportForm.ReportDataSet.Copy();
newReportForm.Close();
ISCRDataSet convertedDataSet = DataSetConverter.Convert( [MyReportDataSet] );
ClientDoc.DatabaseController.AddDataSource((object)convertedDataSet);
ISCRResultFieldController rfc = ClientDoc.DataDefController.ResultFieldController;
ISCRTable crTable = ClientDoc.Database.Tables[0];
ISCRField crField = crTable.DataFields[0];
rfc.Add(-1, crField);
SaveAndClose();
}
}
}
And here the used base class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.ReportAppServer.ClientDoc;
namespace CscReportDesigner
{
internal abstract class Worker : IDisposable
{
private ReportDocument _ReportDoc;
private ISCDReportClientDocument _ClientDoc;
private string _ReportFileName;
public Worker(string reportFileName)
{
//reportFileName = @"d:\Logfiles\BlankReport.rpt";
_ReportFileName = reportFileName;
_ReportDoc = new ReportDocument();
// Load the report from file path passed by the designer.
_ReportDoc.Load(reportFileName);
// Create a RAS Document through In-Proc RAS through the RPTDoc.
_ClientDoc = _ReportDoc.ReportClientDocument;
}
public string ReportFileName
{
get
{
return _ReportFileName;
}
}
public ReportDocument ReportDoc
{
get
{
return _ReportDoc;
}
}
public ISCDReportClientDocument ClientDoc
{
get
{
return _ClientDoc;
}
}
public abstract void Process();
public void SaveAndClose()
{
// The RAS SDK needs to be used to save the temporary report.
_ClientDoc.Save();
// Finally close the report document.
_ClientDoc.Close();
}
public void Dispose()
{
if (_ReportDoc.IsLoaded)
{
_ReportDoc.Close();
}
GC.SuppressFinalize(this);
}
}
}
All seems well, and the DataSet is available in Crystal Reports 2008, and in the Field Explorer are the fields available. But if I want to see a Preview, i get the error message: Invalid Argument provided (twice).
I debugged my code, and the object 'convertedDataSet' in my code is filled with one Table, ane one RowSet. Both are filled with data, so in my opinion it should work...
Hi,
i need to load huge number of records (4,00,000 records) in crystal report in runtime. if follow the below method using DataDefModel.Table and giving table_name the object name in the database (RPT_PROCPLANNEDVSCOMPLETED is the SP in database)., it populates and shows the report in expected time.
CrystalDecisions.ReportAppServer.DataDefModel.Table crTable;
rcDoc.ReportAppServer = "RAS"
rcDoc.New();
crTable = new CrystalDecisions.ReportAppServer.DataDefModel.Table();
CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo crConnectionInfo;
crConnectionInfo = new CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo();
crConnectionInfo = GetADOConnectionInfo(); // Connection propery bag set
crTable.ConnectionInfo = crConnectionInfo;
string table_name;
table_name = "RPT_PROCPLANNEDVSCOMPLETED";
crTable.Name = table_name;
crTable.Alias = table_name;
rcDoc.DatabaseController.AddTable(crTable, null);
now i need to pass dynamic sql query instead of giving object name. hence i followed this method
here DSReport1 is the dataset with dynamic query
xsd_path = Server.MapPath("New.xsd");
CrystalDecisions.ReportAppServer.DataDefModel.Table crTable;
DSReport1.WriteXmlSchema(xsd_path);
rcDoc.ReportAppServer = "RAS"
rcDoc.New();
AddDataSourceUsingSchemaFile(rcDoc, xsd_path, "Views", DSReport1)
//////////////////////////////////////////////////////
void AddDataSourceUsingSchemaFile(ReportClientDocument rcDoc, string schema_file_name, string table_name, System.Data.DataSet data)
{
PropertyBag crLogonInfo; PropertyBag crAttributes;
CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo crConnectionInfo;
CrystalDecisions.ReportAppServer.DataDefModel.Table crTable;
// create logon property
crLogonInfo = new PropertyBag();
crLogonInfo["XML File Path"] = schema_file_name;
// create logon attributes
crAttributes = new PropertyBag();
crAttributes["Database DLL"] = "crdb_adoplus.dll";
crAttributes["QE_DatabaseType"] = "ADO.NET (XML)";
crAttributes["QE_ServerDescription"] = "NewDataSet";
crAttributes["QE_SQLDB"] = true;
crAttributes["QE_LogonProperties"] = crLogonInfo;
// create connection info
crConnectionInfo = new CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo();
crConnectionInfo.Kind = CrConnectionInfoKindEnum.crConnectionInfoKindCRQE;
crConnectionInfo.Attributes = crAttributes;
// create a table
crTable = new CrystalDecisions.ReportAppServer.DataDefModel.Table();
crTable.ConnectionInfo = crConnectionInfo;
table_name = "Views";
crTable.Name = table_name;
crTable.Alias = table_name;
// add a table
rcDoc.DatabaseController.AddTable(crTable, null);
// pass dataset
rcDoc.DatabaseController.SetDataSource(DataSetConverter.Convert(data), table_name, table_name);
}
////////////////////////////////////////////////////////
this method is very slow compared to the above method. it become idle in the line
rcDoc.DatabaseController.SetDataSource(DataSetConverter.Convert(data), table_name, table_name);
any help appriciated
thanks in advance
Padmanaban V
Hai Dennis Dam ,
I also doing the same task what you done.
I try your code using Visual Studio 2005,Asp.Net2.0.
I created those Two classes but i want to know how can we
use these files from .aspx code behind file because i cant
access the file worker.cs and NewReportWorker.cs
from .aspx.cs file. Could you please post the code how to
use this code from .aspx file
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The supplied code is a part of a Crystal Reports 2008 Add-In.
If you look at the document Crystal Reports 2008 Creating Custom Add-Ins (can be found on https://boc.sdn.sap.com/node/6011 ), you will see how my full c# project is build up.
The add-in has the following functionality:
- The user opens Crystal Report 2008
- Opens a new blank report (otherwise the custom add-ins are not available).
- The user starts the add-in, and the add-in comes with a list of available datasets (in our system it is a predefined set of datasets as a 'layer' on our database, we don't want the user to have access to the database. Also because the database can be a sql server or for example an oracle one).
- The user selects a dataset, the add-in gets n rows out of the database.
- The user can now create a crystal report based on this dataset.
I'm not working from a asp.net project. So a cannot give you any asp.net code that works.
A tip should be to download the document, and read it. Maybe this helps you with your problem.
Another thing you should be ware of is that somethings are done with COM (I'm not sure of this exactly).
And using COM from an asp.net page is not as easy as it looks, from a security point of view (the account asp.net is running on, does not have enough rights to use COM on the machine its running on).
Hopefully this helps you a little (or much).
Hai Dennis Dam,
Thanks for your good response. Actualy i download that file but it had only peace of code.
What i expect is during design time i just create a blank
crystal report during runtime i fill the records into DataSet
object with the help of SqlDataAdapter. Then i want to show these records into the crystal report viewer.
But the problem is crystal report is blank then how can i add the records.
Could you please post source for this purpose
Tools i'm using VisualStudio 2005-C#,SQL Server 2005 and Crystal Report 11.5
This is my urgnt work could you please post complete
source code.
Thanks in advance
Edited by: winseelan j on Aug 29, 2008 1:55 PM
Edited by: winseelan j on Aug 29, 2008 1:56 PM
If you have a blank report at design time (with no fields at all on the report), you can set the dataset to your report at runtime, but you also have to place the fields to the report itself by code.
Take the code from the thread that starts with Finally here the code that works for me....
And put the next code after the line: "ClientDoc.DatabaseController.AddTable(table, null);"
ISCRResultFieldController rfc = ClientDoc.DataDefController.ResultFieldController;
ISCRTable crTable = ClientDoc.Database.Tables[0];
ISCRField crField = crTable.DataFields[0];
rfc.Add(-1, crField);
Then the end of the code looks like this:
// Convert 'my table' to a crystal report table.
ISCRTable table = DataSetConverter.Convert(reportDataSet).Tables[0];
table.ConnectionInfo = connectionInfo;
ClientDoc.DatabaseController.AddTable(table, null);
ISCRResultFieldController rfc = ClientDoc.DataDefController.ResultFieldController;
ISCRTable crTable = ClientDoc.Database.Tables[0];
ISCRField crField = crTable.DataFields[0];
rfc.Add(-1, crField);
SaveAndClose();
If you do this all in an add-in for crystal report, you will get an report with one field in the details section.
Hi Pascal,
You have to use the code from the post I made on aug 28, 2008 4:45 PM which start with the text 'Finally here the code that works for me....'.
With this code you save the used DataSet to disk with the code line:
reportDataSet.WriteXml(tempFileName, XmlWriteMode.WriteSchema);
This line will save the dataset with the schema witch include all table names and table fields names to your disk.
After that the saved file will be used as reportsource (the actual data) for your report with the code line:
logonInfo.Add("XML File Path", tempFileName);
And finally the original DataSet will be used to add a table to your report with the code lines:
ISCRTable table = DataSetConverter.Convert(reportDataSet).Tables[0];
table.ConnectionInfo = connectionInfo;
ClientDoc.DatabaseController.AddTable(table, null);
You DO NOT need to use the code that I've posted on Aug 28, 2008 10:59 AM starting with the text 'Hi Alphonse, The last code i posted...'.
So the method i've discribed in that port called 'private Table GetBurgelijkeStaatTable(string tableName)' is not part of the final code. You do not need to 'make' a table in code representing your own dataset.
Hope this helps you...
Finally here the code that works for me....
internal class NewReportWorker : Worker
{
public override void Process()
{
var reportDataSet = [MYDATASET];
// Save the dataset with schema to a temporary file.
var tempFileName = Path.GetTempFileName() + ".xml";
reportDataSet.WriteXml(tempFileName, XmlWriteMode.WriteSchema);
PropertyBag logonInfo = new PropertyBag();
logonInfo.EnsureCapacity(1);
logonInfo.Add("XML File Path", tempFileName);
PropertyBag attributes = new PropertyBag();
attributes.EnsureCapacity(5);
attributes.Add("Database DLL", "crdb_adoplus.dll");
attributes.Add("QE_DatabaseType", "ADO.NET (XML)");
attributes.Add("QE_ServerDescription", "NewDataSet");
attributes.Add("QE_SQLDB", true);
attributes.Add("QE_LogonProperties", logonInfo);
ConnectionInfo connectionInfo = new ConnectionInfo();
connectionInfo.Kind = CrConnectionInfoKindEnum.crConnectionInfoKindCRQE;
connectionInfo.Attributes = attributes;
// Convert 'my table' to a crystal report table.
ISCRTable table = DataSetConverter.Convert(reportDataSet).Tables[0];
table.ConnectionInfo = connectionInfo;
ClientDoc.DatabaseController.AddTable(table, null);
SaveAndClose();
}
}
internal abstract class Worker : IDisposable
{
private ReportDocument _ReportDoc;
private ISCDReportClientDocument _ClientDoc;
private string _ReportFileName;
public Worker(string reportFileName)
{
_ReportFileName = reportFileName;
_ReportDoc = new ReportDocument();
// Load the report from file path passed by the designer.
_ReportDoc.Load(reportFileName);
// Create a RAS Document through In-Proc RAS through the RPTDoc.
_ClientDoc = _ReportDoc.ReportClientDocument;
}
public string ReportFileName
{
get { return _ReportFileName; }
}
public ReportDocument ReportDoc
{
get { return _ReportDoc; }
}
public ISCDReportClientDocument ClientDoc
{
get { return _ClientDoc; }
}
public abstract void Process();
public void SaveAndClose()
{
// The RAS SDK needs to be used to save the temporary report.
_ClientDoc.Save();
// Finally close the report document.
_ClientDoc.Close();
}
public void Dispose()
{
if (_ReportDoc.IsLoaded)
{
_ReportDoc.Close();
}
GC.SuppressFinalize(this);
}
}
Problem solved. Thanx anyone who replied on this thread.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
i need to load huge number of records (4,00,000 records) in crystal report in runtime. if follow the below method using DataDefModel.Table and giving table_name the object name in the database (RPT_PROCPLANNEDVSCOMPLETED is the SP in database)., it populates and shows the report in expected time.
CrystalDecisions.ReportAppServer.DataDefModel.Table crTable;
rcDoc.ReportAppServer = "RAS"
rcDoc.New();
crTable = new CrystalDecisions.ReportAppServer.DataDefModel.Table();
CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo crConnectionInfo;
crConnectionInfo = new CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo();
crConnectionInfo = GetADOConnectionInfo(); // Connection propery bag set
crTable.ConnectionInfo = crConnectionInfo;
string table_name;
table_name = "RPT_PROCPLANNEDVSCOMPLETED";
crTable.Name = table_name;
crTable.Alias = table_name;
rcDoc.DatabaseController.AddTable(crTable, null);
........................................................................................................................................
now i need to pass dynamic sql query instead of giving object name. hence i followed this method
here DSReport1 is the dataset with dynamic query
xsd_path = Server.MapPath("New.xsd");
CrystalDecisions.ReportAppServer.DataDefModel.Table crTable;
DSReport1.WriteXmlSchema(xsd_path);
rcDoc.ReportAppServer = "RAS"
rcDoc.New();
AddDataSourceUsingSchemaFile(rcDoc, xsd_path, "Views", DSReport1)
//////////////////////////////////////////////////////
void AddDataSourceUsingSchemaFile(ReportClientDocument rcDoc, string schema_file_name, string table_name, System.Data.DataSet data)
{
PropertyBag crLogonInfo; PropertyBag crAttributes;
CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo crConnectionInfo;
CrystalDecisions.ReportAppServer.DataDefModel.Table crTable;
// create logon property
crLogonInfo = new PropertyBag();
crLogonInfo\"XML File Path\" = schema_file_name;
// create logon attributes
crAttributes = new PropertyBag();
crAttributes\"Database DLL\" = "crdb_adoplus.dll";
crAttributes\"QE_DatabaseType\" = "ADO.NET (XML)";
crAttributes\"QE_ServerDescription\" = "NewDataSet";
crAttributes\"QE_SQLDB\" = true;
crAttributes\"QE_LogonProperties\" = crLogonInfo;
// create connection info
crConnectionInfo = new CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo();
crConnectionInfo.Kind = CrConnectionInfoKindEnum.crConnectionInfoKindCRQE;
crConnectionInfo.Attributes = crAttributes;
// create a table
crTable = new CrystalDecisions.ReportAppServer.DataDefModel.Table();
crTable.ConnectionInfo = crConnectionInfo;
table_name = "Views";
crTable.Name = table_name;
crTable.Alias = table_name;
// add a table
rcDoc.DatabaseController.AddTable(crTable, null);
// pass dataset
rcDoc.DatabaseController.SetDataSource(DataSetConverter.Convert(data), table_name, table_name);
}
////////////////////////////////////////////////////////
this method is very slow compared to the above method. it become idle in the line
rcDoc.DatabaseController.SetDataSource(DataSetConverter.Convert(data), table_name, table_name);
any help appriciated
thanks in advance
Padmanaban V
To Ted Ueda, TristaL and Alphonse Kouassi.
Where did you all get this knowledge. I searched google, the forum and crystal reports website, but cannot find any information about all of this...
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
We work here.
The great majority of DataSet data "push" use cases has reports being designed in Crystal Reports Designer or the Embedded Designer in Visual Studio.
So there won't be a lot of examples of what you're trying to do out there.
Except this and few other posts here on this forum.
Sincerely,
Ted Ueda
Hai Ted Ueda
Actualy past 3 weeks to try to find the
solution for this work, but i cant get any good solution,
but i believe this thread will solve my problem but here
lot of pieces of codes is there, could you please post
the complete source,please this is my urgent work.
Tools i'm using VisualStudio 2005-C#,SQL Server 2005
and Crystal Report 11.5
Thanks in Advance.
Edited by: winseelan j on Aug 29, 2008 2:27 PM
Hi,
In your code I cannot see any implementation of the PropertyBags as Logon Attributes for the ConnectionInfo. This might be at the origin of the issue. I will advise you to review the code in considering the implementation of the PropertyBags. Here is again another version of the code I previously sent to you.
//======================================================================
// Dataset
OleDbConnection m_connection; // ado.net connection
OleDbDataAdapter m_adapter; // ado.net data adapter
System.Data.DataSet m_dataset; // ado.net dataset
// *** NOTE ***
// ASPNET_wp user needs read permission to mdb_path, and both read and write permission to xsd_path
//Set the path to your database
string mdb_path =@"D:\Program Files\Business Objects\Crystal Reports 11\Samples\en\Databases\xtreme.mdb";
//Set the path to where the customer schema file will be created
string xsd_path = "D:\\WINNT\\Temp\\customer.xsd";
// CR variables
ReportClientDocument m_crReportDocument; // report client document
PropertyBag m_crLogonInfo; // logon info
PropertyBag m_crAttributes; // logon attributes
ConnectionInfo m_crConnectionInfo; // connection info
CrystalDecisions.ReportAppServer.DataDefModel.Table m_crTable; // table
int iField;
Field m_crFieldCustomer;
protected CrystalDecisions.Web.CrystalReportViewer CrystalReportViewer1; // customer field
Field m_crFieldCountry; // country field
private void Page_Load(object sender, System.EventArgs e)
{
CreateReport();
}
void CreateData()
{
// Create OLEDB connection
m_connection = new OleDbConnection();
m_connection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + mdb_path;
// Create Data Adapter
m_adapter = new OleDbDataAdapter("select * from Customer where Country='Canada'", m_connection);
// create dataset and fill
m_dataset = new System.Data.DataSet();
m_adapter.Fill(m_dataset, "Customer");
// create a schema file
m_dataset.WriteXmlSchema(xsd_path);
}
void CreateReport()
{
// create ado.net dataset
CreateData();
// create report client document
m_crReportDocument = new ReportClientDocument();
// set RAS server location
m_crReportDocument.ReportAppServer = "localhost";
// new report document
m_crReportDocument.New();
// create logon property
m_crLogonInfo = new PropertyBag();
m_crLogonInfo["XML File Path"] = xsd_path;
// create logon attributes
m_crAttributes = new PropertyBag();
m_crAttributes["Database DLL"] = "crdb_adoplus.dll";
m_crAttributes["QE_DatabaseType"] = "ADO.NET (XML)";
m_crAttributes["QE_ServerDescription"] = "NewDataSet";
m_crAttributes["QE_SQLDB"] = true;
m_crAttributes["QE_LogonProperties"] = m_crLogonInfo;
// create connection info
m_crConnectionInfo = new ConnectionInfo();
m_crConnectionInfo.Kind = CrConnectionInfoKindEnum.crConnectionInfoKindCRQE;
m_crConnectionInfo.Attributes = m_crAttributes;
// create a table
m_crTable = new CrystalDecisions.ReportAppServer.DataDefModel.Table();
m_crTable.ConnectionInfo = m_crConnectionInfo;
m_crTable.Name = "Customer";
m_crTable.Alias = "Customer";
// add a table
m_crReportDocument.DatabaseController.AddTable(m_crTable, null);
// grab customer name and country field
iField = m_crReportDocument.Database.Tables[0].DataFields.Find("Customer Name", CrFieldDisplayNameTypeEnum.crFieldDisplayNameName, CeLocale.ceLocaleUserDefault);
m_crFieldCustomer = (Field)m_crReportDocument.Database.Tables[0].DataFields[iField];
iField = m_crReportDocument.Database.Tables[0].DataFields.Find("Country", CrFieldDisplayNameTypeEnum.crFieldDisplayNameName, CeLocale.ceLocaleUserDefault);
m_crFieldCountry = (Field)m_crReportDocument.Database.Tables[0].DataFields[iField];
// add customer name and country field
m_crReportDocument.DataDefController.ResultFieldController.Add(-1, m_crFieldCustomer);
m_crReportDocument.DataDefController.ResultFieldController.Add(-1, m_crFieldCountry);
// pass dataset to report
m_crReportDocument.DatabaseController.SetDataSource(DataSetConverter.Convert(m_dataset), "Customer", "Customer");
// view report
CrystalReportViewer1.ReportSource = m_crReportDocument;
}
//=======================================================================
Try and make it work first before using in your project.
Cheers
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Alphonse,
The last code i posted was based on another reply in this thread posted by TristaL.
That is another way to do it, based on the provided dataset.
But in the mean time I tried it 'your way':
public override void Process()
{
var reportDataSet = [MYDATASET];
// Writing the dataset to an xml file with schema information.
var tempFileName = Path.GetTempFileName();
tempFileName += ".xml";
reportDataSet.WriteXml(tempFileName, XmlWriteMode.WriteSchema);
var logonInfo = new PropertyBag();
logonInfo.Add("XML File Path", tempFileName);
var attributes = new PropertyBag();
attributes.Add("Database DLL", "crdb_adoplus.dll");
attributes.Add("QE_DatabaseType", "ADO.NET (XML)");
attributes.Add("QE_ServerDescription", "NewDataSet");
attributes.Add("QE_SQLDB", true);
attributes.Add("QE_LogonProperties", logonInfo);
var connectionInfo = new CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo();
connectionInfo.Kind = CrConnectionInfoKindEnum.crConnectionInfoKindCRQE;
connectionInfo.Attributes = attributes;
string tableName = reportDataSet.Tables[0].TableName;
// Get the table definition exactly like the definition of my own dataset.
Table table = GetBurgelijkeStaatTable(tableName);
table.ConnectionInfo = connectionInfo;
ClientDoc.DatabaseController.AddTable(table, null);
// EDITED BY DENNIS DAM 28 AUG 2008 15:24 *****************************************/
//These two lines are to much... And resulted in the two 'Invalid Argument provided' errors
//ISCRDataSet convertedDataSet = DataSetConverter.Convert(reportDataSet);
//ClientDoc.DatabaseController.SetDataSource(convertedDataSet, tableName, tableName);
// ABOVE EDITED BY DENNIS DAM 28 AUG 2008 15:24 *****************************************/
SaveAndClose();
}
private Table GetBurgelijkeStaatTable(string tableName)
{
Table table = new Table();
table.Name = tableName;
table.Alias = tableName;
table.QualifiedName = tableName;
table.Description = tableName;
var fields = new Fields();
var dbField = new DBField();
//<xs:element name="ID" msprop:REQUIRED="False" type="xs:long" minOccurs="0" />
var fieldName = "ID";
dbField.Description = fieldName;
dbField.HeadingText = fieldName;
dbField.Name = fieldName;
dbField.Type = CrFieldValueTypeEnum.crFieldValueTypeInt64sField;
fields.Add(dbField);
//<xs:element name="OMSCHRIJVING" msprop:REQUIRED="False" type="xs:string" minOccurs="0" />
dbField = new DBField();
fieldName = "OMSCHRIJVING";
dbField.Description = fieldName;
dbField.HeadingText = fieldName;
dbField.Name = fieldName;
dbField.Type = CrFieldValueTypeEnum.crFieldValueTypeStringField;
fields.Add(dbField);
table.DataFields = fields;
return table;
}
And to make it all complete, here's my xml file:
<?xml version="1.0" standalone="yes"?>
<NewDataSet>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:msprop="urn:schemas-microsoft-com:xml-msprop">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:Locale="" msprop:DataSetNr="114">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="BURGELIJKESTAAT" msdata:Locale="">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" msprop:REQUIRED="False" type="xs:long" minOccurs="0" />
<xs:element name="OMSCHRIJVING" msprop:REQUIRED="False" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<BURGELIJKESTAAT>
<ID>1</ID>
<OMSCHRIJVING>Ongehuwd en geen geregistreerd partner en nooit gehuwd of geregistreerd partner geweest</OMSCHRIJVING>
</BURGELIJKESTAAT>
<BURGELIJKESTAAT>
<ID>2</ID>
<OMSCHRIJVING>Gehuwd</OMSCHRIJVING>
</BURGELIJKESTAAT>
<BURGELIJKESTAAT>
<ID>3</ID>
<OMSCHRIJVING>Gescheiden</OMSCHRIJVING>
</BURGELIJKESTAAT>
<BURGELIJKESTAAT>
<ID>4</ID>
<OMSCHRIJVING>Weduwe/weduwnaar</OMSCHRIJVING>
</BURGELIJKESTAAT>
<BURGELIJKESTAAT>
<ID>5</ID>
<OMSCHRIJVING>Geregistreerd partner</OMSCHRIJVING>
</BURGELIJKESTAAT>
<BURGELIJKESTAAT>
<ID>6</ID>
<OMSCHRIJVING>Gescheiden geregistreerd partner</OMSCHRIJVING>
</BURGELIJKESTAAT>
<BURGELIJKESTAAT>
<ID>7</ID>
<OMSCHRIJVING>Achtergebleven geregistreerd partner</OMSCHRIJVING>
</BURGELIJKESTAAT>
<BURGELIJKESTAAT>
<ID>9</ID>
<OMSCHRIJVING>Ongehuwd en geen geregistreerd partner, eventueel wel gehuwd of geregistreerd partner geweest</OMSCHRIJVING>
</BURGELIJKESTAAT>
</NewDataSet>
If I connect to the xml file with CR2008 thru the Database Expert >> Create New Connection >> ADO.NET (XML) >> And only fill the 'File Path:' textbox. >> Finish. >> Select the table. And it works including the Preview of the report.
But!!!
If I do this all with the add-in, I still get the error 'Invalid Argument provided' (twice) when I want to preview my report.
Edited by: Dennis Dam on Aug 28, 2008 3:20 PM
This methods works now... There were two lines in my code that were to much.
//ISCRDataSet convertedDataSet = DataSetConverter.Convert(reportDataSet);
//ClientDoc.DatabaseController.SetDataSource(convertedDataSet, tableName, tableName);
The only thing I have to do now is take the xml data and make a CrystalReports Table based on that data.
I have nothing to add to Ted's answer.
Cheers
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi,
Have a look at the snippet code below written for version 9 that you might accommodate to CR 2008, it demonstrates how to create a report based on a DataSet programmatically.
//=========================================================================
/************************************************************************************************
+ * the following two string values can be modified to reflect your system+
+ ************************************************************************************************/+
+ string mdb_path = "C:
program files
crystal decisions
crystal reports 9
samples
en
databases
xtreme.mdb"; // path to xtreme.mdb file+
+ string xsd_path = "C:
Crystal
rasnet
ras9_csharp_win_datasetreport
customer.xsd"; // path to customer schema file+
+ // Dataset+
+ OleDbConnection m_connection; // ado.net connection+
+ OleDbDataAdapter m_adapter; // ado.net adapter+
+ System.Data.DataSet m_dataset; // ado.net dataset+
+ // CR variables+
+ ReportClientDocument m_crReportDocument; // report client document+
+ Field m_crFieldCustomer;+
+ Field m_crFieldCountry;+
+ void CreateData()+
+ {+
+ // Create OLEDB connection+
+ m_connection = new OleDbConnection();+
+ m_connection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + mdb_path;+
+ // Create Data Adapter+
+ m_adapter = new OleDbDataAdapter("select * from Customer where Country='Canada'", m_connection);+
+ // create dataset and fill+
+ m_dataset = new System.Data.DataSet();+
+ m_adapter.Fill(m_dataset, "Customer");+
+ // create a schema file+
+ m_dataset.WriteXmlSchema(xsd_path);+
+ }+
+ // Adds a DataSource using dataset. Since this does not require intermediate schema file, this method+
+ // will work in a distributed environment where you have IIS box on server A and RAS Server on server B.+
+ void AddDataSourceUsingDataSet(+
+ ReportClientDocument rcDoc, // report client document+
+ System.Data.DataSet data) // dataset+
+ {+
+ // add a datasource+
+ DataSetConverter.AddDataSource(rcDoc, data);+
+ }+
+ // Adds a DataSource using a physical schema file. This method require you to have schema file in RAS Server+
+ // box (NOT ON SDK BOX). In distributed environment where you have IIS on server A and RAS on server B,+
+ // and you execute CreateData above, schema file is created in IIS box, and this method will fail, because+
+ // RAS server cannot see that schema file on its local machine. In such environment, you must use method+
+ // above.+
+ void AddDataSourceUsingSchemaFile(+
+ ReportClientDocument rcDoc, // report client document+
+ string schema_file_name, // xml schema file location+
+ string table_name, // table to be added+
+ System.Data.DataSet data) // dataset+
+ {+
+ PropertyBag crLogonInfo; // logon info+
+ PropertyBag crAttributes; // logon attributes+
+ ConnectionInfo crConnectionInfo; // connection info+
+ CrystalDecisions.ReportAppServer.DataDefModel.Table crTable;+
+ // database table+
+ // create logon property+
+ crLogonInfo = new PropertyBag();+
+ crLogonInfo["XML File Path"] = schema_file_name;+
+ // create logon attributes+
+ crAttributes = new PropertyBag();+
+ crAttributes["Database DLL"] = "crdb_adoplus.dll";+
+ crAttributes["QE_DatabaseType"] = "ADO.NET (XML)";+
+ crAttributes["QE_ServerDescription"] = "NewDataSet";+
+ crAttributes["QE_SQLDB"] = true;+
+ crAttributes["QE_LogonProperties"] = crLogonInfo;+
+ // create connection info+
+ crConnectionInfo = new ConnectionInfo();+
+ crConnectionInfo.Kind = CrConnectionInfoKindEnum.crConnectionInfoKindCRQE;+
+ crConnectionInfo.Attributes = crAttributes;+
+ // create a table+
+ crTable = new CrystalDecisions.ReportAppServer.DataDefModel.Table();+
+ crTable.ConnectionInfo = crConnectionInfo;+
+ crTable.Name = table_name;+
+ crTable.Alias = table_name;+
+ // add a table+
+ rcDoc.DatabaseController.AddTable(crTable, null);+
+ // pass dataset+
+ rcDoc.DatabaseController.SetDataSource(DataSetConverter.Convert(data), table_name, table_name);+
+ }+
+ void CreateReport()+
+ {+
+ int iField;+
+ // create ado.net dataset+
+ CreateData();+
+ // create report client document+
+ m_crReportDocument = new ReportClientDocument();+
+ m_crReportDocument.ReportAppServer = "127.0.0.1";+
+ // new report document+
+ m_crReportDocument.New();+
+ // add a datasource using a schema file+
+ // note that if you have distributed environment, you should use AddDataSourceUsingDataSet method instead.+
+ // for more information, refer to comments on these methods.+
+ AddDataSourceUsingSchemaFile(m_crReportDocument, xsd_path, "Customer", m_dataset);+
+ +
+ // get Customer Name and Country fields+
+ iField = m_crReportDocument.Database.Tables[0].DataFields.Find("Customer Name", CrFieldDisplayNameTypeEnum.crFieldDisplayNameName, CeLocale.ceLocaleUserDefault);+
+ m_crFieldCustomer = (Field)m_crReportDocument.Database.Tables[0].DataFields[iField];+
+ iField = m_crReportDocument.Database.Tables[0].DataFields.Find("Country", CrFieldDisplayNameTypeEnum.crFieldDisplayNameName, CeLocale.ceLocaleUserDefault);+
+ m_crFieldCountry = (Field)m_crReportDocument.Database.Tables[0].DataFields[iField];+
+ // add Customer Name and Country fields+
+ m_crReportDocument.DataDefController.ResultFieldController.Add(-1, m_crFieldCustomer);+
+ m_crReportDocument.DataDefController.ResultFieldController.Add(-1, m_crFieldCountry);+
+ // view report+
+ crystalReportViewer1.ReportSource = m_crReportDocument;+
+ }+
+ public Form1()+
+ {+
+ //+
+ // Required for Windows Form Designer support+
+ //+
+ InitializeComponent();+
+ // Create Report+
+ CreateReport();+
+ //+
+ // TODO: Add any constructor code after InitializeComponent call+
+ //+
+ }+//=========================================================================
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
In my experience that oh-so-descriptive "Unspecified error" usually means the report engine is missing a piece of information it needs to connect to the data source - usually a connection attribute of some sort.
Looking at your code, at least part of the issue might be with the lines you've commented out which set the database DLL. A blank report won't automatically know which database driver you want to use for a newly-added table. The DLL for connecting to a .NET dataset is crdb_adoplus.dll.
Side note: Is there just one table in your dataset? If not, I would recommend sticking with a single table, preferably as a permanent solution but at least until you've got the code working, anyway.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Changed the code to:
fields.Add(dbField);
table.DataFields = fields;
CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo info
= new CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo();
var props = new PropertyBag();
props.Add("Database DLL", "crdb_adoplus.dll");
info.Attributes = props;
table.ConnectionInfo = info;
databaseController.AddTable(table, null);
But still I get the 'Unspecified error'.
I added some debugging code, and found a more specific error message (more or less):
System.Runtime.InteropServices.COMException (0x80004005): Unspecified error
at CrystalDecisions.ReportAppServer.Controllers.DatabaseControllerClass.AddTable(ISCRTable Table, Object RelatedTableLinks)
at CscReportDesigner.NewReportWorker.Process()
at CscReportDesigner.AddInCommandLibrary.doCommand(Int32 CmdID, Object[] arguments)
Edited by: Dennis Dam on Aug 27, 2008 12:05 PM
User | Count |
---|---|
90 | |
10 | |
10 | |
10 | |
7 | |
7 | |
6 | |
5 | |
4 | |
3 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.