2

I'm using textField's that stretch with overflow and relative to my textField I want to add a footnote in pageFooter.

I need to print the text in the pageFooter only if the page contains my textField or at least make the footer appear when the page contains it.

Example:

I have a section in my .jrxml called "Witnesseth" and "Section A" like so: enter image description here

Now, this witnesseth can be so long it can be moved to the next page due to its length.

I have a footer with footnote like this: enter image description here

Currently it appears on every page but I only want it to appear on where the Section A part has been printed.

Petter Friberg
  • 21,252
  • 9
  • 60
  • 109
Ken Flake
  • 585
  • 8
  • 28
  • Have you tried making an expression on the field containing the information `$F{myField}.contains("word")`, you need specify exactly what you need, it's a bit unclear now what you are actually asking. – Petter Friberg Feb 26 '19 at 10:02
  • Hi @PetterFriberg, thanks for your response. I just updated my question. Regarding your response, if I do that I'm afraid it still prints on every page. – Ken Flake Feb 26 '19 at 10:12
  • Hi Kenny ok, you like a footnote. In fact there is no good answer on Stackoverflow, it's similar to this question, https://stackoverflow.com/questions/27549193/how-to-create-good-footnote-in-ireport. You can probably use some parameter hack tick, add map to parameters, set a value, if value exists print footer, remove value. However I don't like that solution I will study it some it would be nice to have a more dynamic solution. I will let know if I come up with something nice. – Petter Friberg Feb 26 '19 at 10:50
  • Hi @PetterFriberg, thank you very much for your response. Please let me know if this has a solution. =) I appreciate you response. – Ken Flake Feb 26 '19 at 10:53
  • @PetterFriberg Can you share me that parameter hack tick so I may try it? =) When can I know value exists? I want to be on this specific page. And when can I remove its value? – Ken Flake Feb 26 '19 at 12:54
  • The parameter hack trick is to instance a HashMap as a parameter, then put stuff to it in a printWhenExpression, then show stuff if it contains your key, then remove the key, but yeah it's very hacky.. – Petter Friberg Feb 26 '19 at 13:14

2 Answers2

3

Creating footnotes in jasper-reports has 2 major challenges if you are not willing to post elaborate the result (which also is not simple):

  1. On which page will the textField start/end when it overflows?

    Only by grouping or using different detail bands are you able to easily have information on which page the textField will start.

  2. The pageFooter is fixed size (it can not scale dynamically)

    You need to pre-define the space that the footnotes will have, in some limited situations you can use groupFooter bands that can dynamically scale but those situations are limited.

Considering this there is no "ultimate" solution to handle footnotes, I will show one to give an idea of what can be done in a simple case scenario.

