How to dynamically set the datasource for subreports with an Active Reports 13 rdlx report - datasource

I have an Active Reports 13 report defined using the rdlx format. The report also contains a number of sub-reports.
When defined in the report designer the data source is set to some test data, however, when the report is embedded in a WPF application we wish to update the location of the database pragmatically.
We have been able to update the data source for the main report, but it is not clear (to us!) how to update the data source for the sub-reports.
string report = _reportPath;
// checked the report file exists ...
if (File.Exists(report))
{
// create and setup the data source
// create an empty page report
GrapeCity.ActiveReports.PageReport def = new GrapeCity.ActiveReports.PageReport();
//load the report layout
def.Load(new System.IO.FileInfo(report));
//setup the dataset
GrapeCity.ActiveReports.PageReportModel.DataSource myDataSource = def.Report.DataSources[0];
def.Report.DataSources[0].ConnectionProperties.DataProvider = "OLEDB";
def.Report.DataSources[0].ConnectionProperties.ConnectString = #"RunData.mdb;provider=Microsoft.Jet.OLEDB.4.0;";
// loop through subreports and set the location of the run data database
// ????
reportViewer.LoadDocument(def.Document);
}
Does anyone have some pointers to how we should be writing the code at "????" above to also update the subreports?

This is done in an event on the report document LocateDataSource
Also, please refer to this sample to see how the LocateDataSource is being used: DataSet DataSource. You can access the sample application by downloading a trial of ActiveReports 13 here.
Best,
GrapeCity Support Team

Related

PowerBI API Clone Report and Dataset changing the datasource

I am developing an application in .NET6 using the PoweBI Client for managing workspaces, reports, datasets, etc.
The idea is that the application will be able to create client workspaces and will inherit reports and datasets from a main workspace. In the main workspace there will be reports published from PowerBI Desktop and therefore the respective dataset will be also there.
At the moment of the clone datasource database, user and password should be changed accordantly to match the workspace customer context. Using the following code I can list the reports on the main workspace (workspace_from_id) and I can create them on customer workspace (workspace_towa_id)
var reports_from = pbiClient.Reports.GetReports(workspace_from_id);
foreach (Report report_from in reports_from.Value)
{
Guid report_from_id = report_from.Id;
CloneReportRequest cloneReportRequest = new();
cloneReportRequest.TargetWorkspaceId = workspace_towa_id;
cloneReportRequest.TargetModelId = dataset_towa.Id;
cloneReportRequest.Name = report_from.Name;
Report report_towa = pbiClient.Reports.CloneReport(workspace_from_id, report_from_id, cloneReportRequest);
}
The problem of the above code is that the dataset is not cloned and the source dataset is used as shared dataset for both workspaces. I tried already to copy the dataset details and create a new one with different database using the following code:
CreateDatasetRequest createDatasetRequest = new();
createDatasetRequest.Name = dataset_from.Name;
createDatasetRequest.Datasources = new List<Datasource>();
createDatasetRequest.Tables = new List<Table>();
Datasources datasources_from = pbiClient.Datasets.GetDatasources(workspace_from_id, dataset_from_id);
foreach (Datasource datasource_from in datasources_from.Value)
{
//FOREACH DATASOURCE IN DATASET
Datasource datasource_towa = new ();
datasource_towa.Name = datasource_from.Name;
datasource_towa.DatasourceType = datasource_from.DatasourceType;
//CHANGE DATASOURCE CONNECTION DETAILS
DatasourceConnectionDetails datasourceConnectiondetails = datasource_from.ConnectionDetails;
datasourceConnectiondetails.Database = $"{Variables.reporting_db}_{group_towa.Name.ToLower()}";
datasource_towa.ConnectionDetails = datasourceConnectiondetails;
datasource_towa.ConnectionString = datasource_from.ConnectionString;
datasource_towa.GatewayId = datasource_from.GatewayId;
//ADD DATASOURCE INTO DATASET
createDatasetRequest.Datasources.Add(datasource_towa);
}
Tables tables_from = pbiClient.Datasets.GetTables(workspace_from_id, dataset_from_id); //WORKS FOR PUSH DATASET
foreach (Table table_from in tables_from.Value)
{
//FOREACH TABLE IN DATASET
Table table_towa = new ();
table_towa.Name = table_from.Name;
table_towa.Source = table_from.Source;
table_towa.Columns = table_from.Columns;
table_towa.Rows = table_from.Rows;
table_towa.Description = table_from.Description;
//ADD TABLE INTO DATASET
createDatasetRequest.Tables.Add(table_from);
}
The problem with the above code is that the pbiClient.Datasets.GetTables function is not working for normal datasets but is used only for push datasets. Finally without beeing able to get the Tables the following code is failing:
var dataset_towa = pbiClient.Datasets.PostDataset(workspace_towa_id, createDatasetRequest);
Finally discovered that also the pbiClient.Datasets.PostDataset method is used to post push dataset as described here: https://learn.microsoft.com/en-us/rest/api/power-bi/push-datasets/datasets-post-dataset
=======UPDATE 13/01/2023=======
Tried already a few other ways to clone the report and dataset like to create a datasource but for that we need a data gateway. In that case when the reports are already into a cloud like Azure for PostgreSQL we do need a gateway. On the other side I tried to create a Virtual Gateway in order to create datasource into this Gateway, but =Virtual Gateway is not supported by PowerBI Api and is only supported in premium capacities.
So seems that I cannot clone report together with a dataset and change the datasource.
Any ideas?
After a lot of hours researching I managed to download report from main workspace and upload them into customer workpaces by changing the datasource details.
Steps to perform:
Export report with PowerBI API /Export as stream into memory
Import report with PowerBI API /Imports as stream from memory (needs special treat to be sure that you read the whole stream from the HTTP Content / using SDK is not working)
Update report ConnectionDetails with PowerBI Client SDK /pbiClient.Datasets.UpdateDatasourcesInGroup (needs special treat to change only the server and database attribute without putting new instance of object)
Update datasource of the dataset with PowerBI Client SDK /pbiClient.Gateways.UpdateDatasource (needs special treat to give credentials as JSON)

