#1 2015-12-14 18:47:22

braddmagyar
Member
Registered: 2015-12-14

Styling HTML reports

I've been looking deep into the documentation, forums and code for this, but I haven't been able to find an answer to this, but is there a way to style the HTML reports that get rendered by dynamic lists? I need the ability to apply CSS to the rendered HTML. I don't mind digging around in the server code, I just need to be pointed in the right direction because I can't find anything in the filesystem where I would be able to do that.

Any ideas?

Offline

#2 2015-12-14 21:13:41

Arno Mittelbach
datenwerke
Registered: 2012-02-14

Re: Styling HTML reports

Hi,

there is good news and bad news. The bad news is, there is currently no nice way of doing this. The good news is, there is a "bad hacking" way of doing this. What we can do is to write a small script that replaces the HTML output generator behind the scenes. This is, however, really something that belongs in the category "very bad hack" and I am not completely sure that it does not have any side effects. The script is the following:

import net.datenwerke.rs.base.service.reportengines.table.TableReportEngine
import net.datenwerke.rs.base.service.reportengines.table.output.generator.TableOutputGenerator
import net.datenwerke.rs.base.service.reportengines.table.output.generator.TableOutputGeneratorManager
import net.datenwerke.rs.base.service.reportengines.table.output.generator.HTMLOutputGenerator

import java.lang.reflect.*;

import java.io.OutputStream
import net.datenwerke.rs.base.service.reportengines.table.output.object.TableDefinition
import net.datenwerke.rs.base.service.reportengines.table.entities.TableReport
import net.datenwerke.rs.base.service.reportengines.table.entities.Column.CellFormatter
import net.datenwerke.rs.core.service.reportmanager.engine.config.ReportExecutionConfig
import net.datenwerke.rs.utils.misc.StringEscapeUtils
import java.io.PrintWriter

import java.util.HashSet

import com.google.inject.Injector
import com.google.inject.Provider

/* load engine - it is a singleton */
def engine = GLOBALS.getInstance(TableReportEngine.class)

/* load output generators of engine */
oldGeneratorProvider = engine.outputGeneratorManager.outputGenerators

/* add our own html generator */
class MyHTMLOutputGenerator extends HTMLOutputGenerator(){
	public void initialize(OutputStream os, TableDefinition td, boolean withSubtotals, TableReport report, TableReport orgReport, CellFormatter[] cellFormatters, ReportExecutionConfig... configs) throws IOException {
		super.initialize(os, td, withSubtotals, report, orgReport, cellFormatters, configs);
		
		def stringBuffer = new StringBuffer();
               def writer = null;
               if(null != os)
			writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(os, charset)));
      
                /* do custom changes in the following block */ 
		stringBuffer.append("""<html>
<head>
</head>
<body>
<h1>My Custom Output</h1>
<table>""")
		stringBuffer.append("<tr>"); 
		for(String colName : td.getColumnNames()){
			stringBuffer.append("<th>"); 
			stringBuffer.append(StringEscapeUtils.escapeXml(colName));
			stringBuffer.append("</th>"); 
		}
		stringBuffer.append("</tr>"); 
		stringBuffer.append("<tr>");
      
        if(null != writer){
			writer.write(stringBuffer.toString());
			stringBuffer.delete(0, stringBuffer.length());
		}
      
               /* overwrite buffer and writer in superclass */
               def sbField = getClass().getSuperclass().getDeclaredField("stringBuffer")
               sbField.setAccessible(true)
               sbField.set(this, stringBuffer)
      
               if(null != writer){
  	             def writerField = getClass().getSuperclass().getDeclaredField("writer")
    	            writerField.setAccessible(true)
            	    writerField.set(this, writer) 
              }
	}
}

/* have injector ready members */
injector = GLOBALS.getInstance(Injector.class)

/* replace generators in engine */
def field = TableOutputGeneratorManager.class.getSuperclass().getDeclaredField("outputGenerators")
field.setAccessible(true)

Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

