How To Render A Html Table In Jaspersoft Studio
Solution 1:
Inspired by Jarvis and mostly for fun
As you have correctly noted you can't render html table in textField you would need to use the HtmlComponent <hc:html/>
but this will create an image and you will not only have scaling problems but also issue as selection and searchability of text. Furthermore as Dave Jarvis has stated in their answer this in general is not a suitable way to pass data to jasper reports.
But who cares about all that lets render your html
We need to convert the html to a
JRDataSource
, we will do this using JsouppublicclassHtmlTableDataSourceimplementsJRDataSource{ private List<Elements> rows; private Iterator<Elements> iterator; private Elements currentRow; public HtmlTableDataSource(String html) { super(); init(html); } private void init(String html) { this.rows = new ArrayList<>(); Document doc = Jsoup.parse(html); Elements tables = doc.select("table"); if (tables == null || tables.isEmpty()) { return; } // Get first table ignore others Element table = tables.get(0); //Get all rows Elements trs = table.select("tr"); for (Element element : trs) { //add all of our columns to our listthis.rows.add(element.select("td")); } this.iterator = this.rows.iterator(); } @Overridepublic Object getFieldValue(JRField field) throws JRException { if (field==null||currentRow==null){ returnnull; } try { int col = Integer.parseInt(field.getName()); if (col<currentRow.size()){ return currentRow.get(col).html(); } } catch (NumberFormatException e) { throw new JRException("Using the HTMLTableDataSource, the field name need to be numbers starting from 0"); } returnnull; } @Overridepublic boolean next() throws JRException { if (this.iterator == null || !this.iterator.hasNext()) { returnfalse; } this.currentRow = this.iterator.next(); returntrue; } }
Now lets use it in a report (you need the above class and Jsoup in classpath)
<?xml version="1.0" encoding="UTF-8"?><jasperReportxmlns="http://jasperreports.sourceforge.net/jasperreports"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"name="htmlTable"pageWidth="595"pageHeight="842"whenNoDataType="AllSectionsNoDetail"columnWidth="555"leftMargin="20"rightMargin="20"topMargin="20"bottomMargin="20"uuid="597c0716-df6b-42ec-a7c8-863eb1b7174a"><stylename="Table_TD"mode="Opaque"backcolor="#FFFFFF"><box><penlineWidth="0.5"lineColor="#000000"/><topPenlineWidth="0.5"lineColor="#000000"/><leftPenlineWidth="0.5"lineColor="#000000"/><bottomPenlineWidth="0.5"lineColor="#000000"/><rightPenlineWidth="0.5"lineColor="#000000"/></box></style><subDatasetname="TableDataset"uuid="998ba41a-db15-454b-a081-bc8613899c31"><fieldname="0"class="java.lang.String"/><fieldname="1"class="java.lang.String"/></subDataset><summary><bandheight="30"><componentElement><reportElementx="0"y="0"width="550"height="30"uuid="5d0d5bcb-a094-4446-a5e9-09de629cefc7"/><jr:tablexmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components"xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd"><datasetRunsubDataset="TableDataset"uuid="eac86c28-fad2-433a-a02e-0dd419d9e135"><dataSourceExpression><![CDATA[new my.package.HtmlTableDataSource("<table style='border: 1px solid black'><tr><td style='border: 1px solid black'><b>1</b></td><td style='border: 1px solid black'><b>2</b></td></tr><tr><td style='border: 1px solid black'>Data</td><td style='border: 1px solid black'>Data</td></tr></table>")]]></dataSourceExpression></datasetRun><jr:columnwidth="180"uuid="86ce5c9c-d285-4a51-bf84-30fa9c55579f"><jr:detailCellstyle="Table_TD"height="30"><textField><reportElementx="0"y="0"width="180"height="30"uuid="3acb437b-8b59-4e78-ac1b-4f096f960e89"/><textElementtextAlignment="Center"verticalAlignment="Middle"markup="html"/><textFieldExpression><![CDATA[$F{0}]]></textFieldExpression></textField></jr:detailCell></jr:column><jr:columnwidth="150"uuid="741517bf-5107-4b13-9d61-44209f266c6c"><jr:detailCellstyle="Table_TD"height="30"><textField><reportElementx="0"y="0"width="150"height="30"uuid="1174a60c-8b9e-441b-a9ef-4340b0cd7b68"/><textElementtextAlignment="Center"verticalAlignment="Middle"markup="html"/><textFieldExpression><![CDATA[$F{1}]]></textFieldExpression></textField></jr:detailCell></jr:column></jr:table></componentElement></band></summary></jasperReport>
The <dataSourceExpression><![CDATA[new my.package.HtmlTableDataSource("<table..")]]></dataSourceExpression>
this will instance our datasource and jasper reports will loop over it calling the next()
method and the getFieldValue(JRField field)
when field is to be evaluate
Result
Other considerations
My implementation of the JRDataSource is just quick and fun, naturally it can be vastly improved.
Dynamic columns, if only a maximum number and they are fixed size you could use a solution similar to this https://stackoverflow.com/a/36911788/5292302 if not switch to use crosstabs modifying the JRDataSource as needed.
Yes I changed <strong/>
to <b/>
this is another problem Why does html tags (s, strong) not work in jasper reports?, in this case you could also handle it within your datasource, hence use Jsoup to substitute.
Solution 2:
Broadly, here's how you can solve this problem:
- Convert the HTML table into CSV format.
- This can be accomplished using JSoup, tablesaw-html, or XSLT.
- Be sure to strip out any formatting.
- Convert each CSV element from HTML to Markdown.
- This replaces
<strong>1</strong>
with*1*
.
- This replaces
- Convert the Markdown to simple HTML.
- Use a high-performance engine such as flexmark.
- This must convert
*1*
into<b>1</b>
, which JasperReports can parse. - If JasperReports can render Markdown, then conversion would not be necessary.
- Create a CSV data source for the data.
- Ensure the fields are marked up as HTML text.
- Render the CSV data source.
- If the number of columns is known, use JasperReports as usual.
- If the number of columns can vary, use DynamicJasper.
There are other possibilities, depending on your expertise with XSLT.
However, this approach is ill-advised. A far simpler approach is to determine why HTML tables are being added into the database, rather than as structured, relational data. Change the process to enter the data into the database as relational data, then make your reports use the data without so many levels of translation.
In short, try to re-frame the problem, as it is seldom efficient or easy to coerce non-relational data into relational form suitable for processing by JasperReports.
See also: http://xyproblem.info/
Post a Comment for "How To Render A Html Table In Jaspersoft Studio"