Drucken mit Java

tpgw

Mitglied
Hallo,

Hier kommt meine nächste Frage😀

Ich möchte eines meiner kleinen Programme gerne um eine Funktion erweitern, und zwar gibt mir das Prog 2 Listen aus, die ich davor in ner jTable einlese, aber das ist ja egal, ich kann die Daten aufbereiten wie es zum Drucken am besten ist..

Es geht darum, dass beide Listen die gedruckt werden sollen einmal ganz oben ein bild bekommen (Logo, s/w) drunter zuerst ein eingerahmtes Feld mit Text und darunter Zeilenweise die Datensätze in mehreren Spalten..
Also am Besten wäre was rel. universelles das ich mit Strings oder StringBuildern oder String Arrays futtern kann oder so..

Wie siehts da aus, ich hab schon bisschen was gelesen, und wie ich das sehe ist Drucken in Java eher schlecht ausgebaut oder irre ich mich da?

mfg
 
ganz oben ein bild bekommen (Logo, s/w) drunter zuerst ein eingerahmtes Feld mit Text und darunter Zeilenweise...

Das ist definitiv mehr als eine kleine Tabelle drucken, denn dafür würde ein table.print() reichen.

Natürlich kannst du auch dein Panel in ein BufferedImage malen und dieses zum Schluss drucken. Meiner Erfahrung nach, ist das aber sehr änderungsresistent und mit viel falschen Testausdrücken verbunden, bis es wirklich passt.

Was du möchtest, nenne ich, wenn auch klein, einen Report.

Da rate ich immer zu JasperReports. Es gibt dazu das Tool iReport mit dem du den Report (Logo, etwas Text) und deine Tablezeilen designen kannst.

Vorteil ist, dass du extrem flexibel bist, weil dein Code nichts davon weiss, WIE der Output wirklich aussieht. Beispielsweise kannst du den Report somit auf dem Schirm, auf dem Drucker oder in PDF erstellen lassen.

Nachteil ist, das du dich erst in Jasperreports einarbeiten musst. Jedenfalls füllst du deinen Report, indem du den Feldern im Report, Werte zuweist, beispielsweise die Logo-Bilddatei etc.

Ich füge mal ein kleines Beispiel an. In dem Report wird ein Logo und die aktuelle Uhrzeit (eingerahmt) gezeigt. Von iReport kommt die Definitionsdatei mit Endung jrxml. Diese wird dann in eine .jasper Datei kompiliert. Und anschliessend werden alle Parameter mit Werten gesetzt. Im Beispiel wird es im JFrame gezeigt (JRViewer). Daraus kann gedruckt werden, oder man macht dieses direkt.
Java:
import java.awt.BorderLayout;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import net.sf.jasperreports.swing.JRViewer;

public class Jasper extends JPanel {
	private JRViewer jv;

	public Jasper() throws JRException {
		setLayout(new BorderLayout());
		String jrxmlFileName = "turtleReport.jrxml";
		JasperDesign jasperDesign = JRXmlLoader.load(jrxmlFileName);
		JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
		Map map = new HashMap();
		InputStream imgInputStream = this.getClass().getResourceAsStream("/images/turtle.jpg");
		map.put("logo", imgInputStream);
		map.put("uhrzeit", new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(new Date()));
		JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, map, new JREmptyDataSource());
		jv = new JRViewer(jasperPrint);
		add(jv, BorderLayout.CENTER);
	}

	public static void main(String[] args) throws JRException {
		JFrame frame = new JFrame("Turtle-Report");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(new Jasper());
		frame.pack();
		frame.setVisible(true);
	}
}
 

Anhänge

  • jasper.PNG
    jasper.PNG
    77,6 KB · Aufrufe: 50
HI,

Ich hab jetzt mal deinen Code getestet, und wollte mich damit spielen..
Das Jasper Library hab ich heruntergeladen und das Prog, also iReport auch..
Wenn ich deinen Code testen will wirft er mir folgenden Fehler: java.lang.NoClassDefFoundError: org/apache/commons/digester/Digester

Was mach ich falsch?
Irgend eine Klasse fehlt offenbar, nur welche?

mfg
 
Irgend eine Klasse fehlt offenbar, nur welche?
Ich tippe mal auf org/apache/commons/digester/Digester:lol:

Im Ernst...

Ich muss dich auf heute abend vertrösten, da ich gerade keinen Zugang zu meinem Rechner habe. Und da ich mit JasperReports seit Ewigkeiten nichts mehr gemacht habe...

Die Libs von JasperReports musst du nämlich auch noch hinzufügen und das waren echt viele.
Und da ich keine Lust hatte, rauszusuchen, welche notwendig sind, habe ich alle genommen.

Ich meine es waren ca. 96 aus dem Lib-Verzeichnis und jasperreports-5.6.0.jar aus dem dist-Ordner. org/apache/commons/digester/Digest beispielsweise ist in lib/commons-digester-2.1.jar.

