<?xml version="1.0" encoding="UTF-8"?><!-- generator="WordPress/2.6.2" -->
<rss version="0.92">
<channel>
	<title>Java报表工具</title>
	<link>http://javareport.cn</link>
	<description>Java报表,web报表,报表工具,报表系统,Java报表工具,java相关技术</description>
	<lastBuildDate>Wed, 08 Sep 2010 01:07:06 +0000</lastBuildDate>
	<docs>http://backend.userland.com/rss092</docs>
	<language>en</language>
	
	<item>
		<title>授权问题与解决办法汇总（三）</title>
		<description>问题描述

某客户的集群环境中使用了绑定ip的授权，其中一台59的机器出现问题，提示：服务器IP地址127.0.0.1与License文件中授权的IP地址不符！

集群环境中除59机器，其他正常，客户服务器均为unix系统。

授权信息：IP= 10.48.**.61;10.48.**.59;10.48.**.53;10.48.**.4

问题分析

导致这个问题的原因可能有两方面：

一是授权本身制作有问题，比如ip绑定错误或ip输入不规范。通过查看和客户确认和查看授权信息基本上排除了这两种可能；

二是客户这台59的机器和其他的不同，主要可能硬件如网卡不尽相同。这需要通过程序获取一下本机ip来做测试。

解决方法

我们使用润乾匹配授权时获取ip的方法，在59本机获取一下当前ip。java.net.InetAddress.getLocalHost().getHostAddress()，经反馈得知，结果为127.0.0.1，所以我们确认问题出在客户机上。

让客户进行了如下操作：

查看 /etc/hosts文件，里面有一条本机名和 222.xxx.xxx.xx这个 IP 对应的记录。把它注释掉，然后修改本机的主机名，又在 hosts文件中加入主机名和222. xx.xx.xx的对应，问题解决了。

总结

通过问题的解决方法，我们可以发现InetAddress.getLocalHost().getHostAddress()方法找到本机 IP的实现方法–依靠本机的机器名去查询IP 地址，和 ping `hostname` 返回的 IP地址是同一个，并不是 ipconfig 方法得到的 eth0 IP 地址。

在windows中InetAddress.getLocalHost().getHostAddress()获得的值可能是在/system32/drivers/etc/host文件中的值。 </description>
		<link>http://javareport.cn/archives/833</link>
			</item>
	<item>
		<title>润乾报表中多种日期格式的展示</title>
		<description>润乾报表中为我们提供了很多样式的日期显示格式。常用的日期格式，例如2010/08/09、2010-08-09、2010年8月9日等格式的日期，都可以通过下图所示的显示格式编辑框中的日期格式加以限制。若我们希望日期显示为20100809，然而日期的格式中，并没有提供相应模板，我们可以自定义模板yyyyMMdd即可实现上述需求。



然而在实际应用中，各种项目需求层出不穷，仅仅能够控制年月日的位置和显示的格式是不够的。

下面来介绍另外一种日期格式的展示。

在一些本地化的软件中，希望将日期写成这样，例：二〇一〇年八月九日。关于这样的格式就不能简单的使用格式编辑来实现，需要自己定义日期的格式。下面来介绍一下如何实现这种负责格式的日期显示。

首先明确转换过程中需要使用到的函数，第一个是chn()，将阿拉伯数字转换成我们本地数字；第二个是year()、month()和day()，这三个函数分别获得年月日的值；最后还需要一个替换函数rplc()，将转换成中文的零替换成要求的〇。

如下图所示我们在单元格中写：=rplc((chn(year(now()))+”年”+chn(month(now()))+”月”+chn(day(now()))+”日”),”零”,”〇”)，即实现了上述要求。



总结：通过多次的转换和替换完成了这个日期格式的显示。整个过程中并没有使用一些繁琐的函数，所使用的都是最基础的函数。所以在无法直接实现某些需求的情况下，不妨换个角度思考一下，也许问题就很容易解决了。 </description>
		<link>http://javareport.cn/archives/831</link>
			</item>
	<item>
		<title>第三方推广：“组头合并格设置不合理”错误的分析</title>
		<description>在润乾报表中，行属性的类型可以设为”分组表头”，分组表头每页都重复，但是分栏的时候不重复，常用于固定表头。关于组头的使用详情，请参考润乾4.5的用户手册4.4.2节。

但是，表头中往往包含跨行的合并格。跨行的合并格作为表头时，对分组表头的使用不了解的客户认为应该将合并格所在行的”组头级别”设置相同。此时，就会报”组头合并格设置不合理”的错误，如下图所示。



在润乾中，单级分组表头可以包含多行，但是每一行的组头级别必须递增，否则就会报错。在上图中，行号为1的行和行号为2的行中存在合并格，但是这两行的组头级别相同，都为1。当发布的时候，就会出现”组头合并格设置不合理”的错误。

通过修改组头级别就可以修正这个错误。组头级别的设置如下图所示：



要解决第一幅图中的错误，只需要将第一行的”组头级别”设为1，第二行的”组头级别”设为2。修改后发布，在浏览中如下展示如下图所示：

 </description>
		<link>http://javareport.cn/archives/829</link>
			</item>
	<item>
		<title>通过api将Excel转化成raq模板</title>
		<description>背景说明

Excle文件中的sheet转换成raq模板，在设计器里转换，是非常简单的。下面介绍如何用api代码转换。

应用举例

新建一个类文件，在类文件中写如下代码 ：
package com.runqian.test;
import com.runqian.report4.ide.ExcelImporter;
import com.runqian.report4.usermodel.IReport;
import com.runqian.report4.util.ReportUtils;
public class ExcelAsRaq {
public static void main(String[] args) {
String excelFile = “F:/tomcat/Tomcat 5.5/webapps/second/reportFiles/yuangong.xls”;//excel文件的路径
ExcelAsRaq dexcel = new ExcelAsRaq();
try {
IReport iReport = dexcel.excelToReport(excelFile, 0);//excel文件转换，取某个sheet转换成的raq模板，从0开始
ReportUtils.write(”F:/tomcat/Tomcat 5.5/webapps/second/reportFiles/yuangong.raq”,iReport);//保存为raq模板的路径
} catch (Exception ex) {
ex.printStackTrace();
}
}
//将excle文件转换为raq模板，返回的是一个IReport对象
private IReport excelToReport(String excelFile, int sheetNum) throws Exception {
ExcelImporter ei = new ExcelImporter(excelFile);
return ei.getReport(sheetNum);
}
}

这样，在相应路径下就有raq模版了。 </description>
		<link>http://javareport.cn/archives/826</link>
			</item>
	<item>
		<title>分页web报表如何统计当前页与其前几页的信息</title>
		<description>

Web报表分页显示是最常见的展示方式之一，博计报表可以根据不同的条件来设置报表的分页。然而报表分页也遇到许多新的需求，如：如何只对当前页某列数据进行统计、如何对当前页及其前几页某列数据进行统计以及如何实现对所有页某列数据的统计。

对所有页某列数据统计可以直接使用数据集函数，如：ds1.sum（某字段名）

而对于要求实现当前页及其前几页某列数据统计，博计报表没有提供专门的函数实现，但是可以使用变通的方式，使用手动分组强制分页的方式实现该需求。 这里的手动分组是指一组数据内让其显示固定条数的数据（如10条），用数据总条数/10就是分组的个数（如果总条数%10!=0，需要加1），然后在每组 后面设置强制分页，这样就可实现每页固定显示10行数据的效果。

本文介绍博计报表实现当前页及其前几页某列数据统计的报表设计过程，以例子形式说明。

第一步：

打开设计器，新建一张空白的报表，然后建一个内建数据集ds1，数据集很简单，只包含一个字段，并且也是对该字段进行统计，如下图：



其中，ID为数据集的字段名，数据类型为字符串，总共增加40条数据。

第二步：

按每页展现10行数据，根据查询数据的总记录条数计算出总共分几页显示，本例中在A1单元格存放计算出的分页结果，表达式为：

=if(ds1.count()%10==0,int(ds1.count()/10),int(ds1.count()/10)+1)

第三步：

根据上步中计算出的分页总页数，手动设置分组，本例中表达式写在A2单元格，为：=list (1 to A1)。这一步的作用就是用分组模拟出分页。

第四步：

按每页显示10条数据，分配查询每页的数据。

本例在B2单元格设置表达式为=list(1 to 10)，这里实际作用相当于按行分页，每页10行数据。C3中表达式为=(A2-1)*10+B2，作用为生成所有数据的连续序列号。D4单元格为根据序列号生成的查询字段（ID）表达式。

第五步：

计算数据

计算数据分当前页计算及当前页与前几页数据和。当前页数统计直接使用=sum(D2{})，而当前页与前几页的数据统计则需要用到层次坐标，这里设置表达式为=D3+D4[-1]。

第六步：

设置模拟分页列A列与设置模拟每页显示10条数据列B列为隐藏列。

第七步：

设置第4行为强制行后分页（如下图），实现分页效果。



报表设计完成后的效果图如下：



报表发布后，分页效果图如下(第一页)：



然后看一下第二页，检验计算结果（如下图）：



到此可以看到数据统计结果是正确的，实现了当前页与前几页数据求和的要求。 </description>
		<link>http://javareport.cn/archives/823</link>
			</item>
	<item>
		<title>读入导出rat文件</title>
		<description>

在使用快逸报表的过程中，在设计器中点击预览按钮，或者点击F9按钮，就可以浏览已经设计出来的报表了。既可以检查设计的样式，为进一步修 改报表做准备，也可以对查询出来的数据进行检查，看看是否出现错误。在这时点击保存，会发现保存为一个与raq文件同名的.rat文件。如果浏览的这张报表上没有错误信息，我们也可以把它当做预览结果，浏览数据。由于导出功能可以保存当时的数据信息，就可以对数据实时的情况进行保存，以便日后查看。这种保 存方法既提高了效率，又减少了对内存的占用，所以有些客户会选择这种方式来对数据进行浏览和实时情况的保存。

下面就介绍一下用代码实现保存和读取rat文件的方法。

首先需要引入相关的文件：

&#60;%@ page import=”java.io.*”%&#62;
&#60;%@ page import=”com.runqian.report4.usermodel.*”%&#62;
&#60;%@ page import=”com.runqian.report4.model.*”%&#62;
&#60;%@ page import=”com.runqian.report4.util.*”%&#62;
&#60;%@ page import=”com.runqian.report4.usermodel.graph.*”%&#62;
第一步，读取报表模版
FileInputStream in = new FileInputStream(”C:\\test.raq”); //根据文件名新建文件输入流
ObjectInputStream ois = new ObjectInputStream(in); //新建对象输入流
第二步，计算报表
ReportDefine rd = new ReportDefine2(1, 1);
Context cxt = new Context();
Engine engine = new Engine(rd, cxt); //构造报表引擎
IReport iReport = engine.calc();
第三步，将计算好的ireport对象导入到rat文件，
OutputStream out1 = new FileOutputStream( “C:\\test.rat” );
ReportUtils.write(out1,iReport);
out1.close();

这样就会发现在c盘根目录下有test.rat这个文件。

下面说一下读入的方法：

FileInputStream in = new ...</description>
		<link>http://javareport.cn/archives/820</link>
			</item>
	<item>
		<title>快逸报表在vista和win7下无法浏览应用的解决办法</title>
		<description>

对于vista和win7系统，快逸报表有着良好的兼容性，无论是设计器还是实际应用。有些客户在安装报表设计报表的时候没有遇到问题，但 是在这两种系统下会发现无法启动应用，或者打开设计器自带的ie浏览页面后，页面一直在读取，并没有展示出应有的界面。会出现这个问题是因为在这两种系统 下c盘是对users受写保护的，在安装设计器的时候的权限不足，当启动应用的时候，由于没有足够的权限才导致这个问题。

