cancel
Showing results for 
Search instead for 
Did you mean: 

How to create a report based on a DataSet programatically

Former Member
0 Kudos

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?

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos
/*****************************************************************
		 * 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
			//
		}
Former Member
0 Kudos

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?!?

ted_ueda
Employee
Employee
0 Kudos

CrystalDecisions.ReportAppServer.DataSetConversion.DataSetConverter

It's a Utility conversion class that converts a ADO.NET DataSet to a ISCRDataSet (internal data set format).

Sincerely,

Ted Ueda

Former Member
0 Kudos

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.

Former Member
0 Kudos

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...

Former Member
0 Kudos

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

Answers (7)

Answers (7)

Former Member
0 Kudos

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

Former Member
0 Kudos

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).

Former Member
0 Kudos

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

Former Member
0 Kudos

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.

Former Member
0 Kudos

Hi Dennis,

did you ever manage to change the field texts displayed in the field explorer. Using your sample, the visible field tags are only ID [ID] and OMSCHRIJVING [OMSCHRIJVING].

Thanks for any hint,

Pascal

Edited by: Pascal Schmidt-Volkmar on Sep 30, 2008 9:58 AM

Former Member
0 Kudos

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...

Former Member
0 Kudos

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.

Former Member
0 Kudos

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

former_member183750
Active Contributor
0 Kudos

Please post in a new thread. This appears to be a different issue that the one described in the original post. For more details, see the [Rules of Engagement|https://www.sdn.sap.com/irj/sdn/wiki?path=/display/home/rulesofEngagement]

Ludek

Former Member
0 Kudos

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...

ted_ueda
Employee
Employee
0 Kudos

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

Former Member
0 Kudos

That explains alot Thanx to you all...

Former Member
0 Kudos

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

Former Member
0 Kudos

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

Former Member
0 Kudos

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.

Former Member
0 Kudos

I have nothing to add to Ted's answer.

Cheers

Former Member
0 Kudos

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+

+ //+

+ }+//=========================================================================

Former Member
0 Kudos

Hi Alphonse Kouassi,

Can you please post your code between the Markup language <place here your code>

ps. with the markup without the spaces between '{' and 'code' and '}'

Former Member
0 Kudos

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.

Former Member
0 Kudos

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