Vielleicht hilft das weiter, ansonsten wie gesagt heute abend mehr Infos.
 
Ok, ich hab jetzt alle Libraries importiert die er benötigt hat, jetzt gehts, nur erscheint der Inhalt nicht den du einfügst, beim Bild hab ich nen anderen Pfad genommen, aber auch den Rest schreibt der report nicht rein...
Es erscheint der Frame und nichts ist drinnen..???:L

mfg
 
Natürlich musst du deinen Report geeignet definieren.

Hier mal meine Reportdatei

[XML]<?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="turtleReport" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<property name="ireport.zoom" value="0.75"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<parameter name="logo" class="java.io.InputStream"/>
<parameter name="uhrzeit" class="java.lang.String"/>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="260" splitType="Stretch">
<image hAlign="Center" vAlign="Middle">
<reportElement x="0" y="0" width="250" height="250"/>
<imageExpression class="java.awt.Image"><![CDATA[$P{logo}]]></imageExpression>
</image>
</band>
</title>
<pageHeader>
<band height="2" splitType="Stretch"/>
</pageHeader>
<columnHeader>
<band splitType="Stretch"/>
</columnHeader>
<detail>
<band height="125" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="379" height="85"/>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font size="20" isBold="true"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$P{uhrzeit}]]></textFieldExpression>
</textField>
</band>
</detail>
<columnFooter>
<band height="45" splitType="Stretch"/>
</columnFooter>
<pageFooter>
<band height="54" splitType="Stretch"/>
</pageFooter>
<summary>
<band height="42" splitType="Stretch"/>
</summary>
</jasperReport>
[/XML]
 
Natürlich musst du deinen Report geeignet definieren.

Hab leider im alten Post die falsche Reportdatei angegeben😳

[XML]<?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="turtleReport" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<property name="ireport.zoom" value="0.75"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<parameter name="logo" class="java.io.InputStream"/>
<parameter name="uhrzeit" class="java.lang.String"/>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="260" splitType="Stretch">
<image hAlign="Center" vAlign="Middle">
<reportElement x="0" y="0" width="250" height="250"/>
<imageExpression class="java.io.InputStream"><![CDATA[$P{logo}]]></imageExpression>
</image>
</band>
</title>
<pageHeader>
<band height="2" splitType="Stretch"/>
</pageHeader>
<columnHeader>
<band splitType="Stretch"/>
</columnHeader>
<detail>
<band height="125" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="379" height="85"/>
<textElement textAlignment="Left" verticalAlignment="Middle">
<font size="20" isBold="true"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$P{uhrzeit}]]></textFieldExpression>
</textField>
</band>
</detail>
<columnFooter>
<band height="45" splitType="Stretch"/>
</columnFooter>
<pageFooter>
<band height="54" splitType="Stretch"/>
</pageFooter>
<summary>
<band height="42" splitType="Stretch"/>
</summary>
</jasperReport>[/XML]
 
Hmm ok, mit dem zweiten Code funktionierts jetzt zumindest soweit dass die Uhrzeit erscheint, aber auch nicht ganz wie in dem Screenshot..

Das ganze scheint recht kompliziert zu sein, bzw blick ich da nicht wirklich durch bisher..

mfg
 
Wenn die Uhrzeit da ist, läuft es ja schon fast😀

Du solltest mal debuggen und verifizieren, das das Logo geladen werden kann.
Java:
InputStream imgInputStream = this.getClass().getResourceAsStream("/images/turtle.jpg");
Kontrollier bitte ob der Stream nicht null ist.

Weiterhin muss der Parameter in der XML-Datei stimmen.
[XML]<parameter name="logo" class="java.io.InputStream"/>[/XML]
Kontrollier bitte ob das bei dir stimmt.
 
Ja ok, da lag der Fehler, der inputStream blieb null, ka warum..

Jetzt hab ich ein BufferedImage genommen und die xml angepasst, da klappts..

mfg
 
Ok, ich komm jetzt zumindest grundlegend mit den Reports klar, und wie das aussieht ist das noch garnicht mal schwer, da ich theoretisch einfach eine Hilfsklasse baue in die ich meine 3 Elemente übergebe (Bild, Tabelle und Text) und die Hilfsklasse packt das in eine Jasper vorlage und druckt..

So nun meine weiteren Fragen die ich selber nicht lösen konnte bisher..
1.Wie bringe ich eine Tabelle auf Java in den Report? Ich habs mid der Tabelle aus der iReport palette probiert aber da kann ich den Code nicht so hinbiegen wie bei dem Textfeld und dem Bild...

2.Kann man das so machen, dass das Vorschaufenster das dann erscheint irgendwie im Windows look ist und von meinem Prog das Logo übernimmt oder wird das von jasper gesteuert?