field.set(engine.outputGeneratorManager, new Provider<Set<TableOutputGenerator>>(){
	public Set<TableOutputGenerator> get(){
		def set = oldGeneratorProvider.get()
		set.retainAll { ! (it instanceof HTMLOutputGenerator) }

		/* inject members */
		def htmlGenerator = new MyHTMLOutputGenerator();
		injector.injectMembers(htmlGenerator)

		/* add it to set */
		set.add(htmlGenerator)
		
		return set;
	}
})

"bad hack in place"

Basically, what we are doing is to load the report engine for dynamic lists and tweak its list of output generators: we add a custom provider that removes the old html generator and adds our own. We implement our own generator by changing the initialization method which starts the output generation of the html. Most of what is there should not be changed, but the start of the html (look for: My Custom Output) can be adapted without harm (i think) and this should allow you to add custom stylesheets.

A word of caution: as I said, I am not sure, that this does not mess with anything. In a first attempt I've created a hack which would cause problems in case of parallel execution of reports (this should now be ok).

Happy hacking.

Cheers
-Arno

Offline

#3 2015-12-15 10:06:20

karolina
Member
Registered: 2014-08-09

Re: Styling HTML reports

Some months ago I had the same question and I came up with another not-very-nice solution - a Velocity template.

Here is an example of a template that I used with a dynamic list variant having columns: DOCUMENT_NUMBER, DOCUMENT_DATE, BRUTTO_AMOUNT

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>$parameters.get("_RS_REPORT_NAME")</title>
</head>
<body>
    <div class = "reportHeader">
        <h2>$parameters.get("_RS_REPORT_NAME")</h2>
    </div>
    <div class = "reportIntro">
        <!-- Place your intro text here -->
        <p><!-- Paragraph 1 --></p>
        <p><!-- Paragraph 2 --></p>
        <p><!-- Paragraph 3 --></p>
    </div>
    <div class = "dataTable">
        #set( $count = 1 )
        <TABLE>
            <TR>
                <TH>No.</TH>
                <TH>Document No.</TH>
                <TH>Document Date</TH>
                <TH>Amount</TH>
            </TR>
            #foreach( $record in $data )
            <TR>
                <TD>$count</TD>
                <TD>$record.DOCUMENT_NUMBER</TD>
                <TD>$record.DOCUMENT_DATE</TD>
                <TD align="right">$record.BRUTTO_AMOUNT</TD>
            </TR>
            #set( $count = $count + 1 )
            #end
        </TABLE>
    </div>
    <div class = "reportChart"></div>
    <div class = "reportSummary"></div>
        <!-- Place your summary text here -->
        <p><!-- Paragraph 1 --></p>
        <p><!-- Paragraph 2 --></p>
        <p><!-- Paragraph 3 --></p>
    <div class = "reportFooter">
        <I>Created by: $parameters.get("_RS_USER_USERNAME")</I>
    </div>
</body>
</html>

What you need to do is to create a similar html file (with added link to your CSS stylesheet or a style section in the file) and attach it as a velocity template to your dynamic list variant.

The not-very-nice part is that for each variant you may need to create a separate template, as a desired layout, number of columns and their names may differ.
I also did not test it on the RS version that you probably use.

It is possible to create a template by scripting for a given report ID, but this means diving a bit into RS source code (and still it will work only for reports with similar layouts).

Offline

#4 2015-12-15 13:49:15

Arno Mittelbach
datenwerke
Registered: 2012-02-14

Re: Styling HTML reports

Hi all,

could you tell us a bit about how you would ideally like to be able to style the html export? Would it for example be sufficient, if there were callbacks that allow you to insert custom CSS, some html before the table, and some html after the table, or do you require additional functionality?

Cheers
-Arno

Offline

#5 2015-12-15 17:03:55

braddmagyar
Member
Registered: 2015-12-14

Re: Styling HTML reports

Arno Mittelbach wrote:

Hi all,

could you tell us a bit about how you would ideally like to be able to style the html export? Would it for example be sufficient, if there were callbacks that allow you to insert custom CSS, some html before the table, and some html after the table, or do you require additional functionality?

Cheers
-Arno

Hi Arno, thanks for the helpful info smile Yes, having the ability to insert custom css (maybe eventually with an option to save preset or default styles and apply them to the report) and custom html before/after the table would be perfect!

Offline

Board footer

Powered by FluxBB