This is a migrated thread and some comments may be shown as answers.

Import Designer Generated Report to App Guidance

2 Answers 157 Views
Report Designer (standalone)
This is a migrated thread and some comments may be shown as answers.
Jaime Bula
Top achievements
Rank 2
Jaime Bula asked on 27 Aug 2012, 10:40 PM
Hi,

I've been looking everywhere, but I don't find any "Import Designer Generated Report to App Guidance".

Should they be saved on the Database or DLL?, How to set the Data Source?, Best Practices? Security?? Etc...

This info will be appreciatted.

2 Answers, 1 is accepted

Sort by
0
Accepted
erwin
Top achievements
Rank 1
Veteran
Iron
answered on 28 Aug 2012, 04:11 PM
Hi Jaime

Working on the same questions, this is what I came up so far:

Using .trdx files directly in my App for simplicity (because I want Power Users to be able to design and use their own Reports):
ReportDefinitionFile contains the path to the .trdx file. But you can store the report definition XML wherever you want. See the overloads to the Deserialize method.

Not sure about subreports that are somewhere else than in files yet - you would probably have to implement your own ReportResolver.

If you want to use .dlls there is no point in using the standalone designer use the Visual Studio Integrated Designer.
I'm learning on this - so I don't know it this is best practice, but seems to work ;-)

// use the telerik ReportXmlSerializer to create a Report object from XML
  var xmlSerializer = new ReportXmlSerializer();
  var reportDocument = (Telerik.Reporting.Report)xmlSerializer.Deserialize(ReportDefinitionFile);
 
  // create a ReportSource object
  var reportSource = new InstanceReportSource();
  reportSource.ReportDocument = reportDocument;
 
  // get the applications connection string (I'm using LLBLGEN here)
  SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder();
  scsb.ConnectionString = CommonDaoBase.ActualConnectionString;
 
  // ... needed by other parts ot the app
  this.connectionString = CommonDaoBase.ActualConnectionString;
  this.databaseDatabase = scsb.InitialCatalog;
  this.databaseServer = scsb.DataSource;
  this.databaseLogin = scsb.UserID;
  this.databasePassword = scsb.Password;
  this.integratedSecurity = scsb.IntegratedSecurity;
 
  // fill in well-known Report Parameters if the report defines them
  // if ReportParameter "OctopusConnectionString" is present, the report uses Binding to set up it's DataSource objects
  if (!SetReportParameters(reportDocument))
  {
      // no OctopusConnectionString Parameters, set the ConnectionString on the Report DataSource
      SqlDataSource sds = (SqlDataSource)reportDocument.DataSource;
      sds.ConnectionString = scsb.ConnectionString;
 
      // try to patch DataItems in the report (Table, Crosstab, List, Subreports have their own DataSource objects)
      SetConnectionStrings(reportDocument.Items, scsb.ConnectionString);
  }
 
  this.reportViewer1.ReportSource = reportSource;
  this.reportViewer1.RefreshReport();

Fill In Report Parameters:
Define standard Names for Parameters where your Reports expect Values or preset List of possible Values from your Application:
The sample shows how to fill multi value parameters. Note that I set the Visible Attribute to false for Parameters that the User should not see (In the designer you have to set this to true to be able to fill in Values for Preview).

I support two methods of dynamically changing the ConnectionString of the DataSources:
If the report defines a Parameter called "OctopusConnectionString", I just fill that in. The report uses Binding (see old forum posts on examples) to set the DataSource.ConnectionString property from a Report Parameter.
This allows the Report to use additional DataSources with other Connection Strings.