Export SSRS report in pdf format from SSIS

I've a situation, where I need to export a report from my report server to my local in pdf format through SSIS package.
This can be done from a Script Task. An example of this is below with C# as the language used.
Add an HTTP Connection Manager. For the Server URL enter the url for the report server. You find this in Reporting Services Configuration Manager on the Web Service URL pane. Make sure to use credentials with the appropriate privileges. I recommend testing and verifying the before proceeding.
Add a C# Script Task with the code below. The ServerURL property will be the as follows:
Report server URL + ?/ + report name including the path with the SSRS folder + the command options (beginning with first &rs below). In this case Format=PDF is for saving in PDF format.
// this will be the name that was given to the HTTP Connection manager when it was created
ConnectionManager conn = Dts.Connections["HTTP Connection Manager"];
HttpClientConnection httpConn = new HttpClientConnection(conn.AcquireConnection(null));
// location where PDF will be saved to
string outputPDF = #"C:\Test\NameOfReport.pdf";
httpConn.ServerURL = #"http://YourReportServer?/Folder of Report/Report Name&rs:Command=Render&rs:Format=PDF&rc:Toolbar=False";
// second parameter of true indicates to overwrite file
httpConn.DownloadFile(outputPDF, true);
You could use a Script Task in SSIS to export the report from SSRS. Take a look at the following blog post. It explains how to export an SSRS report via SSIS. https://sqlserverrider.wordpress.com/2013/02/15/generate-pdf-report-from-ssis/
Also, this forum thread has some other examples: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/d6ac1ba5-90a2-403b-898e-edaab3c7b270/generate-ssrs-pdf-from-ssis?forum=sqlintegrationservices

Crystal reports 11 RDC (COM API) displays printer dialog even when I tell it not to prompt

