Monthly Archives: March 2009

Reporte maestro-detalle usando JRXMLDatasource de JasperReports 3.1.2

Introducción

Este es un ejemplo de como realizar un reporte maestro detalle usando JasperReports.
Vamos a generar un simple pdf con el detalle de una factura(Invoice).
También pueden ver Como usar el JRXmlDataSource de JasperReports 3.1.2, para una introducción al JRXmlDataSource.

Archivo XML de datos

bueno, esta es la parte mas simple. :)

(invoice.xml)

<?xml version="1.0" encoding="UTF-8"?>
 
<invoice>
    <invoiceNumber>BP-0123</invoiceNumber>
    <invoiceDate>03/01/2009</invoiceDate>
    <clientName>ACME INC</clientName>
    <clientId>BP102USA</clientId>
    <products>
        <product>
            <name>Iphone 6000G</name>
            <quantity>12</quantity>
            <amout>4000</amout>
        </product>
        <product>
            <name>Lenovo T61P</name>
            <quantity>5</quantity>
            <amout>7000</amout>
        </product>
        <product>
            <name>Xbox 123</name>
            <quantity>2</quantity>
            <amout>1000</amout>
        </product>
        <product>
            <name>GOLDPATH 1</name>
            <quantity>4</quantity>
            <amout>400</amout>
        </product>
    </products>
</invoice>

Como verán, solo definimos datos como, nombre del cliente y el detalle de los productos.

Creación de diseños invoice.jrxml y invoice-detail.jrxml

Tanto los diseños del reporte maestro y detalle son los mismos. Como el de detalle es el mas simple lo listare primero y luego el maestro.

(invoice-detail.jrxml)

<?xml version="1.0" encoding="UTF-8"  ?>
<!-- Created with iReport - A designer for JasperReports -->
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="invoice-detail">
	<property name="ireport.scriptlethandling" value="0" />
	<property name="ireport.encoding" value="UTF-8" />
 
	<field name="name" class="java.lang.String">
		<fieldDescription><![CDATA[name]]></fieldDescription>
	</field>
	<field name="quantity" class="java.lang.String">
		<fieldDescription><![CDATA[quantity]]></fieldDescription>
	</field>
	<field name="amout" class="java.lang.Integer">
		<fieldDescription><![CDATA[amout]]></fieldDescription>
	</field>
 
	<variable name="totalAmount" class="java.lang.Integer" resetType="Report" calculation="Sum">
		<variableExpression><![CDATA[$F{amout}]]></variableExpression>
	</variable>
		<background>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</background>
		<title>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</title>
		<pageHeader>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</pageHeader>
		<columnHeader>
			<band height="32"  isSplitAllowed="true" >
				<staticText>
					<reportElement
						x="15"
						y="8"
						width="192"
						height="18"
						key="staticText-1"/>
					<box></box>
					<textElement>
						<font isBold="true"/>
					</textElement>
				<text><![CDATA[Product Name]]></text>
				</staticText>
				<staticText>
					<reportElement
						x="228"
						y="8"
						width="131"
						height="18"
						key="staticText-2"/>
					<box></box>
					<textElement>
						<font isBold="true"/>
					</textElement>
				<text><![CDATA[Quantity]]></text>
				</staticText>
				<staticText>
					<reportElement
						x="381"
						y="8"
						width="108"
						height="18"
						key="staticText-3"/>
					<box></box>
					<textElement textAlignment="Right">
						<font isBold="true"/>
					</textElement>
				<text><![CDATA[Amout]]></text>
				</staticText>
			</band>
		</columnHeader>
		<detail>
			<band height="38"  isSplitAllowed="true" >
				<textField isStretchWithOverflow="false" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="15"
						y="11"
						width="192"
						height="18"
						key="textField"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
				</textField>
				<textField isStretchWithOverflow="false" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="228"
						y="11"
						width="131"
						height="18"
						key="textField"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.String"><![CDATA[$F{quantity}]]></textFieldExpression>
				</textField>
				<textField isStretchWithOverflow="false" pattern="¤ #,##0.00" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="381"
						y="11"
						width="108"
						height="18"
						key="textField"/>
					<box></box>
					<textElement textAlignment="Right">
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.Integer"><![CDATA[$F{amout}]]></textFieldExpression>
				</textField>
				<staticText>
					<reportElement
						x="492"
						y="14"
						width="31"
						height="14"
						key="staticText-4"/>
					<box></box>
					<textElement>
						<font size="8"/>
					</textElement>
				<text><![CDATA[USD]]></text>
				</staticText>
			</band>
		</detail>
		<columnFooter>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</columnFooter>
		<pageFooter>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</pageFooter>
		<summary>
			<band height="33"  isSplitAllowed="true" >
				<textField isStretchWithOverflow="false" pattern="¤ #,##0.00" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="364"
						y="7"
						width="125"
						height="26"
						key="textField"/>
					<box></box>
					<textElement textAlignment="Right">
						<font size="14"/>
					</textElement>
				<textFieldExpression   class="java.lang.Integer"><![CDATA[$V{totalAmount}]]></textFieldExpression>
				</textField>
				<staticText>
					<reportElement
						x="492"
						y="9"
						width="26"
						height="14"
						key="staticText-5"/>
					<box></box>
					<textElement>
						<font size="8"/>
					</textElement>
				<text><![CDATA[USD]]></text>
				</staticText>
				<staticText>
					<reportElement
						x="15"
						y="7"
						width="112"
						height="26"
						key="staticText-6"/>
					<box></box>
					<textElement>
						<font size="14" isBold="true"/>
					</textElement>
				<text><![CDATA[TOTAL]]></text>
				</staticText>
			</band>
		</summary>
</jasperReport>

Como veran, se definen tres campos para los productos: name, quantity y amount, luego estos campos son desplegados en el área de detalle del reporte.

Ademas tambien estamos declarando una variable llamada totalAmount, que nos sirve calcular el total de la factura.

(invoice.jrxml)

<?xml version="1.0" encoding="UTF-8"  ?>
<!-- Created with iReport - A designer for JasperReports -->
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="invoice">
	<property name="ireport.scriptlethandling" value="0" />
	<property name="ireport.encoding" value="UTF-8" />
 
	<parameter name="detailPath" isForPrompting="false" class="java.lang.String"/>
 
	<field name="clientName" class="java.lang.String">
		<fieldDescription><![CDATA[clientName]]></fieldDescription>
	</field>
	<field name="clientId" class="java.lang.String">
		<fieldDescription><![CDATA[clientId]]></fieldDescription>
	</field>
	<field name="invoiceNumber" class="java.lang.String">
		<fieldDescription><![CDATA[invoiceNumber]]></fieldDescription>
	</field>
	<field name="invoiceDate" class="java.lang.String">
		<fieldDescription><![CDATA[invoiceDate]]></fieldDescription>
	</field>
 
		<background>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</background>
		<title>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</title>
		<pageHeader>
			<band height="50"  isSplitAllowed="true" >
				<staticText>
					<reportElement
						x="5"
						y="6"
						width="227"
						height="35"
						key="staticText-2"/>
					<box></box>
					<textElement>
						<font fontName="FreeSerif" size="24"/>
					</textElement>
				<text><![CDATA[SomeCompany co.]]></text>
				</staticText>
			</band>
		</pageHeader>
		<columnHeader>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</columnHeader>
		<detail>
			<band height="136"  isSplitAllowed="true" >
				<staticText>
					<reportElement
						x="460"
						y="43"
						width="0"
						height="0"
						key="staticText-1"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<text><![CDATA[Static Text]]></text>
				</staticText>
				<textField isStretchWithOverflow="false" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="95"
						y="30"
						width="173"
						height="18"
						key="textField"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.String"><![CDATA[$F{clientName}+ "  - " + $F{clientId}]]></textFieldExpression>
				</textField>
				<textField isStretchWithOverflow="false" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="94"
						y="7"
						width="100"
						height="18"
						key="textField"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.String"><![CDATA[$F{invoiceNumber}]]></textFieldExpression>
				</textField>
				<staticText>
					<reportElement
						x="4"
						y="30"
						width="26"
						height="18"
						key="staticText-3"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<text><![CDATA[To:]]></text>
				</staticText>
				<staticText>
					<reportElement
						x="4"
						y="7"
						width="81"
						height="18"
						key="staticText-4"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<text><![CDATA[Invoice Number:]]></text>
				</staticText>
				<staticText>
					<reportElement
						x="5"
						y="53"
						width="82"
						height="18"
						key="staticText-5"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<text><![CDATA[Date:]]></text>
				</staticText>
				<textField isStretchWithOverflow="false" isBlankWhenNull="false" evaluationTime="Now" hyperlinkType="None"  hyperlinkTarget="Self" >
					<reportElement
						x="96"
						y="53"
						width="78"
						height="18"
						key="textField"/>
					<box></box>
					<textElement>
						<font/>
					</textElement>
				<textFieldExpression   class="java.lang.String"><![CDATA[$F{invoiceDate}]]></textFieldExpression>
				</textField>
				<subreport  isUsingCache="true">
					<reportElement
						x="8"
						y="90"
						width="521"
						height="29"
						key="subreport-1"/>
					<dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JRXmlDataSource)$P{REPORT_DATA_SOURCE}).subDataSource($P{detailPath})]]></dataSourceExpression>
                    <subreportExpression  class="java.lang.String"><![CDATA["./invoice-detail.jasper"]]></subreportExpression>
				</subreport>
			</band>
		</detail>
		<columnFooter>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</columnFooter>
		<pageFooter>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</pageFooter>
		<summary>
			<band height="0"  isSplitAllowed="true" >
			</band>
		</summary>