private bool SetReportParameters(IReportDocument src)
   {
       bool connectionStringParameterDefined = false;
       foreach (ReportParameter p in src.ReportParameters)
       {
           if (p.Name == "OctopusOrganizations")
           {
               DataTable dt = new DataTable();
               dt.Columns.Add("Label", typeof(string));
               dt.Columns.Add("Value", typeof(long));
 
               System.Collections.Generic.List<long> allValues = new System.Collections.Generic.List<long>();
 
               OrganizationCollection oc = new OrganizationCollection();
               oc.GetMulti(null);
 
               foreach (OrganizationEntity org in oc)
               {
                   DataRow r = dt.NewRow();
                   r["Label"] = org.Name;
                   r["Value"] = org.Id;
                   allValues.Add(org.Id);
                   dt.Rows.Add(r);
               }
 
               p.Text = "Organizations";
               p.AvailableValues.ValueMember = "Value";
               p.AvailableValues.DisplayMember = "Label";
               p.AvailableValues.DataSource = dt;
               p.MultiValue = true;
 
               if (Globals.ApplicationGlobals.ApplicationSettings.ReportAllOrganizations)
               {
                   p.Visible = false;
                   p.Value = allValues;
               }
               else
               {
                   p.Visible = true;
               }
           }
           else if (p.Name == "OctopusSoftwareCategories")
           {
               DataTable dt = new DataTable();
               dt.Columns.Add("Label", typeof(string));
               dt.Columns.Add("Value", typeof(long));
 
               System.Collections.Generic.List<long> allValues = new System.Collections.Generic.List<long>();
 
               SoftwareCategoryCollection scc = new SoftwareCategoryCollection();
               scc.GetMulti(null);
 
               foreach (SoftwareCategoryEntity sc in scc)
               {
                   DataRow r = dt.NewRow();
                   r["Label"] = sc.Name;
                   r["Value"] = sc.Id;
                   allValues.Add(sc.Id);
                   dt.Rows.Add(r);
               }
 
               p.Text = "Software Categories";
               p.AvailableValues.ValueMember = "Value";
               p.AvailableValues.DisplayMember = "Label";
               p.AvailableValues.DataSource = dt;
               p.MultiValue = true;
 
               if (Globals.ApplicationGlobals.ApplicationSettings.ReportAllSoftwareCategories)
               {
                   p.Visible = false;
                   p.Value = allValues;
               }
               else
               {
                   p.Visible = true;
               }
           }
           else if (p.Name == "OctopusSoftwarePackages")
           {
               DataTable dt = new DataTable();
               dt.Columns.Add("Label", typeof(string));
               dt.Columns.Add("Value", typeof(long));
 
               System.Collections.Generic.List<long> allValues = new System.Collections.Generic.List<long>();
 
               SoftwarePackageCollection spc = new SoftwarePackageCollection();
 
               PredicateExpression filter = null;
               filter = new PredicateExpression();
               filter.Add(new FieldCompareValuePredicate(EntityFieldFactory.Create(SoftwareCategoryFieldIndex.Junk), ComparisonOperator.Equal, 0));
 
               RelationCollection relations = new RelationCollection();
               relations.Add(SoftwarePackageEntity.Relations.SoftwareCategoryEntityUsingSoftwareCategoryId);
 
               spc.GetMulti(filter, relations);
 
               foreach (SoftwarePackageEntity sp in spc)
               {
                   DataRow r = dt.NewRow();
                   r["Label"] = sp.Name;
                   r["Value"] = sp.Id;
                   allValues.Add(sp.Id);
                   dt.Rows.Add(r);
               }
 
               p.Text = "Software Packages";
               p.AvailableValues.ValueMember = "Value";
               p.AvailableValues.DisplayMember = "Label";
               p.AvailableValues.DataSource = dt;
               p.MultiValue = true;
 
               if (Globals.ApplicationGlobals.ApplicationSettings.ReportAllSoftwareCategories)
               {
                   p.Visible = false;
                   p.Value = allValues;
               }
               else
               {
                   p.Visible = true;
               }
           }
           else if (p.Name == "OctopusReportName")
           {
               p.Value = "Octopus " + this.ReportName;
               p.Visible = false;
           }
           else if (p.Name == "OctopusDatabase")
           {
               p.Value = this.Database;
               p.Visible = false;
           }
           else if (p.Name == "OctopusLicensee")
           {
               p.Value = this.LicenseeName;
               p.Visible = false;
           }
           else if (p.Name == "OctopusReportFile")
           {
               p.Value = this.ReportDefinitionFile;
               p.Visible = false;
           }
           else if (p.Name == "OctopusObjectId")
           {
               p.Value = this.ObjectId;
               p.Visible = false;
           }
           else if (p.Name == "OctopusRevision")
           {
               p.Value = Octopus.Base.Licensing.OctopusVersion.BuildVersion;
               p.Visible = false;
           }
           else if (p.Name == "OctopusVersion")
           {
               p.Value = Octopus.Base.Licensing.OctopusVersion.DisplayVersion;
               p.Visible = false;
           }
           else if (p.Name == "OctopusConnectionString")
           {
               p.Value = this.connectionString;
               p.Visible = false;
               connectionStringParameterDefined = true;
           }
       }
 
       return connectionStringParameterDefined;
   }


If the report does not define a Parameter called "OctopusConnectionString", I set the Report.DataSource.ConnectionString property to my apps connection string.
As other DataItems in the Report have their own DataSources, I have to recursively change the Connection String there too. This is where it gets a bit clumsy, see my other posts:

/// <summary>
      /// Recursively set the connection string on all report items that have a sql datasource
      /// </summary>
      /// <param name="items"></param>
      /// <param name="connectionString"></param>
      private void SetConnectionStrings(Telerik.Reporting.ReportItemBase.ItemCollection items, string connectionString)
      {
          foreach (Telerik.Reporting.ReportItemBase ib in items)
          {
              if (ib.Items != null)
              {
                  if (ib.Items.Count > 0)
                  {
                      SetConnectionStrings(ib.Items, connectionString);
                  }
              }
 
              SqlDataSource ds = null;
 
              if (ib is Telerik.Reporting.Chart)
              {
                  Telerik.Reporting.Chart chart = ib as Telerik.Reporting.Chart;
                  ds = chart.DataSource as SqlDataSource;
              }
              else if (ib is Telerik.Reporting.Crosstab)
              {
                  Telerik.Reporting.Crosstab crosstab = ib as Telerik.Reporting.Crosstab;
                  ds = crosstab.DataSource as SqlDataSource;
              }
              else if (ib is Telerik.Reporting.Table)
              {
                  Telerik.Reporting.Table table = ib as Telerik.Reporting.Table;
                  ds = table.DataSource as SqlDataSource;
              }
              else if (ib is Telerik.Reporting.List)
              {
                  Telerik.Reporting.List list = ib as Telerik.Reporting.List;
                  ds = list.DataSource as SqlDataSource;
              }
              else if (ib is Telerik.Reporting.SubReport)
              {
                  Telerik.Reporting.SubReport rpt = ib as Telerik.Reporting.SubReport;
                  ds = rpt.Report.DataSource as SqlDataSource;
              }
 
              if (ds != null)
              {
                  ds.ConnectionString = connectionString;
              }
          }
      }

Maybe someone at Telerik comes up with a more elegant solution to this.

Regards
Erwin


0
Jaime Bula
Top achievements
Rank 2
answered on 28 Aug 2012, 06:57 PM
Thanx for your post!

Has pointed me on a direction. Now I'll try to make it work with the Silverlight Report Viewer.

Best Regards!
Tags
Report Designer (standalone)
Asked by
Jaime Bula
Top achievements
Rank 2
Answers by
erwin
Top achievements
Rank 1
Veteran
Iron
Jaime Bula
Top achievements
Rank 2
Share this question
or