如果重新安装到其他盘符下，就不会有问题了。

如果不重新安装，解决思路如下：使用管理员身份登陆操作系统，给tomcat配置可用的权限，就可以实现应用的访问了。

解决方法：找到$TOMCAT_HOME$conf，把conf文件夹设置为完全控制。



（右键属性-安全-找到当前登录名-下面选择完全控制）

保存，重启TOMCAT 。

注意：

重要的是”当前登录名”，不是”CREATOR OWNER”，也不是”Administrator”，如果没有当前用户的话，添加一个即可。 </description>
		<link>http://javareport.cn/archives/818</link>
			</item>
	<item>
		<title>快逸报表同时多列纵向扩展</title>
		<description>

在快逸报表中，属性中有对报表中分栏的设置，通过简单的设置可以完成分栏报表的设计，在页面上展示出来分栏的效果。有些客户在进行设计时需要在报表的内部根据相关的条件进行分栏展示，本篇文章就着重介绍一下这种报表的设置方法。

首先先看一下数据库表结构和数据：



其中，Pname是 姓名，PYEAR 是入职年份。

按照年分分类，然后在每个年份下循序显示所有的姓名，这个报表如何实现呢？

实现思路：先用group（）函数对年份进行分组。然后将每个年份下的数据取出来用valueat（）函数进行匹配。下面是报表的设计：



C2中 =ds1.Group(PYEAR)，按照年份分组。

C3中 =ds1.count()，主要目的是计算出每个年份下有多少条记录。

B3中 =max(C3{})，取到所有年份下，记录条数最多一个年份的记录数。

B4中 =1 to B3，扩展出需要的行数，以便所有的记录都能显示出来，而且为数据的扩展提供其中一个参数。

C4中 =valueat(ds1.select(Pname),B4-1)，使用ds1.select(Pname)函数取得当年的所有记录，然后再用valueat（）函数配合B4提供的参数取得数据集内相应的数据。

在web中展示如下：



这样报表就设计完了，客户可以根据自己的需求隐藏掉相关行，也可以根据需要在数据的左侧匹配上相关的数据，满足客户的各种需求。 </description>
		<link>http://javareport.cn/archives/816</link>
			</item>
	<item>
		<title>行式填报表中填报监听类的使用小例</title>
		<description>

行式填报表是快逸报表提供的一种特殊的填报表，它相对于普通的填报表而言具有以下优点：
1 在网页上可以动态地实现增加、删除、修改行的数据
2 增加行时可以引用定义的流水号，实现流水号在增加行时自动运算（如递增）的功能
3 可以实现在网页上动态地导入不定行的excel数据

如果有这样的需求：某个报表的数据是从物理表A检索出来的，但是由于某些业务需要，物理表B引用了A表中的某些数据，如果要更新A中数据的同时也要 更新B表中的数据，在A表中添加数据的时候直接在A中添加就可以了，在删除物理表A中数据的同时，要检查B表中是否引用了这个要删除的数据，如果引用了也 要同时把B表中的这个值更新为空。

这样的需求，用行式填报表实现最好了，因为都是整条数据的添加、删除。但是如何实现更新A表也要更新B表，删除A表中的数据也要删除B表中的数据，A表中插入新数据但是不影响B表。

快逸报表提交的时候涉及到三种对数据库的操作：插入(insert) 、删除(delete) 、更新(update)。

行式填报表在提交时的具体体现是：
(1) 在原有数据基础上进行了修改，提交时执行的是update
(2) 在原有数据基础上删除删除了某行，提交时执行的是delete
(3) 在原有数据基础上插入新一行数据，提交时执行的是insert

