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

How to modify external stylesheet programmatically

6 Answers 97 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Tursunkhuja
Top achievements
Rank 2
Iron
Veteran
Tursunkhuja asked on 17 Jul 2020, 07:20 PM

I'm using external style sheets in my reports. Report designer uses style sheet file with absolute path. See the example of external style sheet from report xml definition below.

  <ExternalStyleSheets>
    <ExternalStyleSheet Kind="Absolute" Path="D:\Shared\2020R1\Marvin's Vision Reports\StyleSheet.xml" />
  </ExternalStyleSheets>

I import the reports in our project and then I store style sheet file beside the report file. When I run and show a report, external style sheet file may not be found because it's using absolute path as you see from the example above. 

How can I programmatically change my report(running report)'s ExternalStyleSheet to set Url kind to relative path instead of absolute path? and how to reset Path attribute to just file name programmatically?

6 Answers, 1 is accepted

Sort by
0
Neli
Telerik team
answered on 24 Jul 2020, 06:40 AM

Hi Tursunhuja,

If you are using the HTML5 Report Viewer, you may test to implement the custom logic for changing the path's kind in custom report source resolver. You will need to read the report definition and set the path. For further information, please, check Exporting and Reusing Style Sheets article. Let us know about the type of project and viewer if you are not using the HTML5 Report Viewer.

Regards,
Neli
Progress Telerik

0
Tursunkhuja
Top achievements
Rank 2
Iron
Veteran
answered on 24 Jul 2020, 06:59 AM

I'm using HTML5 Report Viewer and there is Reporting REST Web API project on .NET Core 3.1. I implemented custom report resolver.

Should I read report XML definition, go through the ExternalStylesSheet items and reset the path?

0
Neli
Telerik team
answered on 29 Jul 2020, 12:26 PM

Hello Tursunhuja,

The purpose of the custom report resolver from the article is to return an XmlReportSource with an XML report definition obtained from an SQL Server database. In your case, you need to unpackage the report definition, remove the style sheet of the report, and add it again with relative path. Finally, return the report as an Instance report source. The code below represents the approach:

class CustomReportSourceResolver : IReportSourceResolver
{
    ReportSource IReportSourceResolver.Resolve(string report, OperationOrigin operationOrigin, IDictionary<string, object> currentParameterValues)
    {
        var reportPackager = new ReportPackager();
        using (var sourceStream = System.IO.File.OpenRead("SampleReport.trdp"))
        {
            var reportInstance = (Report)reportPackager.UnpackageDocument(sourceStream);
            var externalStyleSheet = new ExternalStyleSheet("TelerikReportingStyleSheet.xml");
            reportInstance.ExternalStyleSheets.Clear();
            reportInstance.ExternalStyleSheets.Add(externalStyleSheet);
            InstanceReportSource irs = new InstanceReportSource();
            irs.ReportDocument = reportInstance;
            return irs;
        }
    }
}

I hope this information helps you. Please, let us know if you need further assistance.

Regards,
Neli
Progress Telerik

0
Tursunkhuja
Top achievements
Rank 2
Iron
Veteran
answered on 30 Jul 2020, 06:40 AM

I'm having 2 problems.

Some reports have external style sheets defined by a report designer. You can see example of it from the attached picture file. There can be several style sheet files totally. On building our project all style sheet files are going to copied to app Output folder. It means programmatically we need to change the current report style sheet path from absolute to relative. I can do that on runtime maybe in custom report resolver in resolve() method. 

Problem #1:

In your code you cleared ExternalStyleSheets collection and then adding new one. But, before adding new style I need to know existed style sheet file name. I tried to get style file name with this code reportInstance.ExternalStyleSheets[0].Name. But, Name property is private.

Eventually, I solved this issue by editing report xml definition. See part of my code:

            void UpdateExternalStyleSheetPath(ref Telerik.Reporting.Report reportObject)
            {
                if ((reportObject.ExternalStyleSheets as Collection<ExternalStyleSheet>).Any())
                {
                    var reportXml = XElement.Parse(reportObject.ToXmlString());
                    var externalStyleSheets = reportXml.Elements().FirstOrDefault(l => l.Name.LocalName == "ExternalStyleSheets").Elements();
                    foreach (var externalStyleSheet in externalStyleSheets)
                    {
                        string path = externalStyleSheet.Attribute("Path").Value;
                        string fileName = Path.GetFileName(path);
                        externalStyleSheet.Attribute("Path").Value = fileName;
                    }
                    reportObject = ReportHelper.ToTelerikReport(reportXml.ToString());
                }
            }

