11.1 事件机制详解
前面通过脚本获取数据源,以及在报表中利用单元格或者数据项的onRender方法添加脚本来增加交互性,或者直接在脚本编辑器中书写少量代码,或多或少的都利用到了BIRT的脚本和事件机制,但这仅仅只是冰山一角。
BIRT提供了一个基于Mozilla Rhino的脚本模型。报表引擎创建报表的过程可以划分为两个阶段——生成和呈现。生成阶段利用报表设计,生成一个名为报表文档的中间文件。呈现阶段利用报表文档进行渲染,生成HTML或PDF。报表生产线既可以将两个阶段作为一个任务执行,也可以作为两个任务分别执行。如果作为一个任务,那么报表文档是生成在内存中。在设计器中选择『以HTML方式预览』时,默认是采用这种方式的。反之,如果作为两个任务分别执行,那么报表文档将被保存在磁盘中。在设计器中选择『在浏览器中预览』时,默认是采用这种方式的。
每一个阶段的事件都通过事件处理器覆盖,用以修改报表内容。既可以用JavaScript,也可以用Java。
事件:
三大对象——报表对象、报表元素和数据源(集)——具有脚本事件。当前所处的阶段决定了可以定制的事件类型和对象属性。
下图描绘了包含一个表和一个数据元素的简单报表的事件触发顺序:
产生阶段:
展现阶段:
我们以一个报表为例来打印出事件的执行顺序:
我们新建报表javascript_logging_demo.rptdesign,选用脚本数据源,定义数据集,
仅仅只有两列
row_int 整数
row_string 字符串
我们在获取数据集的时候必须书写两个方法:
open方法
rowCount = 0;
fetch方法:
while (rowCount < 5) {
rowCount ++;
row['row_int'] = rowCount;
row['row_string'] = "another string " + rowCount;
return true;
}
把两个数据列拖入一个1行2列的表中,布局报表报表,做适当美化,预览效果如下:
为了查看这个报表的事件执行顺序,我们需要在报表,数据源,数据集,表,行,数据项上书写一系列日志,方法如下:
选择大纲视图,选择报表编辑器的脚本查看选项卡:
我们选中报表名称,在initialize中书写如下的语句:
- // INTIALIZE THE LOGGER WITH A FILE BASED LOGGER
- importPackage(Packages.java.util.logging);
- importPackage(Packages.logging);
- var fileHandler = new FileHandler("javascript.log", false);
- //fileHandler.setFormatter(new BirtEventFormatter());
- var rootLogger = Logger.getLogger("");
- rootLogger.addHandler(fileHandler);
- function log ( str ){
- Logger.getAnonymousLogger().info(str);
- }
- reportContext.setPersistentGlobalVariable("log", log);
- log("Initialize");
// INTIALIZE THE LOGGER WITH A FILE BASED LOGGER
importPackage(Packages.java.util.logging);
importPackage(Packages.logging);
var fileHandler = new FileHandler("javascript.log", false);
//fileHandler.setFormatter(new BirtEventFormatter());
var rootLogger = Logger.getLogger("");
rootLogger.addHandler(fileHandler);
function log ( str ){
Logger.getAnonymousLogger().info(str);
}
reportContext.setPersistentGlobalVariable("log", log);
log("Initialize");
说明:源码的含义是生成一个javascript.log文件,用来记录日志信息,并把写日志事件设置成全局常量方法,以便在其他方法中直接调用。
这样,我们在选中数据源,数据集,表,行,单元格,数据项时,即可通过下拉方法框书写一系列日志。
例如在数据源上:
beforeOpen | log("Data Source Before Open"); |
Open | log("Data Source Open"); |
beforeClose | log("Data Source Before Close"); |
close | log("Data Source Close"); |
afterClose | log("Data Source After Close"); |
在数据集上
beforeOpen | log("Data Set Before Open"); |
Open | log("Data Set Open"); |
fetch | log("Data Set Fetch"); |
onFetch | log("Data Set OnFetch"); |
beforeClose | log("Data Set Before Close"); |
close | log("Data Set Close"); |
afterClose | log("Data Set After Close"); |
其它事件类似,不一一举例。
运行报表,我们在eclipse的根目录下可以看到产生的javascript文件:
内容如下:
<?xml version="1.0" encoding="GBK" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780241</millis>
<sequence>170</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Initialize</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780241</millis>
<sequence>171</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Table onPrepare</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780241</millis>
<sequence>172</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Row onPrepare</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780241</millis>
<sequence>173</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Cell onPrepare</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780241</millis>
<sequence>174</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Data onPrepare</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780241</millis>
<sequence>175</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>before factory</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780241</millis>
<sequence>176</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>before render</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>177</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Data Source Before Open</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>178</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Data Source Open</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>179</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Data Source Afger Open</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>180</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Data Set BeforeOpen</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>181</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Data Set Open</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>182</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Data Set AfterOpen</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>183</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Data Set Fetch</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>184</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Data Set OnFetch</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>185</sequence>
<level>INFO</level>
<class>sun.reflect.NativeMethodAccessorImpl</class>
<method>invoke0</method>
<thread>12</thread>
<message>Data Set Fetch</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>186</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Set OnFetch</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>187</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Set Fetch</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>188</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Set OnFetch</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>189</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Set Fetch</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>190</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Set OnFetch</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>191</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Set Fetch</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>192</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Set OnFetch</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780256</millis>
<sequence>193</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Set Fetch</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>194</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Table onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>195</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Table onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>196</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>197</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>198</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>199</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>200</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>201</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>202</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>203</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>204</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>205</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>206</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>207</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>208</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>209</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>210</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>211</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>212</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>213</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>214</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>215</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>216</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>217</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>218</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>219</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>220</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>221</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>222</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>223</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>224</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onCreate</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>225</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onRender</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>226</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Set BeforeClose</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>227</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Set Close</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780272</millis>
<sequence>228</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Set AfterOpen</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780288</millis>
<sequence>229</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Table onPageBreak</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780288</millis>
<sequence>230</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onPageBreak</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780288</millis>
<sequence>231</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onPageBreak</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780288</millis>
<sequence>232</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onPageBreak</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780288</millis>
<sequence>233</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onPageBreak</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780288</millis>
<sequence>234</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Row onPageBreak</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780288</millis>
<sequence>235</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>after render</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780288</millis>
<sequence>236</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Source Before Close</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780288</millis>
<sequence>237</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Source Close</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780288</millis>
<sequence>238</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>Data Source After Close</message>
</record>
<record>
<date>2013-01-05T10:43:00</date>
<millis>1357353780288</millis>
<sequence>239</sequence>
<level>INFO</level>
<class>sun.reflect.GeneratedMethodAccessor24</class>
<method>invoke</method>
<thread>12</thread>
<message>after factory</message>
</record>
</log>
从message标签我们可以看到各个方法的执行顺序和执行时间。
11.2 javascript事件绑定
reportContext和this:
在使用Script编辑器时,如果选择Pallette View,那么会显示选定的报表元素、指定事件中能够使用的函数和变量。例如,下图指出了某个数据元素的onCreate事件能够使用的函数和变量:
this可用于在事件中列出元素的所有方法和属性。
reportContext则可以用于访问和修改报表一级的属性。开发人员可用它来设置全局变量。例如:
报表的onInitialize事件
reportContext.setPersistentGlobalVariable("testglobal", "test global string");
用Persistent版本的方法能让变量跨持久化。变量是Object类型的,具有高度的灵活性。
某个表中一个标签的onPrepare事件
this.text = reportContext.getPersistentGlobalVariable('testglobal');
全局变量可以通过绑定编辑器赋给数据元素。只需在给定列的表达式构建器中引用该变量即可。例如,如果绑定编辑器中有一列,其值从数据库取回。那么可以通过以下的表达式,在原值后附加上某个全局变量的值:
dataSetRow["MyString"] + "-" + reportContext.getPersistentGlobalVariable('testglobal');
reportContext也可用于访问会话级变量。
// attributeBean是Birt Viewer提供的一个会话级变量
myAttributeBean = reportContext.getHttpServletRequest.getAttribute('attributeBean');
reportDoc = myAttributeBean.getReportDocumentName();
this.text = reportDoc;
reportContext允许访问和修改脚本内使用的上下文。例如:
报表的onInitialize事件
appContext = reportContext.getAppContext();
importPackage(Packages.java.util)
myArrList = new ArrayList();
myArrList.add("one");
myArrList.add("two");
appContext.put("AppContextTest", myArrList);
这段代码读取了当前的应用上下文,并进行了一些修改。然后,可以在某个标签元素的onPrepare事件处理器中,这样使用:
appContext = reportContext.getAppContext();
myObject = appContext.get("AppContextTest");
this.text = myObject.size();
上例也可以这样实现:
reportContext.setPersistentGlobalVariable("testglobal", myArrList);
reportContext还可用于获取当前的区域信息,以及存储于资源文件中的消息。
报表级事件
afterFactory | 结束生成阶段时执行 |
afterRender | 结束呈现阶段时执行 |
beforeFactory | 开始生成阶段前执行 |
beforeRender | 开始呈现阶段前执行 |
initialize | 开始生成阶段和呈现阶段前执行 |
在initialize事件中,可以定义全局函数、变量和对象。例如,创建一个全局的函数:
function gTest(v){
return "Global Function:" + v;
}
// 仅在图表脚本中使用时需要
reportContext.setPersistentGlobalVariable("gTest", gTest);
只需这样调用:
gTest("MyTest");
或:
gTest = reportContext.getPersistentGlobalVariable("gTest");
val = gTest("Use Persistent");
在图表脚本中访问reportContext时,使用:
context.getExternalContext().getScriptable()
如,图表标题可以这样修改:
function beforeGeneration(chart, context){
importPackage(Packages.org.eclipse.birt.chart.model.type.impl);
newChartTitle = context.getExternalContext().getScriptable().getPersistentGlobalVariable("testglobal");
chart.getTitle().getLabel().getCaption().setValue(newChartTitle);
}
在beforeFactory中,有几个方法可以用于访问报表中的元素。需要对元素命名。例如,想要在动态文本元素"TestHeader"中显示数据集"orders"的查询语句,可以在beforeFactory中这样写:
query = this.getDataSet("orders").queryText
this.getDynamicText("TestHeader").valueExpr = "query;";
报表元素级事件
onPrepare | 生成阶段中,为每个报表元素调用一次。可用于修改设计。变更影响元素的所有实例,例如,所有的表行。 |
onCreate | 生成阶段中调用。可访问和修改元素的某个实例(如,每隔9行设置1行背景为红色) |
onRender | 呈现阶段中调用。类似于onCreate。不可访问数据。 |
一个非常简单的例子——某表中的明细行:
onPrepare:
this.getStyle().backgroundColor = "red"; // 影响所有行
onCreate:
if (this.getRowData().getExpressionValue(3) > 100)
this.getStyle().backgroundColor = "red"; // 只影响该行
如果该表中有100行,则onPrepare只调用1次,而onCreate和onRender将调用100次。
元素级事件实例
设置标签、文本、动态文本和数据元素的值
标签:onPrepare/onCreate
this.text = "My New Label"
文本:
this.context = "My New Text"
动态文本:
this.valueExpr = "row['CITY']";
this.valueExpr = "'my row count: ' + (row[0] + 1)";
数据元素:
使用绑定编辑器。
设置TOC
类似于值表达式,期待字符串:
this.tocExpression = "'tocbyrownumber: ' + row[0]";
使用行数据
在onCreate中可使用行数据,可用于对值进行检查。
this.getRowData().getExpressionValue(i) // 第i列的值
this.getRowData().getExpressionValue("some_expression") // 对该行套用表达式的值
例如:
if (this.getRowData().getExpressionValue(1) == "product1")
this.getStyle().backgroundColor = "red";
if (this.getRowData().getExpressionValue("row[price]" == "$30")
this.getStyle().backgroundColor = "blud";
修改超链接
可在onPrepare中修改:
this.getAction().URI = "'http://www.google.com'";
getStyle
用于定制给定元素的属性。例如:
this.getStyle().fontWeight = "bold";
getParent
用于访问父元素。例如,从数据元素获取表:
this.getParent().getParent().getParent();
父子层级如下:dataElement->Cell->Row->Table
所以如果你想从一个数据元素改变它的表的背景,就可以这么更改:this.getParent().getParent().getParent().getStyle().backgroundColor = "Silver";
getValue
满足一些基于值变更视觉外观的需求。
if (this.getValue() > 30){
this.getStyle().fontFamily = "Arial"
this.getStyle().backgroundColor = "Yellow"
}
或者用这种方式也行:
if (this.getRowData().getExpressionValue("row[QtyOrdered]") > 30){
this.getStyle().fontFamily = "Arial"
this.getStyle().backgroundColor = "Yellow"
}
命名表达式
是指在某个元素上创建,并给予命名的表达式。其定义可在onPrepare中修改,其值可在onCreate和onRender中访问。例如,定义一个表达式totalCreditValue,其值为Total.sum(row[?CREDITLIMIT?])。然后,就可在其他元素中用JavaScript和Java访问。
例如,在某个表上建一个表达式"RWC",值为row[0],则可在行中用以下方式访问:
rc = this.parent.getNamedExpressionValue("RWC");
数据源事件:
beforeOpen | 数据源打开阶段,在连接数据源之前调用的脚本 |
afterOpen | 数据源打开之后的阶段调用的脚本 |
beforeClose | 在数据源关闭之前,可以调用的脚本 |
我们可以在数据源打开之前传入数据库密码,就是在beforeOpen中书写:
currentPassword = this.getExtensionProperty("odaPassword");
DataSourceClass = new Packages.myExternalSecurity();
this.setExtensionProperty("odaPassword", DataSourceClass.getPassword());
不过现在有了数据绑定,所以这种用法并不常见。
数据集事件:
beforeOpen | 数据集打开阶段,在连接数据源获取数据集之前调用的脚本 |
afterOpen | 数据集打开之后的阶段调用的脚本 |
fetch | 用于获取行数据阶段调用脚本 |
beforeClose | 在数据集关闭之前,可以调用的脚本 |
afterClose | 在数据集关闭之后,可以调用的脚本 |
如果是脚本数据源,那么在数据源上有open,close方法,数据集上还有open,fetch,close方法:
例如我们可以在beforeOpen中书写下面的脚本用来定制查询:
this.queryText = "SELECT * FROM Customers where CustomerID IN (" + params["customersInClause"] +")";
如果是脚本数据源,可以如下书写:
打开数据集阶段的事件open:
importPackage(Packages.test.my.ds)
myDataSet = new DS();
myArrayList = myDataSet.getList();
myIter = myArrayList.iterator();
获取数据集阶段fetch:
if( !myIter.hasNext() ){
return false;
}
//myOnlyColumn 必须已经在数据集中已经定义了
row["myOnlyColumn"] = iter.next();
return true;
我们可以在脚本中书写更复杂的逻辑,用来在运行时控制报表的显示。
例如在一个beforeOpen的方法中输入下面语句:
importPackage(Packages.org.eclipse.birt.report.model.api);
importPackage(Packages.org.eclipse.birt.report.model.api.elements);
delm = reportContext.getReportRunnable().designHandle.getDesignHandle().findElement("QTYELEMENT");
mr = StructureFactory.createMapRule();
mr.setTestExpression("row[\"QUANTITYORDERED\"]");
mr.setOperator(DesignChoiceConstants.MAP_OPERATOR_GT);
mr.setValue1("40");
mr.setDisplay("A lot");
ph = delm.getPropertyHandle(StyleHandle.MAP_RULES_PROP);
ph.addItem(mr);
说明,上面语句的含义是给报表添加一个映射MapRule,让行row["QUANTITYORDERED"]大于40的数据项都显示成"A lot"
预览如下:
我们还可以让它不显示HideRule:
importPackage(Packages.org.eclipse.birt.report.model.api);
importPackage(Packages.org.eclipse.birt.report.model.api.elements);
delm = reportContext.getReportRunnable().designHandle.getDesignHandle().findElement("QTYELEMENT");
hr = StructureFactory.createHideRule();
hr.setFormat("html");
hr.setExpression("if( row[\"QUANTITYORDERED\"] > 30 ){true;}else{false;}");
ph = delm.getPropertyHandle("visibility");
ph.addItem(hr);
预览效果如下:
也能动态增加排序字段:
importPackage(Packages.org.eclipse.birt.report.model.api);
importPackage(Packages.org.eclipse.birt.report.model.api.elements);
delm = reportContext.getReportRunnable().designHandle.getDesignHandle().findElement("mytable");
sc = StructureFactory.createSortKey();
sc.setKey("row[\"CONTACTLASTNAME\"]");
sc.setDirection("asc");
ph = delm.getPropertyHandle(TableHandle.SORT_PROP);
ph.addItem(sc);
下面的语句是给报表添加自动刷新和用户刷新,我们把它放置在任何onPrepare中即可:
var paramsString = "";
var paramDefs = reportContext.getDesignHandle().getAllParameters();
for (i = 0; i < paramDefs.size(); i++ ) {
var paramDef = paramDefs.get(i);
if (paramDef.getClass().toString() == "class org.eclipse.birt.report.model.api.ScalarParameterHandle") {
var paramVal = reportContext.getParameterValue(paramDef.getName())
if (paramVal == null || paramVal == "null") {
paramVal = "";
} else if (paramVal.length > 0) {
var paramValTmp = "";
for (j = 0; j < paramVal.length; j++) {
if (paramVal[j] != null && paramVal[j] != "null") {
if (j > 0)
paramValTmp += "|";
paramValTmp += encodeURIComponent(paramVal[j]);
}
}
paramVal = paramValTmp;
} else {
paramVal = encodeURIComponent(paramVal);
}
paramsString += "&" + paramDef.getName() + "=" + paramVal;
}
}
this.content="<form name='input' onSubmit='return reloadPage();'>"
+"<input type='submit' value='refresh report' οnclick='reloadPage()'>refresh manual</input></form>"
+"<script type=text/javascript'>"
+"function reloadPage() {"
//alert( targetURL );
+" var targeturl = window.location+'"+paramsString+"';"
+" location.replace(targeturl);"
+" return false;"
+"}"
+"timer=setTimeout('reloadPage()', 20000);"
+"</script>"
当然,图表也能书写脚本,如下所示:
var chart1 = this.getReportElement( "Chart1" )
var chart2 = this.getReportElement( "Chart2" )
var chart3 = this.getReportElement( "Chart3" )
var chart4 = this.getReportElement( "Chart4" )
var chart5 = this.getReportElement( "Chart5" )
var chart6 = this.getReportElement( "Chart6" )
var chart7 = this.getReportElement( "Chart7" )
var chart8 = this.getReportElement( "Chart8" )
var chart9 = this.getReportElement( "Chart9" )
var chart10 = this.getReportElement( "Chart10" )
var chart11 = this.getReportElement( "Chart11" )
var chart12 = this.getReportElement( "Chart12" )
var chart13 = this.getReportElement( "Chart13" )
var color1 = chart1.getTitle().getCaption().getColor()
var color2 = chart2.getTitle().getCaption().getColor()
var font = chart3.getTitle().getCaption().getFont()
chart1.setColorByCategory( true );
chart1.getTitle().getCaption().setValue( "Color by Category" );
chart1.setColorByCategory( true );
chart1.getTitle().getCaption().setValue( "Color by Category" );
chart2.setColorByCategory( false );
chart2.getTitle().getCaption().setValue( "Color by Value Series" );
color1.setRed( 255 );
color1.setGreen( 0 );
color1.setBlue( 0 );
chart1.getTitle().getCaption().setColor( color1 );
chart2.setColorByCategory( false );
chart2.getTitle().getCaption().setValue( "Color by Value Series" );
color2.setRed(255);
color2.setTransparency( 127 );
chart3.getDescription().setValue("newDesc");
chart3.getTitle().getCaption().setValue( chart3.getDescription().getValue() );
font.setSize( 9 );
font.setBold( false );
font.setItalic( true );
font.setStrikeThrough( true );
font.setUnderline( true );
chart4.setDimension( "ThreeDimensional" )
chart5.setDimension( "TwoDimensional" )
chart6.setDimension( "TwoDimensionalWithDepth" )
chart7.setDimension( "TwoDimensional" )
chart8.setDimension( "TwoDimensionalWithDepth" )
chart9.setDimension( "ThreeDimensional" )
chart10.getCategory().setSorting( "Descending" )
chart10.getTitle().getCaption().setValue(chart10.getCategory( ).getOptionalValueGroupingExpr())
chart11.getTitle().getCaption().setValue( chart11.getOutputType() )
chart12.setOutputType("PNG")
chart12.getTitle().getCaption().setValue( chart12.getOutputType() )
chart13.getLegend( ).setVisible( true );
chart13.getLegend( ).setShowValue( true );
chart13.getLegend( ).getTitle( ).setVisible( true );
chart13.getLegend( ).getTitle( ).getCaption( ).setValue( "Legend" )
说明,以上语句修改了13个图表,修改了分类颜色,标题,字体,排序等等
具体的使用说明,参考BIRT engine API: