Procházet zdrojové kódy

FormulaField、PromptFields、SpecialVarField等特殊crystal元素映射为jasper的variable

sunyj před 8 roky
rodič
revize
d2a310f30a

+ 58 - 0
src/main/java/com/uas/report/crystal2jasper/CrystalToJasper.java

@@ -1,14 +1,19 @@
 package com.uas.report.crystal2jasper;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileFilter;
 import java.io.FileNotFoundException;
+import java.io.FileReader;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.Set;
 
 import javax.xml.transform.TransformerException;
@@ -206,6 +211,8 @@ public class CrystalToJasper {
 			// 修改查询语句
 			String queryString = parseQueryString(rptXmlFile);
 			modifyQueryString(subReportFile, queryString);
+			// 移除模板中多余变量
+			removeUnusedVariables(subReportFile);
 		}
 
 		File rptXmlFile = new File(uncompressedDir, "content.xml");
@@ -217,6 +224,8 @@ public class CrystalToJasper {
 		// 修改查询语句
 		String queryString = parseQueryString(rptXmlFile);
 		modifyQueryString(reportFile, queryString);
+		// 移除模板中多余变量
+		removeUnusedVariables(reportFile);
 		// 替换子报表路径
 		processSubReportPath(reportFile, subReportNames);
 
@@ -289,6 +298,55 @@ public class CrystalToJasper {
 		saveXmlFile(document, jrxmlFile);
 	}
 
+	/**
+	 * 移除模板中多余变量
+	 * 
+	 * @param jrxmlFile
+	 *            报表
+	 * @throws DocumentException
+	 * @throws IOException
+	 */
+	@SuppressWarnings("unchecked")
+	private void removeUnusedVariables(File jrxmlFile) throws DocumentException, IOException {
+		Set<String> usedVariables = getUsedVariables(jrxmlFile);
+		if (!CollectionUtils.isEmpty(usedVariables)) {
+			Document document = new SAXReader().read(jrxmlFile);
+			List<Element> elements = document.selectNodes("//*[name()='variable']");
+			for (Element element : elements) {
+				String variableName = element.attributeValue("name");
+				// 变量未实际使用,移除元素
+				if (!usedVariables.contains(variableName)) {
+					element.getParent().remove(element);
+				}
+			}
+			saveXmlFile(document, jrxmlFile);
+		}
+	}
+
+	/**
+	 * 获取实际使用的变量
+	 * 
+	 * @param jrxmlFile
+	 *            报表
+	 * @return
+	 * @throws IOException
+	 */
+	private Set<String> getUsedVariables(File jrxmlFile) throws IOException {
+		BufferedReader bufferedReader = new BufferedReader(new FileReader(jrxmlFile));
+		String line = null;
+		Set<String> result = new HashSet<>();
+		while ((line = bufferedReader.readLine()) != null) {
+			// 格式为$V{PD_TOTAL}
+			Pattern pattern = Pattern.compile("\\$V\\{([^\\$]*)\\}");
+			Matcher matcher = pattern.matcher(line);
+			while (matcher.find()) {
+				result.add(matcher.group(1));
+			}
+		}
+		bufferedReader.close();
+		return result;
+	}
+
 	/**
 	 * 处理报表中子报表的路径
 	 * 

+ 76 - 93
src/main/resources/crystal2jasper.xsl

@@ -5,7 +5,7 @@
 
 	<xsl:output method="xml" version="1.0" encoding="UTF-8"
 		indent="yes"
-		cdata-section-elements="parameterDescription defaultValueExpression queryString text textFieldExpression subreportParameterExpression connectionExpression subreportExpression" />
+		cdata-section-elements="parameterDescription defaultValueExpression queryString variableExpression text textFieldExpression subreportParameterExpression connectionExpression subreportExpression" />
 	<!-- position rate from crystal to jasper -->
 
 	<xsl:variable name="positionRate">
@@ -39,6 +39,7 @@
 			<xsl:attribute name="rightMargin"><xsl:value-of select="$rightMargin" /></xsl:attribute>
 			<xsl:attribute name="topMargin"><xsl:value-of select="$topMargin" /></xsl:attribute>
 			<xsl:attribute name="bottomMargin"><xsl:value-of select="$bottomMargin" /></xsl:attribute>
+
 			<!-- parameters -->
 			<parameter name="WHERE_CONDITION" class="java.lang.String">
 				<parameterDescription>where子句</parameterDescription>
@@ -49,6 +50,7 @@
 				<parameterDescription>报表的路径</parameterDescription>
 				<defaultValueExpression>"/mnt/data/reports"</defaultValueExpression>
 			</parameter>
+
 			<!-- subreport parameters -->
 			<xsl:for-each select="PromptFields/Field[@type='PromptVarField']">
 				<xsl:variable name="name" select="substring-after(Name/@value,'Pm-')" />
@@ -97,6 +99,43 @@
 					</xsl:attribute>
 				</field>
 			</xsl:for-each>
+
+			<!-- variables -->
+			<!-- FormulaFields to variable -->
+			<xsl:for-each select="FormulaFields/Field[@type='FormulaField']">
+				<variable>
+					<xsl:attribute name="name">
+						<xsl:value-of select="Name/@value" /> 
+					</xsl:attribute>
+					<variableExpression>
+						<xsl:value-of select="TextData" />
+					</variableExpression>
+				</variable>
+			</xsl:for-each>
+			<!-- PromptFields(don't start with 'Pm-') to variable -->
+			<xsl:for-each select="PromptFields/Field[@type='PromptVarField']">
+				<xsl:variable name="name" select="Name/@value" />
+				<xsl:choose>
+					<xsl:when test="substring-after($name,'Pm-')">
+					</xsl:when>
+					<xsl:otherwise>
+						<variable>
+							<xsl:attribute name="name">
+								<xsl:value-of select="$name" />
+							</xsl:attribute>
+						</variable>
+					</xsl:otherwise>
+				</xsl:choose>
+			</xsl:for-each>
+			<!-- SpecialVarField to variable -->
+			<xsl:for-each select="//Reference[@type='SpecialVarField']">
+				<variable>
+					<xsl:attribute name="name">
+						<xsl:value-of select="@value" /> 
+					</xsl:attribute>
+				</variable>
+			</xsl:for-each>
+
 			<!-- title -->
 			<xsl:if test="AreaPair[@type='ReportAreaPair']/Area[@type='ReportHeader']">
 				<title>
@@ -171,98 +210,42 @@
 		<xsl:variable name="type" select="@type" />
 		<xsl:choose>
 			<xsl:when test="$type='Box'">
-				<!-- <rectangle>
-					<reportElement mode="Opaque">
-						<xsl:variable name="x" select="@x_position" />
-						<xsl:variable name="y" select="@y_position" />
-						<xsl:variable name="x2" select="@x2_position" />
-						<xsl:variable name="y2" select="@y2_position" />
-						position
-						<xsl:choose>
-							<xsl:when test="$x2 > $x">
-								<xsl:attribute name="x">
-									<xsl:value-of select="round($x div $positionRate)" />
-								</xsl:attribute>
-								<xsl:attribute name="width">
-									<xsl:value-of select="round(($x2 - $x) div $positionRate)" />
-								</xsl:attribute>
-							</xsl:when>
-							<xsl:otherwise>
-								<xsl:attribute name="x">
-									<xsl:value-of select="round($x2 div $positionRate)" />
-								</xsl:attribute>
-								<xsl:attribute name="width">
-									<xsl:value-of select="round(($x - $x2) div $positionRate)" />
-								</xsl:attribute>
-							</xsl:otherwise>
-						</xsl:choose>
-						<xsl:choose>
-							<xsl:when test="$y2 > $y">
-								<xsl:attribute name="y">
-									<xsl:value-of select="round($y div $positionRate)" />
-								</xsl:attribute>
-								<xsl:attribute name="height">
-							    	<xsl:value-of select="round(($y2 - $y) div $positionRate)" />
-								</xsl:attribute>
-							</xsl:when>
-							<xsl:otherwise>
-								<xsl:attribute name="y">
-									<xsl:value-of select="round($y2 div $positionRate)" />
-								</xsl:attribute>
-								<xsl:attribute name="height">
-							    	<xsl:value-of select="round(($y - $y2) div $positionRate)" />
-								</xsl:attribute>
-							</xsl:otherwise>
-						</xsl:choose>
-					</reportElement>
-				</rectangle> -->
+				<!-- <rectangle> <reportElement mode="Opaque"> <xsl:variable name="x" 
+					select="@x_position" /> <xsl:variable name="y" select="@y_position" /> <xsl:variable 
+					name="x2" select="@x2_position" /> <xsl:variable name="y2" select="@y2_position" 
+					/> position <xsl:choose> <xsl:when test="$x2 > $x"> <xsl:attribute name="x"> 
+					<xsl:value-of select="round($x div $positionRate)" /> </xsl:attribute> <xsl:attribute 
+					name="width"> <xsl:value-of select="round(($x2 - $x) div $positionRate)" 
+					/> </xsl:attribute> </xsl:when> <xsl:otherwise> <xsl:attribute name="x"> 
+					<xsl:value-of select="round($x2 div $positionRate)" /> </xsl:attribute> <xsl:attribute 
+					name="width"> <xsl:value-of select="round(($x - $x2) div $positionRate)" 
+					/> </xsl:attribute> </xsl:otherwise> </xsl:choose> <xsl:choose> <xsl:when 
+					test="$y2 > $y"> <xsl:attribute name="y"> <xsl:value-of select="round($y 
+					div $positionRate)" /> </xsl:attribute> <xsl:attribute name="height"> <xsl:value-of 
+					select="round(($y2 - $y) div $positionRate)" /> </xsl:attribute> </xsl:when> 
+					<xsl:otherwise> <xsl:attribute name="y"> <xsl:value-of select="round($y2 
+					div $positionRate)" /> </xsl:attribute> <xsl:attribute name="height"> <xsl:value-of 
+					select="round(($y - $y2) div $positionRate)" /> </xsl:attribute> </xsl:otherwise> 
+					</xsl:choose> </reportElement> </rectangle> -->
 			</xsl:when>
 			<xsl:when test="$type='Line'">
-				<!-- <line>
-					<reportElement mode="Opaque">
-						<xsl:variable name="x" select="@x_position" />
-						<xsl:variable name="y" select="@y_position" />
-						<xsl:variable name="x2" select="@x2_position" />
-						<xsl:variable name="y2" select="@y2_position" />
-						position
-						<xsl:choose>
-							<xsl:when test="$x2 > $x">
-								<xsl:attribute name="x">
-									<xsl:value-of select="round($x div $positionRate)" />
-								</xsl:attribute>
-								<xsl:attribute name="width">
-									<xsl:value-of select="round(($x2 - $x) div $positionRate)" />
-								</xsl:attribute>
-							</xsl:when>
-							<xsl:otherwise>
-								<xsl:attribute name="x">
-									<xsl:value-of select="round($x2 div $positionRate)" />
-								</xsl:attribute>
-								<xsl:attribute name="width">
-									<xsl:value-of select="round(($x - $x2) div $positionRate)" />
-								</xsl:attribute>
-							</xsl:otherwise>
-						</xsl:choose>
-						<xsl:choose>
-							<xsl:when test="$y2 > $y">
-								<xsl:attribute name="y">
-									<xsl:value-of select="round($y div $positionRate)" />
-								</xsl:attribute>
-								<xsl:attribute name="height">
-							    	<xsl:value-of select="round(($y2 - $y) div $positionRate)" />
-								</xsl:attribute>
-							</xsl:when>
-							<xsl:otherwise>
-								<xsl:attribute name="y">
-									<xsl:value-of select="round($y2 div $positionRate)" />
-								</xsl:attribute>
-								<xsl:attribute name="height">
-							    	<xsl:value-of select="round(($y - $y2) div $positionRate)" />
-								</xsl:attribute>
-							</xsl:otherwise>
-						</xsl:choose>
-					</reportElement>
-				</line> -->
+				<!-- <line> <reportElement mode="Opaque"> <xsl:variable name="x" select="@x_position" 
+					/> <xsl:variable name="y" select="@y_position" /> <xsl:variable name="x2" 
+					select="@x2_position" /> <xsl:variable name="y2" select="@y2_position" /> 
+					position <xsl:choose> <xsl:when test="$x2 > $x"> <xsl:attribute name="x"> 
+					<xsl:value-of select="round($x div $positionRate)" /> </xsl:attribute> <xsl:attribute 
+					name="width"> <xsl:value-of select="round(($x2 - $x) div $positionRate)" 
+					/> </xsl:attribute> </xsl:when> <xsl:otherwise> <xsl:attribute name="x"> 
+					<xsl:value-of select="round($x2 div $positionRate)" /> </xsl:attribute> <xsl:attribute 
+					name="width"> <xsl:value-of select="round(($x - $x2) div $positionRate)" 
+					/> </xsl:attribute> </xsl:otherwise> </xsl:choose> <xsl:choose> <xsl:when 
+					test="$y2 > $y"> <xsl:attribute name="y"> <xsl:value-of select="round($y 
+					div $positionRate)" /> </xsl:attribute> <xsl:attribute name="height"> <xsl:value-of 
+					select="round(($y2 - $y) div $positionRate)" /> </xsl:attribute> </xsl:when> 
+					<xsl:otherwise> <xsl:attribute name="y"> <xsl:value-of select="round($y2 
+					div $positionRate)" /> </xsl:attribute> <xsl:attribute name="height"> <xsl:value-of 
+					select="round(($y - $y2) div $positionRate)" /> </xsl:attribute> </xsl:otherwise> 
+					</xsl:choose> </reportElement> </line> -->
 			</xsl:when>
 			<!-- staticText -->
 			<xsl:when test="$type='Text'">
@@ -425,10 +408,10 @@
 									<xsl:value-of select="concat('$F{',$value,'}')" />
 								</xsl:when>
 								<xsl:when test="$type='FormulaField'">
-									<xsl:value-of select="concat('@FormulaField ',$value)" />
+									<xsl:value-of select="concat('$V{',substring($value,2),'}')" />
 								</xsl:when>
 								<xsl:when test="$type='SpecialVarField'">
-									<xsl:value-of select="concat('@SpecialVarField ',$value)" />
+									<xsl:value-of select="concat('$V{',$value,'}')" />
 								</xsl:when>
 								<xsl:otherwise>
 									<xsl:value-of select="concat('@Unknown ',$value)" />