Problem #2:
Some of our reports use drill down report (or sub-report). The drill down report has external style sheet as well. If I run the first/primary report, it looks good and it has style sheet applied, but its drill down report (sub-report) doesn't have the style sheet applied. I noticed that the only on running main/primary report the Resolve() method runs, but on running drill down report the Resolve() method doesn't run.

Do you have any idea to solve the problems (especially the problem #2)?

0
Neli
Telerik team
answered on 04 Aug 2020, 03:01 PM

Hi Tursunhuja,

When it comes to the first question, you may vote for Use IReportResolver instance to resolve child reports request or to use System Reflection to access the private property. Basically, you can use the same approach for the subreport as in the main report- get the XML and modify it.

Regards,
Neli
Progress Telerik

0
Tursunkhuja
Top achievements
Rank 2
Iron
Veteran
answered on 21 Apr 2021, 09:30 AM

Hi Neli,

Problem #2 is resolved by Telerik Reporting R2.2020.

For the Problem #1, it's not good solution when we edit report XML definition to find ExternalStyleSheets element and change some attribute. Report's ExternalStyleSheets property is read-only. We can add new external style sheet with like this code report.ExternalStyleSheets.Add(new ExternalStyleSheet(){...}) but it will not fix our problem. Our problem is we need to modify already existed external style sheet item in the ExternalStyleSheets collection.

Scenario: Our report has one external style sheet. When we preview the report via our app, in goes through custom report resolver. How can we change the report's style sheet Path property in custom report resolver?

Neli
Telerik team
commented on 27 Apr 2021, 02:37 PM

Hello Tursunkhuja,

Thank you for your clarification. I am afraid that firstly, you need to clear the ExternalStyleSheet and re-add it again with the required path.

Tursunkhuja
Top achievements
Rank 2
Iron
Veteran
commented on 28 Apr 2021, 03:24 AM

Hi,
By modifying already existed external style sheet, I meant I need to get style sheet file first and then, I will clear the collection and re-add it again. The problem here is without reading file path I don't know what is file path (or file name). That's why I asked about issue with reading ExternalStyleSheet programmatically.
Neli
Telerik team
commented on 06 May 2021, 02:46 PM

Hi Tursunkhuja,

Note that the ExternalStyleSheet Class does not have any methods that would allow changing the kind. It has only a few constructors. If you don't want to remove the ExternalStyleSheet and add it again, you can add test saving the report as TRDX. Then in the CustomReportSourceResolver, you need to read the file and replace the kind. For example:

<ExternalStyleSheets>
    <ExternalStyleSheet Kind="Absolute" Path="D:\FolderName\TestStyleSheet.xml" />
  </ExternalStyleSheets>

should be replaced with:

 <ExternalStyleSheets>
    <ExternalStyleSheet Kind="Relative" Path="TestStyleSheet.xml" />
  </ExternalStyleSheets>


Tursunkhuja
Top achievements
Rank 2
Iron
Veteran
commented on 07 May 2021, 04:06 AM

Hi Neli,
Your suggestion is like workaround. Should I create a feature request to have correct way (to make Kind and Path properties as public)?
Neli
Telerik team
commented on 11 May 2021, 10:49 AM

Hi Tursunkhuja,

I discussed the case with one of our developers and indeed, removing and adding the external style sheet is the best way to change the kind.

Tursunkhuja
Top achievements
Rank 2
Iron
Veteran
commented on 11 May 2021, 10:55 AM | edited

Hi,
For example our report has like this external style sheet:
<ExternalStyleSheet Kind="Absolute" Path="D:\FolderName\TestStyleSheet.xml" />

And we want to change Kind to 'Relative' and Path to just file name like this:
<ExternalStyleSheet Kind="Relative" Path="TestStyleSheet.xml" />

Removing and adding the external style sheets doesn't help us because before removing external style sheets we need to know all the style sheets and their Paths. So, we need to know style sheet file name in our custom report resolver.

Scenario:
Report writer person uses absolute path for his report style sheet and his style sheet file is stored in his local machine. After he finished designing his report he will upload the report into our app (so it will be transferred to our server machine). After that, when we want to see his report through our client app, the report doesn't have style sheet applied.
Neli
Telerik team
commented on 20 May 2021, 03:04 PM

Hi Tursunkhuja,

Thank you for the details.

In this case, the only option that I can suggest is to read the report definition and replace the kind and path of the ExternalStyleSheet.

Tags
General Discussions
Asked by
Tursunkhuja
Top achievements
Rank 2
Iron
Veteran
Answers by
Neli
Telerik team
Tursunkhuja
Top achievements
Rank 2
Iron
Veteran
Share this question
or