</jasperReport>

Acá es donde se pone un poco confuso :) Donde tenemos que poner nuestra atención es en el elemento subreport. Este elemento también puede ser creado usando el iReport.

reportElement, define la posición donde se encontrara el subreporte.

dataSourceExpression, en la expresion estamos indicando que vamos a usar el un sub data source, del data source principal del reporte.
“detailPath”, es una xpath que indicara la fuente de datos del subreporte.

subreportExpression, contiene la localización del diseño compilado del reporte de detalle, en consecuencia este es el path de un archivo .jasper.

Java

package bo.sumasoftware.hellojasperreports;
 
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.engine.data.JRXmlDataSource;
 
import java.util.HashMap;
 
/**
 * @author renan
 */
public class WriteInvoiceBasic {
    public static void main(String[] args) throws JRException {
        JasperCompileManager.
                compileReportToFile( "src/main/jrxml/invoice.jrxml","invoice.jasper");
        JasperCompileManager.
                compileReportToFile( "src/main/jrxml/invoice-detail.jrxml","invoice-detail.jasper");
 
        JasperReport master = (JasperReport)JRLoader.loadObject("invoice.jasper");
        JRXmlDataSource xmlDataSource = new JRXmlDataSource("src/main/xml/invoice.xml", "/invoice");
        HashMap hashMap = new HashMap();
        hashMap.put("detailPath","/invoice/products/product");
        JasperPrint jasperPrint = JasperFillManager.fillReport(master, hashMap, xmlDataSource);
        JasperExportManager.exportReportToPdfFile(jasperPrint, "invoice-basic.pdf");
    }
}

Compilación de los reportes. Como veran lo primero que hacemos es compilar los reportes maestro y detalle. al compilar estamos creando los respectivos archivos .jasper de cada reporte.
Hacemos esto, ya que en el reporte maestro se necesita pasar un archivo .jasper.

Cargando reporte maestro. Para realizar esto estamos usando la clase JRLoader y su método loadObject para leer el reporte maestro cmpilado invoice.jasper.

Creacion de JRXMLDataSource. Al crear este objeto, le pasamos como parámetro el archivo xml de datos y también una expresión xpath que indica el nodo raiz de datos para el reporte principal.

Definición de parámetros. En un HashMap estamos definiendo un parámetro llamado “detailPath”. detailPath indica contiene una expresión xpath que indica el data source del subreporte.
Esta es la parte importe. Si nos equivocamos en definir este parámetro el subreporte simplemente no mostrar información.
También tenemos que hacer notar que este es un parámetro definido en el diseño del reporte maestro y se hace referencia a este en el elemento dataSourceExpression.

Impresión del reporte. Acá ya solo se llena el reporte y luego se lo imprime en un archivo pdf.

:) bueno, hasta aquí por hoy. :)
pueden bajar el código fuente. Este es un poco diferente pero tiene dos ejemplos, uno básico y otro mas completo.

ShowModalDialog en Firefox

Este post es muy simple. :)

Lo bueno de firefox 3 fue que ya tiene soporte para el uso del método showModalDialog, que es una implementacion original Internet Explorer.