Our limitation is that a footnote relative to a textField will be on the page that textField starts on, furthermore the height of the pageFooter will only allow maximum 3 footnotes x page (that's my predefined space). Do note that it would be easy to have footnote on page where textFields end by adding faking textField in new detail band.

The idea is to use a simple JRScriplet that will collect data when printWhenExpression on textField is called (it may be called several times so we need to handle this). In pageFooter we will request the data collected to generate our footnote list.

Example

JRScriplet, we will call addFootnote to add a note and getFootnoteDatasource to print our current footnotes.

public class FootnoteScriplet extends JRDefaultScriptlet {

    //Distinct ordered values (since jasper may call more then once)
    private TreeSet<String> footNotes;

    public FootnoteScriplet(){
        super();
        this.footNotes = new TreeSet<>();
    }   

    /**
     * Add a footnote 
     * @param footNote, string of footNote 
     * @return always <code>true</true> since we use in printWhenExpression
     */
    public boolean addFootnote(String footNote){
        this.footNotes.add(footNote);
        return true;
    }

    /**
     * Get the datasource for footNotes and clear for future use.
     * @return
     */
    public JRDataSource getFootnoteDatasource(){
        JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(new ArrayList<>(footNotes));
        this.footNotes.clear();
        return ds;
    }
}

jrxml, run with OnEmptyRecord datasource to test, the structure is to use multiple detail band, call our scriplet in textField's printWhenExpression (that always return true) to add footnote and then use a jr:list component to display the collected footnotes in the pageFooter.

<?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="Footnotes" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" scriptletClass="my.package.FootnoteScriplet" uuid="b5b15f62-e36a-4c91-a871-ea43faa7d0af">
    <subDataset name="footNoteDS" uuid="884dba42-5c44-4049-a50a-b7e13cc47607">
        <queryString>
            <![CDATA[]]>
        </queryString>
        <field name="_THIS" class="java.lang.String"/>
    </subDataset>
    <parameter name="TEXT" class="java.lang.String">
        <defaultValueExpression><![CDATA["Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"]]></defaultValueExpression>
    </parameter>
    <queryString>
        <![CDATA[]]>
    </queryString>
    <group name="TEXT2" footerPosition="CollateAtBottom">
        <groupExpression><![CDATA["2"]]></groupExpression>
    </group>
    <detail>
        <band height="50">
            <textField isStretchWithOverflow="true">
                <reportElement x="0" y="0" width="550" height="16" isRemoveLineWhenBlank="true" uuid="8def1808-b5c0-45b6-943f-8a88ec04f02b">
                    <printWhenExpression><![CDATA[$P{REPORT_SCRIPTLET}.addFootnote("Footnote 1")]]></printWhenExpression>
                </reportElement>
                <textElement>
                    <font size="12"/>
                </textElement>
                <textFieldExpression><![CDATA["(1)" + $P{TEXT} + "\n" + $P{TEXT}]]></textFieldExpression>
            </textField>
        </band>
        <band height="50">
            <textField isStretchWithOverflow="true">
                <reportElement positionType="Float" x="0" y="0" width="550" height="16" uuid="b6faedf8-11d8-45c8-ac46-e3fb95106140">
                    <printWhenExpression><![CDATA[$P{REPORT_SCRIPTLET}.addFootnote("Footnote 2")]]></printWhenExpression>
                </reportElement>
                <textElement>
                    <font size="12"/>
                </textElement>
                <textFieldExpression><![CDATA["(2)" + $P{TEXT} + "\n" + $P{TEXT}]]></textFieldExpression>
            </textField>
        </band>
        <band height="50">
            <textField isStretchWithOverflow="true">
                <reportElement positionType="Float" x="0" y="0" width="550" height="16" uuid="2db72e84-3e07-4e38-b2bb-c172bbd30956">
                    <printWhenExpression><![CDATA[$P{REPORT_SCRIPTLET}.addFootnote("Footnote 3")]]></printWhenExpression>
                </reportElement>
                <textElement>
                    <font size="12"/>
                </textElement>
                <textFieldExpression><![CDATA["(3)" + $P{TEXT}  + "\n" + $P{TEXT}]]></textFieldExpression>
            </textField>
        </band>
        <band height="50">
            <textField isStretchWithOverflow="true">
                <reportElement positionType="Float" x="0" y="0" width="550" height="16" uuid="4e4b4f2f-4279-4c21-8f0d-62ba92760edd">
                    <printWhenExpression><![CDATA[$P{REPORT_SCRIPTLET}.addFootnote("Footnote 4")]]></printWhenExpression>
                </reportElement>
                <textElement>
                    <font size="12"/>
                </textElement>
                <textFieldExpression><![CDATA["(4)" + $P{TEXT}  + "\n" + $P{TEXT}]]></textFieldExpression>
            </textField>
        </band>
        <band height="50">
            <textField isStretchWithOverflow="true">
                <reportElement positionType="Float" x="0" y="0" width="550" height="16" uuid="5552de59-29f3-49e7-87aa-ee75b811739d">
                    <property name="footNote" value="&quot;FootNote 5&quot;"/>
                    <printWhenExpression><![CDATA[$P{REPORT_SCRIPTLET}.addFootnote("Footnote 5")]]></printWhenExpression>
                </reportElement>
                <textElement>
                    <font size="12"/>
                </textElement>
                <textFieldExpression><![CDATA["(5)"  + $P{TEXT}  + "\n" + $P{TEXT}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
    <pageFooter>
        <band height="64">
            <line>
                <reportElement x="13" y="5" width="534" height="1" uuid="c5b242d5-cafa-43ed-9536-391a4728edf6"/>
                <graphicElement>
                    <pen lineWidth="0.25" lineStyle="Solid"/>
                </graphicElement>
            </line>
            <componentElement>
                <reportElement positionType="Float" x="11" y="10" width="470" height="16" uuid="08bbac11-4f61-4858-8d82-639875dfe1c7"/>
                <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="footNoteDS" uuid="c10d3aaf-8109-4f5b-8099-40450ea9ad7e">
                        <dataSourceExpression><![CDATA[$P{REPORT_SCRIPTLET}.getFootnoteDatasource()]]></dataSourceExpression>
                    </datasetRun>
                    <jr:listContents height="16" width="470">
                        <textField>
                            <reportElement x="0" y="0" width="470" height="16" uuid="d6b5f278-02eb-43d0-934e-5282d37950f5"/>
                            <textElement verticalAlignment="Middle"/>
                            <textFieldExpression><![CDATA[$F{_THIS}]]></textFieldExpression>
                        </textField>
                    </jr:listContents>
                </jr:list>
            </componentElement>
            <textField>
                <reportElement positionType="FixRelativeToBottom" x="500" y="44" width="50" height="20" uuid="7e4a61be-7f67-4003-bd6e-1417cd77378b"/>
                <textElement textAlignment="Right" verticalAlignment="Middle"/>
                <textFieldExpression><![CDATA["P." + $V{PAGE_NUMBER}]]></textFieldExpression>
            </textField>
        </band>
    </pageFooter>
</jasperReport>

Output

Output

This is far from the ultimate solution, instead the answer wants to demonstrate the problems related to footnotes and give an initial idea how to handle them.

Petter Friberg
  • 21,252
  • 9
  • 60
  • 109
  • Hi @PetterFriberg, I have tried your solution, and a footnote does appear. Thank you for this. But, for example, when I forcely overflow until my detail 2 creates a new page, It still appears where it's "supposed to be", but it should appear actually on the next page. Kindly help.. =) – Ken Flake Mar 05 '19 at 10:39
  • @Kenny put a fake detail band after with an empty textField and add your footnote to that (the empty textField will be on new page) – Petter Friberg Mar 05 '19 at 10:44
  • where should I put the fake detail band? after detail 2 or after the detail where I want it to show? – Ken Flake Mar 05 '19 at 11:18
  • @Kenny using a new detail band makes sure that the text on previous detail band is evaluated first, hence after the text that if overflows to new page you want footnote in new page. – Petter Friberg Mar 05 '19 at 11:52
  • Okay. I'll check this out. Thank you so much @Petter. But as of right now, I still can't get it to work. I'll do some playing around JasperSoft.. – Ken Flake Mar 06 '19 at 02:12
1

I fixed my version of this problem by following this answer on SO.

This may be what Petter mentions as the "parameter hack trick", but nonetheless it does follow the page the footnote should be in even if the previous page overflows, etc.

Ken Flake
  • 585
  • 8
  • 28