mr mcwolf mr mcwolf -3 years ago 154
Java Question

How to create a dotted line under all lines in a wrapping textField that runs to end?

I'm looking for a way to create a jasper report element that represents a dynamic height and label text box as a

textField
that stretch with overflow

The content of the text box should include a dotted line for each line from beginning to end.

Rough sketch of desired result.

A rough sketch of the final result.

Answer Source

There are no settings in JasperReports that let you achieve this directly, one of the simplest strategy probably is to convert your text to a datasource, hence a list of lines, then you display every line in a textField with a dotted line under it.

To create the datasource we need to calculate when the line break will occur and for this we need to use java, I will use the LineBreakMeasurer

Java code converting a long text into a list of lines, depending on wrappingWidth and Font

public class JRSplitText {

    public static JRDataSource getTextDataSource(String text, int wrappingWidth, String fontName, int fontStyle, int fontSize) {
        // Our list with the different text segements (lines)
        List<String> textSegements = new ArrayList<>();

        // Instance a FontRenderContext
        AffineTransform affinetransform = new AffineTransform();
        FontRenderContext frc = new FontRenderContext(affinetransform, true, true);

        // Instance the AttributedString and it's iterator
        AttributedString attrText = new AttributedString(text);
        // To consider font-extensions lets load font directly from jasper-reports
        FontUtil fontUtil = FontUtil.getInstance(DefaultJasperReportsContext.getInstance());
        Font font = fontUtil.getAwtFontFromBundles(fontName, fontStyle, fontSize, Locale.getDefault(), false);
        attrText.addAttribute(TextAttribute.FONT, font);
        AttributedCharacterIterator styledText = attrText.getIterator();

        // Start measurer how much text can fit in our width and add each line
        // to our list
        LineBreakMeasurer measurer = new LineBreakMeasurer(styledText, frc);
        while (measurer.getPosition() < styledText.getEndIndex()) {
            TextLayout layout = measurer.nextLayout(wrappingWidth);
            String line = text.substring(measurer.getPosition() - layout.getCharacterCount(), measurer.getPosition());
            textSegements.add(line);
        }

        // return a datasource of our lists
        return new JRBeanCollectionDataSource(textSegements);
    }
}

With this code in classpath we can call it directly from jrxml with our text and font to get a datasource.

JasperReports - jrxml, we will call the class above with some text in a parameter (it could be field or variabile), in example I'm using jr:list component to iterate datasource but you can also use a normal subreport.

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="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="lineBreakTest" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="597c0716-df6b-42ec-a7c8-863eb1b7174a">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
    <subDataset name="datasource" uuid="6a442aa1-3bf1-494c-9654-e6d3122dd5a7">
        <queryString>
            <![CDATA[]]>
        </queryString>
        <field name="_THIS" class="java.lang.String"/>
    </subDataset>
    <parameter name="text" class="java.lang.String">
        <defaultValueExpression><![CDATA["Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."]]></defaultValueExpression>
    </parameter>
    <title>
        <band height="18">
            <componentElement>
                <reportElement positionType="Float" x="2" y="0" width="550" height="15" uuid="3a68753d-ac77-4941-9dd9-fdeca5ad2f76"/>
                <jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" printOrder="Vertical">
                    <datasetRun subDataset="datasource" uuid="a76bcffd-57ad-44bf-b2c9-20b89089e440">
                        <dataSourceExpression><![CDATA[jdd.so.JRSplitText.getTextDataSource($P{text},550,"SansSerif",java.awt.Font.PLAIN,10)]]></dataSourceExpression>
                    </datasetRun>
                    <jr:listContents height="15" width="550">
                        <textField>
                            <reportElement x="0" y="0" width="550" height="15" uuid="c9685fa5-a942-4709-9fa9-98e9cc80bc5c"/>
                            <box>
                                <bottomPen lineWidth="1.0" lineStyle="Dotted"/>
                            </box>
                            <textElement>
                                <font fontName="SansSerif" size="10"/>
                            </textElement>
                            <textFieldExpression><![CDATA[$F{_THIS}]]></textFieldExpression>
                        </textField>
                    </jr:listContents>
                </jr:list>
            </componentElement>
        </band>
    </title>
</jasperReport>

Output

result

The dotted lines does not seem nice in screen-shot, but this is only a screen shot-issue

Note: wrappingWidth and font parameters, is our width of textField and its font. The line height is controlled by height of textField

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download