实现方法：用行式填报表中的更新属性实现对A表数据的添加、删除、修改；在填报监听类中实现对B表的更新和删除；然后填报监听类中根据sql语句知道哪一行数据是新增的、修改的还是被删除了，这样就可以实现上面的需求了。

那么就可以通过继承填报监听类AbstractInputListener 在afterSave()或者afterCommit()函数中获取提交的sql语句，然后在返回的sql语句中进行遍历，查看sql语句的类型。

下面介绍一下监听类的写法：

public class testColInput extends AbstractInputListener{
public void afterSave() throws Exception {//afterCommit方法也可以
//得到sql语句
InputSQL[] sql = this.getInputSql();
Object arg[];
for (int i = 0; i &#60; sql.length; i++) {
String sqlStr = sql[i].getSql();
// 得到sql语句中的参数
arg = sql[i].getParams();
if (sqlStr.matches(”insert.*”)) {
System.out.println(”这是插入语句:” + sqlStr);
for(int j=0;j&#60;arg.length;j++){
System.out.print(” 第”+j+”参数:”+arg[j]);
}
System.out.println();
}
if (sqlStr.matches(”update.*”)) {
System.out.println(”这是修改语句:” + sqlStr);
for(int ...</description>
		<link>http://javareport.cn/archives/814</link>
			</item>
	<item>
		<title>快逸报表日志文件的配置方法</title>
		<description>

日志系统是一种不可或缺的跟踪调试工具，特别是在无人职守的后台程序以及那些没有跟踪调试环境的系统中有着广泛的应用。 长期以来日志系统作为一种应用程序服务，对于跟踪调试、程序状态记录、崩溃数据恢复都有非常重要的意义。

快逸报表也提供了一套日志系统，只需要简单的配置，不用再开发代码，就可以生成一个完整的日志系统。

下面说一下日志的配置方法：

首先要在WEB-INF下的reportConfig.xml文件中配置日志记录配置属性文件的路径，如下代码：

&#60;config&#62;
&#60;name&#62;logConfig&#60;/name&#62;
&#60;value&#62;/WEB-INF/runqianReportLog.properties&#60;/value&#62;&#60;!–日志文件的路径–&#62;
&#60;/config&#62;

快逸的日志记录配置属性文件为runqianReportLog.properties，默认存放在WEB-INF文件夹下，下面说一下配置文件的内容：

//日志级别可为OFF,ERROR,WARN,INFO,DEBUG,ALL, 优先级依次降低，若为OFF则不输出任何
//日志信息；若为INFO，则只输出ERROR,WARN,INFO等级别的信息，依次类推。
log4j.logger.runqianReportLogger=ALL,LOG1,LOG2
//输出日志到系统控制台
log4j.appender.LOG1=org.apache.log4j.ConsoleAppender
//输出文件的格式
log4j.appender.LOG1.layout=org.apache.log4j.PatternLayout
log4j.appender.LOG1.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %c : [%-5p] %x - %m%n
//日志文件的编码格式，不设置此项在英文操作系统乱码
log4j.appender.LOG1.encoding=UTF-8
//输出日志到指定文件
log4j.appender.LOG2=org.apache.log4j.RollingFileAppender
//可以指定LOG2.File的全路径, 若未指明，则为相对WEB服务器启动文件的路径
log4j.appender.LOG2.File=D:\\newMis2.log
// Append默认值是true,日志记录添加到末尾；false在每次启动时进行覆盖
log4j.appender.LOG2.Append=true
//日志文件的最大字节数
log4j.appender.LOG2.MaxFileSize=10MB
//日志文件的最多备份数
log4j.appender.LOG2.MaxBackupIndex=1
//输出文件的格式
log4j.appender.LOG2.layout=org.apache.log4j.PatternLayout
log4j.appender.LOG2.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %c : [%-5p] %x - %m%n

总结：日志配置文件的内容大部分按照默认值就可以，客户可以根据自己的需要修改日志得输出级别和日志文件的路径。 </description>
		<link>http://javareport.cn/archives/812</link>
			</item>
</channel>
</rss>