I'm using Crystal Reports 11's RDC (COM) API to print. My code looks like this:
HRESULT res = m_Report->SelectPrinter(b_driver, b_device, b_port);
if (FAILED(res)) return res;
// For these calls, the #import wrapper throws on error
m_Report->PutPrinterDuplex(dmDuplex);
m_Report->PutPaperSize(dmPaperSize);
m_Report->PutPaperSource((CRPaperSource)pdlg->GetDevMode()->dmDefaultSource);
if (m_Report->GetPaperOrientation() == crDefaultPaperOrientation)
m_Report->PutPaperOrientation(crPortrait);
VARIANT vfalse;
VariantInit(&vfalse);
vfalse.vt=VT_BOOL;
vfalse.boolVal=0;
res = m_Report->PrintOut(vfalse);
However, at the end of all this, crystal reports still shows its own printer selection dialog - but only for some reports, it seems. Why does crystal reports show a print dialog even when I pass false for promptUser? And how, then, can I suppress crystal reports' internal printer selection dialog and force it to use my values?
Edit: Whoops, CR11, not CR9.
Some further information:
The reports that work properly (ie, do not show the print dialog) are generated internally using the RDC API; we create a new report object, import subreports into it, then print the result. No problem there.
The reports that do not work properly (ie, force the print dialog to open) have been created with a previous version of crystal reports; however, opening and saving the report does not seem to help.
Sample reports in the Crystal Reports installation directory show the same problem.
I tried reproducing with VBScript; however, the result was that nothing was printed at all (no dialog, no nothing):
Set app = CreateObject("CrystalRuntime.Application.11")
Set report = app.OpenReport("C:\Program Files\Business Objects\Crystal Reports 11.5\Samples\en\Reports\General Business\Inventory Crosstab.rpt")
report.PrintOut(True)
rem Testing with a True parameter to force a print dialog - but no printout and nothing appears (no error either though)
First, let me preface that I'm not a C/C++ programmer, so I'm not able to test the code--my interaction w/ the SDK has been with the VB and .Net interface over the years.
I found the following code from BO's devlibrary:
// A dummy variant
VariantInit (&dummy);
dummy.vt = VT_EMPTY;
HRESULT hr = S_OK;
// Specify the path to the report you want to print
_bstr_t ReportPath("c:\\Program Files\\Business Objects\\Crystal Reports 11.5\\Samples\\En\\Reports\\General Business\\Inventory.rpt");
_variant_t vtEmpty(DISP_E_PARAMNOTFOUND, VT_ERROR);
// Instantiate the IApplication object
m_Application.CreateInstance("CrystalRuntime.Application.115");
//Open the Report using the OpenReport method
m_Report = m_Application->OpenReport(ReportPath, dummy)
//Print the Report to printer
m_Report->PrintOut(dummy, dummy, dummy, dummy);
Does it work? It should print the report with its 'default' printer settings and without prompting.
You wrote:
However, at the end of all this,
crystal reports still shows its own
printer selection dialog - but only
for some reports, it seems.
Generally speaking, I've found that Crystal tends to ignore commands to suppress dialogs if it thinks something is missing. I've found this to be true with the parameter dialog. Perhaps it apply to this situation as well. I would ask what is different about the reports that cause the dialog to be generated. There is a 'no printer' option that can be set. Perhaps this is the common thread.
Do you have access to the VB6 IDE? If you write the equivalent commands using VB6's interface, does the prompting occur?
You might also investigate using the CRPE32.dll instead of the report-designer control. To be honest, I don't know if the RDC wraps the CRPE DLL or is an entirely-separate code base.
Turns out it was a bug in my code after all - I'd previously put in a wrapper for the RDC API to fix certain other bugs we were having; due to the large number of methods in the IReport interfaces, I wrote a script to generate pass-through stubs for the methods I wasn't interested in. Turns out that script was passing in bogus values for parameters with default values. Oops! Fixing the wrapper code fixed the bug here.

How can I dynamically add an image logo to ReportViewer Parameters?