En fin la forma mas fácil de usar es la siguiente:

window.showModalDialog(url, “”, “toolbar:0; dialogWidth:1024px; dialogHeight:800px; status:0; resizable=1;”);

El primer parámetro es el url de la pagina que queremos abrir.

El segundo argumento es un objeto, en el cual se le pueden pasar parámetros, es decir, podríamos pasar un objeto string o json que tenga mas información :) . En el ejemplo le estamos pasando un string vacio.

El tercer argumento se utiliza para indicar como se va a comportar la ventana. Es decir alto, ancho, si va o no tener barra de menus, etc.

Mas detalle lo pueden encontrar en el sitio msdn de microsoft :)

Hasta la próxima.

Como instalar Java JDK 1.6 en Ubuntu 8.10

Hola amigos,

Este tutorial lo hago para un amigo que necesita instalar el jdk java en
ubuntu.

Como notaran es un poco largo el proceso, pero gracias a los amigos de javamexico.org, vi que ubuntu ya tiene un paquete listo para instalar usundo su package manager.

El comando para instalar java es:

$ sudo apt-get install sun-java6-jdk

Lo bueno de ubuntu es que la tiene paquetes para cosas como flash y otros paquetes que no son fáciles de instalar en otras distribuciones.

Para alguno que desee probar el camino largo acá lo tienen :)

1. Bajar el JDK java 1.6 del sitio de Sun. http://java.sun.com/javase/downloads/index.jsp

2. Seleccionar la Java SE Development Kit (JDK)

3. Esto nos lleva a una pagina, done nos permite seleccionar el sistema operativo, por lo general yo solo selecciono Linux :) .

4. Luego nos pasara a una pagina donde nos muestra los paquetes disponibles. Yo selecciono jdk-6u12-linux-i586.bin, ya que esta versión es un paquete parecido a un tar.gz.

5. Una vez ejecutado el archivo recién bajado, este nos extraerá una carpeta con el nombre jdk1.6.0_12.

6. Movemos la carpeta jdk1.6.0_12 al folder /usr/local, que es la carpeta estándar para los programas tipo gui o consola. si tienen problemas en copiar el jdk a la carpeta /usr/local, pueden llamar al nautilus con el comando

sudo nautilus

De esta forma podran acceder a la carpeta /usr/local.

7. Vamos a proceder a adicionar la variable JAVA_HOME al sistema. Para eso editamos el archivo bash.bashrc con el siguiente comando:

sudo vi /etc/bash.bashrc

Al final del archivo colocamos las siguientes instrucciones.

export JAVA_HOME=/usr/local/jdk1.6.0_12
export PATH=$JAVA_HOME/bin:$PATH

Con esto nos aseguramos que la variable JAVA_HOME siempre estara disponible en el sistema.

8. Abrimos una consola nueva y ejecutamos el comando:

java -version

El cual nos arrogara el siguiente resultado:

java version “1.6.0_12″
Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
Java HotSpot(TM) Server VM (build 11.2-b01, mixed mode)

Si no funciona :( bueno entonces abra que echar mano de los permisos de linux. Aca la secuencia de comandos que utilice.

sudo chmod 777 /usr/local/jdk1.6.0_12
sudo chmod -R 666 /usr/local/jdk1.6.0_12
sudo chmod 777 /usr/local/jdk1.6.0_12/bin
sudo chmod 777 /usr/local/jdk1.6.0_12/db
sudo chmod 777 /usr/local/jdk1.6.0_12/demo
sudo chmod 777 /usr/local/jdk1.6.0_12/include
sudo chmod 777 /usr/local/jdk1.6.0_12/jre

sudo chmod 777 /usr/local/jdk1.6.0_12/jre
sudo chmod 777 /usr/local/jdk1.6.0_12/lib
sudo chmod 777 /usr/local/jdk1.6.0_12/man
sudo chmod 777 /usr/local/jdk1.6.0_12/sample

sudo chmod 777 /usr/local/jdk1.6.0_12/bin/*

Como verán estoy colocando permiso 777 a todas las carpetas (ojo solo carpetas) :) . Tambien se esta colocando 777 a los archivos dentro de bin. el resto esta con permiso 666.

Eso seria todo. Hasta la próxima :)