mfg
 
Sorry für die späte Antwort, habe aber extrem viel zu tun😎

Was du möchtest, kann "einfach" mit einer JRBeanCollectionDataSource gemacht werden. So werden Collections-Beans als Datenlieferanten mit Jasper verbunden. Eine kleine Beschreibung dazu findest du hier.

Das habe ich mal in meinem Beispiel angewendet. Du musst darauf achten, das die Collection-Daten im Detail-Band enthalten sind (da für alle Items) und die Uhrzeit im Page-Header (da nur einmal). XML und Screenshot im Anhang.

Java:
public class Jasper extends JPanel {
    private JRViewer jv;

    public Jasper() throws JRException, PrinterException {
	setLayout(new BorderLayout());
	String jrxmlFileName = "src/turtleReport.jrxml";
	JasperDesign jasperDesign = JRXmlLoader.load(jrxmlFileName);
	JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
	Map<String, Object> map = new HashMap<>();
	InputStream imgInputStream = this.getClass().getResourceAsStream("/images/tomcat.png");
	map.put("logo", imgInputStream);
	map.put("uhrzeit", new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(new Date()));
	Collection<JapserPerson> data = new ArrayList<JapserPerson>();
	data.add(new JapserPerson("turtle"));
	data.add(new JapserPerson("Merkel"));
	JRDataSource datasource = new JRBeanCollectionDataSource(data, true);
	JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, map, datasource);
	jv = new JRViewer(jasperPrint);
	add(jv, BorderLayout.CENTER);
    }

    public static void main(String[] args) throws JRException, PrinterException {
	JFrame frame = new JFrame("Turtle-Report");
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.add(new Jasper());
	frame.setSize(700, 700);
	frame.setVisible(true);
    }
}
 

Anhänge

Hi,

Ok, danke, das hilft mir schonmal ein Stück weiter..
Aber die große Frage ist immer noch ob das so auch mit einem ganzen JTable oder dem entsprechenden Table Model geht?

Wie gesagt, ich hab einen ausgefüllten JTable aus einem anderen Frame der übergeben und gedruckt werden soll, ich kann die Daten daraus gerne anders aufbereiten, aber im Endeffekt soll eine Tabelle mit 5od6 Spalten und ca. 20 Zeilen auf dem fertigen Report erscheinen..

Das wäre das wichtigte eig., der Rest ist mehr oder weniger Kosmetik..

Aber Danke schonmal, das Jasper Library sieht nach ner guten Lösung aus wenn man es beherrscht😀

mfg
 
Deine Frage verstehe ich nicht.

Einmal kannst du deine Daten umpacken, damit es gut mit Jasper zusammenpasst. Das habe ich gemacht und Ergebnis siehst du im Screenshot.

Du kannst aber auch direkt dein TabelModel verwenden, denn bei JRBeanCollectionDataSource muss "es nur" eine Bean sein.

Du musst "lediglich" für alle Daten im Model entsprechende getter/setter haben, damit du in iReport das Feld definieren kannst und darüber der entsprechende getter-Aufruf in deiner Bean erfolgt.
 

Anhänge

  • report.PNG
    report.PNG
    136,6 KB · Aufrufe: 39
Achso, ja ok, wenn ich das TableModel auch als Source hernehmen kann ist das in Ordnung..

Ich habe mich evtl. falsch ausgedrückt, da ich die Daten wie gesagt unteschiedlich aufbereiten kann, das ich kein Thema, nur will ich dann schon eine Tabelle gedruck haben, also mit den Linien, Header etc...

Ist das im Bereich des Machbaren?

mfg
 
Jetzt komme ich in Bereiche, die ich noch nicht gemacht habe😳

Du kannst zu jedem Text-Element über Padding and Borders einstellen, wie es aussehen soll.

Aber ich vermute eher, das du ein Table-Element meinst. Aber wie das mit eigenen Daten "bestückt" wird, weiss ich nicht.
 
Sorry, das ich erst jetzt antworte.😳

Hatte aber extrem viel zu arbeiten und zweitens musste ich erst probieren, wie Tabellen in Jasper noch mal funktionieren.

Habe aber nun ein Beispiel fertig gemacht und poste es hiermit.😉

Wie auch bei den anderen Beispielen ist die "Zauberklasse" JRBeanCollectionDataSource.

Beim Füllen des Reports gibst du eine Methode an, die dir eine JRDataSource, in diesem Fall eine JRBeanCollectionDataSource, bereitstellt.

Diese wird von Jasper für die Daten "befragt" welche Daten denn in der Tabelle stehen sollen. In diesem einfachen Beispiel sind es die Städte 0 bis 10. In iReport habe ich noch einen statischen Text im Table-Header und im Column-Header angegeben, damit die Tabelle "schöner" aussieht.
 

Anhänge


Zurück
Oben