I need help adding an image logo in ReportViewer dynamically. I get this image from db, convert it to Base64, and then I need to add it in ReportViewer... This code next:
rpViewer.LocalReport.EnableExternalImages = true;
Company _company = db.Companys.Where(c => c.codCompany == c.codCompany).Single();
//first step
byte[] img = _company.imagem.ToArray(); // i get image from db
MemoryStream _ms = new MemoryStream(img);
string logo = Convert.ToBase64String(img); //convert to base64
// 2 step
List<ReportParameter> lstReportParams = new List<ReportParameter>();//Create params
lstReportParams.Add(new ReportParameter("Logo", logo));
lstReportParams.Add(new ReportParameter("LogoMimeType", "image/png"));
// Doesn't work here (see error below)
this.rpViewer.LocalReport.SetParameters(lstReportParams);
this.rpViewer.RefreshReport();
The error:
{"An error occurred during local report processing."}
{"An attempt was made to set a report parameter 'Logo' that is not defined in this report."}
In Rldc:
MIMEType =Parameters!LogoMimeType.value
Value ="System.Convert.FromBase64String(Parameters!Logo.Value)"
Why doesn't it work?
Why is not recognizing the parameter?
I can load that image in ReportViewer.
Your RDLC file needs to have the Logo parameter created in order for your Parameter List to be reckognized by your report.
You will need to edit your RDLC file, and create a parameter. You can do this by opening the RDLC file in Visual Studio, then click on Report in the file menu, and select Report Parameters.
The error message say's that you have not defined the report parameter Logo. Is this report parameter defined?
You may also be running into problems with the size of the parameters you are sending in.
We had a similar problem, with a report that needed to display different images. In our case there were only about 10 images.
The way we solved it was to place all images on the report, and then set them visable or not depending upon a parameter.

I would like to extract the SQL queries from Crystal Report .rpt files, is there a way to do this?

I would like to extract the SQL queries from Crystal Report .rpt files, is there a way to do this?
I don't have any of the Crystal Reports products, just the .rpt files.
Here's a .Net example of code that grabs the Command Sql from all Crystal Reports in a given directory. It requires the Crystal 2008 .Net SDK to be installed (you can download a trial from SAP):
foreach (string file in Directory.GetFiles("c:\\projects\\Reports", "*.rpt"))
{
Console.WriteLine(String.Format("Processing {0}...", file));
var doc = new CrystalDecisions.CrystalReports.Engine.ReportDocument();
doc.Load(file);
foreach (dynamic table in doc.ReportClientDocument.DatabaseController.Database.Tables)
{
if (table.ClassName == "CrystalReports.CommandTable")
{
string commandSql = table.CommandText;
//TODO: do something with commandSql
}
}
}
To get the SQL as Crystal would build it when running a report, see this link: SAP Note 1280515 - How to extract SQL query from Crystal reports using RAS sdk.
I believe to do this, you need to supply the report parameter values so that Crystal can connect to the database in order to build the SQL. In the example, since a Report Viewer control is used, Crystal can prompt the user for the parameters.
In "Crystal Reports ActiveX Designer Design and Runtime Library" (craxddrt.dll), the Report.SQLQueryString property will do what you want.
I can't seem to find an equivalent property in the .Net SDK, and believe me, I've been looking.
** edit **
It appears that one can make use of the In-Process RAS Server to get this information:
CrystalDecisions.ReportAppServer.DataDefModel.CommandTableClass.CommandText
The other way around this is if you can run the reports, you can hook up SQL Profiler to your DB and capture the incoming SQL on the database side.
JoshL's answer worked for several of my reports, but not all of them. The following method, using ReportClientDocument.RowsetController.GetSQLStatement, was able to extract some of the queries that the other method missed.
foreach (string file in Directory.GetFiles("c:\\projects\\Reports", "*.rpt"))
{
Console.WriteLine(String.Format("Processing {0}...", file));
var doc = new CrystalDecisions.CrystalReports.Engine.ReportDocument();
doc.Load(file);
var controller = doc.ReportClientDocument.RowsetController;
var groupPath = new CrystalDecisions.ReportAppServer.DataDefModel.GroupPath();
string temp = String.Empty;
string commandSql = controller.GetSQLStatement(groupPath, out temp);
//TODO: do something with commandSql
}
My experience is with older versions of Crystal (8,9) - I've no idea what the file formats look like for more recent versions. However, it's worth opening the files up in a text editor just in case, but for the file formats I've seen, the query text is not accessible this way.
If I remember correctly, some versions of Visual Studio 2003 came with tools for manipulating Crystal .rpt files (but I guess this isn't of much use to you, since if you had this already, you wouldn't be asking!).
It's not a very imaginative suggestion, but perhaps your quickest route would be to download the 30-day trial version of the current Crystal Reports, and see if that will open the files for you.
In the Visual studio, select the .rpt file and Go to field explorer, right click on DatabaseFields. Click on SQL query option to view the query.