Rtf模板开发例如背景,纹理分栏等等功能都能用word工具实现不再具体总结大家可以参考word教程。。。。。
一.组
定义一个组的目的是告诉XMLPublisher对重复的数据行进行循环显示,也就是说需要使用for-each进行数据记录的循环显示
<?for-each:XML group element tag name?>
……
<?endfor-each?>
分页是自然的,但如果想在某处强制分页如新组新页,那么可以使用Word的分页符(CTRL+ENTER快捷键),但会导致最后出现空白页;这样只能使用如下几种方式:
1、 分组声明中加@section,如<?for-each@section:G_PO_HEADER?>。
2、 <?end for-each?>前加<?split-by-page-break:?>。这个翻译后,实际上是:
<xsl:iftest="position()<last()">
< xsl:attribute name="break-before">page</xsl:attribute>
< /xsl:if>
3、 <?end for-each?>前加<xsl:attributename="break-after">page</xsl:attribute>,此法下RTF最后无空白页,但PDF有空白页。
4、 <?end for-each?>前加<xsl:attributename="break-before">page</xsl:attribute>此法下RTF、PDF最后都有空白页。
1、 任意条件分页,需要借助IF+上面的break-after或者break-before,如:
<?if:CURRENCY_CODE="CNY"?>
< xsl:attribute name="break-before">page</xsl:attribute>
< ?end if?>
2、 固定行分页,需要借助IF+上面的break-after或者break-before,在行<?end for-each?>前,如下语句控制每页5行:
<?if:position() mod 5 =0?>
< xsl:attribute name="break-before">page</xsl:attribute>
< ?end if?>
1、 标准的页眉页脚,即单个页眉页脚,使用Word的功能即可。
2、 扩展的页眉页脚,可使用<?start:body?><?endbody?>把主体部分“框”起来,凡是在这两个标记之外的东西,都将被当作页眉页脚。
1、 可以用Word的“自动图文集”,在任意地方插入页码,这个是“自然页码”。
2、 如果在某种情况下想让页码从特定值开始,比如新的组页码重新编号,则需要借助命令,如在for-each后写:<?initial-page-number:1?>。这里的“1”,实际上也可以用数据文件中的XML元素来替换。
1、 Word可在页眉页脚部分实现首页不同或奇偶页不同,没法实现末页不同,即使借助代码控制,实际实现的也是末页布局不同,而非“页眉页脚”不同。
<?start@last-page:body?><?end body?>
报表本身仅有一页时,则用<?start@last-page-first:body?><?endbody?>
例子“Advanced/LastPage”,注意布局需要独立成页,即之前需要加分页符。
2、 以偶数页结束,主要目的是显示偶数页页眉页脚
<?section:force-page-count;’end-on-even-layout’?>
如果仅显示空白页,则用<?section:force-page-count;’end-on-even’?>
3、 以奇数页结束,主要目的是显示奇数页页眉页脚
<?section:force-page-count;’end-on-odd-layout’?>
如果仅显示空白页,则用<?section:force-page-count;’end-on-odd’?>
七.嵌套模板
由于在页眉和页脚中不允许使用窗体域,而当报表页眉页脚中希望插入XML数据的时候,可以考虑使用嵌套模板。
嵌套模板是在模板中定义一个子模板,然后在需要的地方调用它,如在页眉页脚中调用它。
定义子模板
子模板标记之间可以使用任何的标记和内容,和模板的主体部分没有任何区别
<?template:internaltemplate name?>
……
<?end template?>
. 调用子模板
<?call:internaltemplate name?>
八.图片插入
接插入图片
可以直接在模板中插入jpg、gif或png格式图片
URL链接图片
•在模板中随意插入一张图片
•在设置图片对话框中的网站标签页中,在可选文字中输入如下的URL格式链接
url:{’http://image location’}
url:{’http://www.oracle.com/images/ora_log.gif’}
OA Media 库图片
•在模板中随意插入一张图片
•在设置图片对话框中的网站标签页中,在可选文字中输入如下的URL格式链接
url:{’${OA_MEDIA}/image name’}
url:{’${OA_MEDIA}/ORACLE_LOGO.gif’}
九. 超链接
•使用word中的插入超链接功能来插入静态链接
•如果超链接包括了模板中的数据元素,可以在运行时动态的创建超链接,在链接地址中按如下格式输入:
{URL_LINK}
URL_LINK可以是一个完整的URL地址,也可以使URL地址中的一部分。
它是动态传入的数据元素,如下传入URL的参数:
http://www.oracle.com?product={PRODUCT_NAME}
PRODUCT_NAME是运行时传入值的数据元素名称
如下是一个完整的URL地止
{SUPPLIER_URL}
SUPPLIER_URL 是运行时传入值的数据元素名称
十.表格
XML Publisher 支持通过XML数据来动态创建表格内容和题头
动态创建题头的步骤:
à使用<?tagname?>标记的方式来插入题头,并将其格式化为题头。这里不能使用表单
域的功能。
例如报表要求将公司名称显示为题头,XML数据标记名为<COMPANY_NAME>,在
报表模板中需要显示标题的地方输入<?COMPANY_NAME?>即可
à通过word的内置功能创建表格的其他内容
在运行的时候,系统自动替换表格中和题头标记的值
十一. 复选框
可以在模板中定义复选框,并根据传入的值来决定是否被选中
定义复选框的步骤:
使用word中的复选框型窗体域功能添加复选框
打开复选框型窗体域选项窗口
设置默认值:未选中或选中
在窗体域帮助文字中输入复选框选中的条件表达式,它必须是一个布尔表达式,只能返回true或false
如:XML数据中包括了<population>的元素,如果<population>的值大于10000
则复选框被选中,则在窗体域帮助文字中输入如下的条件表达式:
<?population>10000?>
十二.IF语句
<?if:condition?>
……
<?end if?>
例子
<?if:VENDOR_NAME=’COMPANYA’?>
……
<?end if?>
样板文本中使用IF语句
<?if@inlines:condition?>
……
<?end if?>
例子
1.The program was<?if:SUCCESS=’N’?>not<?end if?> successful
结果The program was
not
successful
2.The program was<?if@inlines:SUCCESS=’N’?>not<?end if?> successful
结果: The program wassuccessful.
十三.If-then-Else 语句
<?xdofx:if element_condition then result1 elseresult2 end if?>
例子:
<?xdofx:if AMOUNT > 1000 then 'Higher‘
Else
if AMOUNT < 1000 then 'Lower‘
Else
'Equal‘
end if?>
十四. Choose 语句
<?choose:?>
<?when:expression?>
……
<?when:expression?>
……
<?otherwise?>
十五. 格式化列
根据条件显示或隐藏列
<?if@column:condition?>
……
<?end if?>
例子:
<?if@column:condition?>
<?quantity?>
<?end if?>
<?if@column: /items/@type="PRIVATE"?>
<?quantity?>
<?end if?>
十六. 格式化行
当条件满足的时候加亮行
设置行的背景颜色
满足条件的时候才显示行
根据条件来格式化表格的行
<?if:condition?> <?end if?>
<?if@row:condition?>
<xsl:attributename="background-color"
xdofo:ctx="incontext">lightgray
</xsl:attribute>
<?end if?>
十七. 单元格加亮(字体加亮)
可以根据条件来加亮单元格
<?if:condition>
<xsl:attribute xdofo:ctx="block"name="background-color">
red
</xsl:attribute>
<?end if?>
例子:
<?if:debit>1000?>
<xsl:attribute xdofo:ctx="block"name="background-color">
red
</xsl:attribute>
<?end if?>
举例
Settingfont to bold if invoice amount isgreater than $1,000.
<?if:ACCTD_AMT>1000?><xsl:attributexdofo:ctx="block" name="font-weight">bold</xsl:attribute><?endif?>
Invoice Number |
Invoice Amount |
Grp: Invoice13222-2 |
Settingbackground color to greenif invoice amount is greater than $1,000.
<?if:ACCTD_AMT>1000?><xsl:attributexdofo:ctx="block" name="background-color">green</xsl:attribute><?endif?>
Invoice Number |
Invoice Amount |
Grp: Invoice13222-2 |
CH$100.00EFE |
十八. 计算合计值
1. 首先尽量用report生成总计,就不用写总计,直接加个总计域就行
2. 如果report生成的数据没有总计,那么可以使用固有函数实现
We have two choices when it comes tothe totals:
- In this case, the XML data contains the values at supplier level so we can just use a new field containing, <?ENT_SUM_VENDOR?> and <?ACCTD_SUM_VENDOR?> respectively.
- Alternatively we can use a native XSL SUM function to calculate the summary
<?sum(…..)?>例如<?sum(ENT_AMT)?> and<?sum(ACCTD_AMT)?>
This worksvery well but you should note that you are now performing calculations in themiddle tier which is not as performant as in the database. You should performas much of your business processing in the database as possible.
You also notice that we can give somecontext to the total by adding another form field to contain the supplier name,<?VENDOR_NAME?>, as we are in the invoices level we can simply referencethe parent vendor name value for the supplier.
可以对多个字段进行合计,由于页合计在XML数据中是不存在的,所以需要定义一个变量,定义变量的同时将计算的字段关联起来了
<?add-page-total:TotalFieldName;’element’?>
TotalFieldName:合计值对应的字段
’element’:被合计的XML元素名称
<?add-page-total:dt;’debit’?>
<?add-page-total:ct;’credit’?>
<?add-page-total:net;’debit - credit’?>
十九. 显示页合计
<?show-page-total:TotalFieldName;’number-format’?>
TotalFieldName:合计值对应的字段
number-format:合计值显示的格式
例子:
<?show-page-total:dt;$#,##0.00; ($#,##0.00)’?>
<?show-page-total:ct;$#,##0.00; ($#,##0.00)’?>
<?show-page-total:net;$#,##0.00; ($#,##0.00)’?>
<?show-page-total:pt;'#,##0.00'?>
二十.结转合计
某些报表要求将页的合计显示在页尾和下一页的页头,这种合计叫做结转合计。下面是结
转合计的例子:
在第一页的尾部显示了页的合计;在第二页的顶部结转显示了第一页的合计,依次类推
需要在页码的顶部实现结转合计,只要在每页的(除了第一页)顶部使用如下的语句:
<xdofo:inline-total displaycondition="exceptfirst" name="InvAmt">
Brought Forward:
<xdofo:show-brought-forwardname="InvAmt"
format="99G999G999D00"/>
</xdofo:inline-total>
举例:
<?template:header?>
Invoice Listing Report |
|
1000 |
1000 |
<?end template ?>
<?template:footer?>
Page Total: |
1000 |
1000 |
|
|
1000 |
1000 |
<?endtemplate?>
Init PTs
Invoice Type |
Invoice Number |
Invoice Date |
Invoice Currency |
Entered Amount |
Accounted Amount |
FEINV_TYPE |
132342 |
10-May-07 |
USD |
1,000.00 |
1,000.00 EG |
End PTs
二十一. 连续合计(同参数高级应用)
报表实现如下的累积合计值
1. 定义变量
<?xdoxslt:set_variable($_XDOCTX, ’VariableName’, 0)?>
<?xdoxslt:set_variable($_XDOCTX, ’RTotalVar’,0)?>
2. 添加每行值
<?xdoxslt:set_variable($_XDOCTX, ’Var’,xdoxslt:get_variable($_XDOCTX,’Var’) +tag name)?>
<?xdoxslt:set_variable($_XDOCTX, ’RTotalVar’,xdoxslt:get_variable($_XDOCTX,’RTotalVar’) + INVAMT)?>
3. 显示累积合计值
xdoxslt:get_variable($_XDOCTX, ’VariableName’)?>
xdoxslt:get_variable($_XDOCTX, ’RTotalVar’)?>
二十二. 排序
可以使用组中的字段对组进行排序,在组标记内插入如下的命令标记:
<?sort:element name?>
<?sort: VENDOR_NAME?>
也可以对组中的多个字段进行排序:
<?sort:element name?><?sort:elementname?>……
<?sort:VENDOR_NAME?> <?sort:INVOICE_NUM?>
二十三. 对XML数据从新分组
Youmay need to further group your data in addition to the existing grouping, inthis case we have:
SUPPLIERS
INVOICES
Ratherthan update the XML extraction, we can actually introduce a new group to thehierarchy in the template layer so we have:
SUPPLIERS
CURRENCY
INVOICES
Wecan use a new function, ‘for-each-group’ to effectively regroup the data in thetemplate to show the invoices by currency code, we can then show summary totalsat the current level too. In the template below you notice that it has beenrestructured from the previous version. There is now a new table:
TheReGrp:Curr field has the following:
for-each-group:G_INVOICE_NUM;INVOICE_CURRENCY_CODE
Thisis specifying that we want to create a new group ‘INVOICE_CURRENCY_CODE’ based onthe original ‘G_INVOICE_NUM’ group.We then have the currency label/value pair, the invoice table then follows,inside the Grp:Invoice field we now have ‘for-each:current-group()’ torefer to the new INVOICE_CURRENCY_CODE group we have just created. Note: wecannot refer to the group as INVOICE_CURRENCY_CODE as this group is onlycreated at runtime.
Sonow we have a new grouping we can create summary totals at this level togenerate totals per currency, inside the new fields we havesum (current-group()/ENT_AMT) for the enteredamount, again we use the current-group() tag to refer to the new ‘INVOICE_CURRENCY_CODE’ group.
I
Supplier |
Supplier 1 |
Address |
ReGrp:Curr Currency: USD
End Curr |
结果:多加了个分组Currency
XML Publisher提供了对XML数据从新分组的功能,这样报表可以根据需要随意进行层次结构的从新组织,无需按照原有的结构显示
<?for-each-group:BASE-GROUP;GROUPING-ELEMENT?> <?end for-each-group?>
为了在已定义的分组中再进行分组,使用如下的命令标记实现嵌套分组:
<?for-each:current-group();GROUPING-ELEMENT?>
在运行时,XML Publisher根据新的分组规则,循环显示模板中定义的字段值,
使用如下的命令标记显示显示的信息:
<?for-each:currentgroup()?> <?endfor-each?>
使用上述的语法方式,可以通过表达式来进行分组:
<?for-each:BASE-GROUP; GROUPING-EXPRESSION?>
<?for-each-group:temp;floor(degree div 10?>
二十四. 使用变量
变量使用“set get”的方式来分配、更新和取得变量的值
<?xdoxslt:set_variable($_XDOCTX,’variablename’, value)?>
<?xdoxslt:get_variable($_XDOCTX, ’variablename’)?>
<?xdoxslt:set_variable($_XDOCTX, ’x’,xdoxslt:get_variable($_XDOCTX, ’x’ + 1)?>
举例
This template contains a variable called 'x'
Let’s initialize X to 1
<?xdoxslt:set_variable($_XDOCTX,'x', 1)?> <?xdoxslt:get_variable($_XDOCTX, 'x')?>
X= ?
Lets add 10 to X
<?xdoxslt:set_variable($_XDOCTX,'x',xdoxslt:get_variable($_XDOCTX,'x')+10)?><?xdoxslt:get_variable($_XDOCTX, 'x')?>
高级应用Running Total
RTotVar<?xdoxslt:set_variable($_XDOCTX, 'RTotVar', 0)?>
Invoice Number |
Invoice Amount |
Running Total |
Grp: Invoice13222-2 |
$100.00 |
<?xdoxslt:set_variable($_XDOCTX,'RTotVar', xdoxslt:get_variable($_XDOCTX, 'RTotVar') +ACCTD_AMT)?><?xdoxslt:get_variable($_XDOCTX, 'RTotVar')?>
结果(思考这里为什么可以不用for-each)
二十五.参数
1. 定义参数
可以传递运行时参数给模板,但是Oracle Application并发管理器不支持传参数给模板,只能在程序中通过API传递参数
<xsl:paramname="PARAMETERNAME" select="DEFAULT"xdofo:ctx="begin"/>
PARAMETERNAME:参数的名称
DEFAULT:参数的默认值,select可以省略
xdofo:ctx=“begin“是必须的,它代表了在模板开始的时候就声明变量
这个语法必须在窗体域帮助文字中使用,窗体域可以放到模板中的任意位置
2. 应用参数
模板中使用参数的方法是在参数名称前添加$字符,
如:声明了参数“InvThresh”,则通过”$InvThresh”来引用它
也可以在API中通过程序来引用参数值
Properties prop = newProperties();
prop.put("xslt.InvThresh","1000");
举例
Name: xslt. InvThresh
Value: 1000
Template Builder
In the config file, under<<TEMPLATE_BUILDER_HOME>>/config, under the Properties section,enter the following:
<propertyname="xslt.InvThresh">1000</property>
InvThresh Declaration
Invoice Number |
Invoice Amount |
二十六.数字日期
1. 数字格式化
XML Publisher支持两种数字格式化方式
Word本身的数字格式掩码
Oracle的format-number功能
<?format-number:fieldname;’999G999D99’?>
2. 日期格式化
XML Publisher支持三种日期格式化方式
Word本身的日期格式掩码
Oracle的format-date功能
<?format-date:date_string; ’FORMAT_MASK’;?>
<?format-date:hiredate;’YYYY-MM-DD’?>
二十七. 抽象日期格式化
Oracle的抽象日期格式掩码语法
<?format-date:fieldname;’MASK’?>
<?format-date:hiredate;’SHORT’?>
<?format-date:hiredate;’LONG_TIME_TZ’?>
二十八. 成批打印报表
很多需求需要成批打印报表到一个PDF文档,如发票或者采购订单。由于单据是针对不同的客户或者供应商,每个文档都需要进行必要的页码重置和文档页码合计等。如果页头和页眉的数据从XML数据得到(如客户名称)也需要重置
XMLP通过使用上下文命令来支持这个需求,它允许指定段对应的元素,当断发生变化的时候,相关的文档内容也会被重置,使用如下的标记命令:
<?for-each@section:group name?>
Group name 是需要开始一个新的段对应元素的名称,使用如下的数据说明如何在一个PDF文档输出中重置页眉和页脚。
以上的数据中,每个G_INVLOICE包括了一个发票信息,为了让XMLP实现一个发票作为一段的功能,只要在for-each标记中添加如下的命令
<?for-each@section:G_INVLOICE?>
Group name 是需要开始一个新的段对应元素的名称
上面是针对上一页数据设计的一个模版,打印报表的时候,只要遇到一个G_INVOICE就
会产生一个新的段。页码就会被重置,从数据过来的页眉和页脚信息也被更新。注意
<?TRX_NUMBER?>标记,它是属于G_INVOICE组下的,只要一个新的段产生,它将会
显示新的值
二十九. 交叉表
交叉表的报表在设计时是无法知道列的数目,也不知道列的题头是,这些都是需要根据数据来决定的。
<?for-each@section:group name?>
三十. 动态数据列
使用动态数据列功能可以实现根据某种条件来动态的显示报表的列数
<?for-each@section:group name?>
三十一.重复标题行实现(重复表头)
Repeatable RowHeaders
If your invoices break across a pageand you want to repeat the column header row, this can be achieved usingMSWord’s functionality.
- Highlight the header row高亮直接用word设置
- Table > Table Properties
- Under the Row tab select the ‘Repeat as Header row at the top of each page’
If the invoices table breaks across apage the header row will be repeated.
Splitting Rows acrosspages
You can prevent rows splitting acrossa page break by using MSWord’s functionality:
- Highlight the data row
- Table > Table Properties
- Under the Row tab deselect the ‘Allow row to break across pages’
Rows that would normally be splitacross two pages are now moved to the second page to preserve the row data.
I
在word中设置
举例
IFUse thefor-each@section to repeat the header information across pages of the outputdocument. In this case, the Customer Name will be repeated if the lineinformation runs across more than one page, the page numbering will also bereset.EI
for-each@section G_CUSTOMER
ADDRESS_LINE1
ADDRESS_LINE2
CITY, STATE ZIP
DearSir or Madam:
for-each G_CURRENCY
Your TRX_CURRENCY_CODE defers from the following invoices:
Transaction Number |
Transaction Date |
Transaction Amount |
Transaction Amount Remaining |
01-Jan-2007 |
$ 100.00 |
end for-each
end for-each
三十二. 页眉页脚logo,时间等
- There is one caveat to this, you cannot use form fields in the header so you’ll need to use the full placeholder text if you want to use data in the header.
- It is good practice to use tables in the header and footer area to organize data and objects.
Youcan see in the header and footer of this report that we have several reportobjects embedded:
a) Logos: The Oracle logo is a straightforwardjpg image that has been embedded into the document. XML Publisher also supportsbmp, gif and png. We do not currently support wmf formats. Tip: Try and get alarger image than you need and shrink it in the template, this will improve thequality of the image at runtime.
b) Boilerplate – you can insert any text youwish in the header/footer and it will be repeated on each page (i.e. the reporttitle above, and the company address in the footer).
c) Data – as mentioned above you cannot use formfields in the header/footer area but this does not stop you adding data tothese areas. You just need to use the full placeholder text, this can beformatted just like the form fields and the incoming data will take on the sameproperties.
d) Page numbering – you can insert pagenumbering just as you would in a regular Word document, at runtime XMLPublisher will paginate the output and insert the correct page numbers. Thisuses the word merge fields for page number and total page number so we canbuild up text such as ‘Page X of Y’ in the template and final output.
e) Run Date – similar to the page numbering wecan also use the date merge field to insert the run date for the report. Itshould be noted that this is the publishing date and not necessarily the datethe data was generated.
注意时间和页数是会自己变化的
创建时
运行时
三十三.数字格式numberformatting
- XSL natively supports number formatting using its format-number function, it returns a formatted string and takes the form:
stringformat-number(number,format,[decimalformat])
Parameter Description
Number Required. Specifies the number to be formatted
Format Required. Specifies the format pattern. Here are some ofthe characters used in the formatting pattern:
Ø # (Denotes a digit. Example:####)
Ø 0 (Denotes leading and followingzeros. Example: 0000.00)
Ø . (The position of the decimalpoint Example: ###.##)
Ø , (The group separator forthousands. Example: ###,###.##)
Ø % (Displays the number as apercentage. Example: ##%)
Ø ; (Pattern separator. The firstpattern will be used for positive numbers and the second for negative numbers)
Decimalformat Optional.
So forexample to format the entered amount for thousands and 2 decimal places wewould use the following in the formfield:
format-number(ENT_AMT, "###,###.00") whichwould convert 1234.5 to1,234.50
If you have negativenumbers these are supported too in the format:
format-number(ENT_AMT,"###,###.00";"(###,###.00)") thesecond format denotes how the negative number should be displayed (note thesemi colon separating the formats).So -1234.5 would become (1,234,50)
To handlethousand/decimal delimiter formatting you need to do a little work on yourtemplate. XSL supports any delimiters but it needs to be told what to use. Youdo this by declaring the decimal format in your template thus:
<xsl:decimal-formatname="Euro" decimal-separator="," grouping-separator="."xdofo:ctx="begin"/>
Name – is the nameyou give you format, this can be referenced from your format-number calls
Decimal-separator –this is the character you wish to use as the decimal point
Grouping-separator –this is the character you wish to use to denote the thousand separator.
There are severalother options that can be set but these are the basic two.
Please note the useof the xdofo:ctx=”begin” – this is an advanced feature which forces the decimalformat declaration to the root of the template no matter where it is put in thephysical RTF.
So when we call theformat function this time we use:
<?format-number(ACCTD_AMT,'#.###,00', 'Euro')?>
This time 1234.5 willbecome 1.234,50 asexpected. Note the format string has changed this time.
- The other alternative is to use MSWord’s native field formatting. If you open one of the fields below you’ll notice that there is a field type drop down list that includes ‘Number’ as an option. You can select this, and then select the number format you require.
- XDO Formatting – once finalized XDO will format the numbers and dates according to runtime locale settings. Details to follow.
In this template the
Entered Amt uses <?format-number(ENT_AMT,"#,###.00")?>
Accounted Amtuses <?format-number(ACCTD_AMT,"#.###,00","Euro")?>
Supplier totals usethe MSWord formatting
三十四:BIPUBLISHER图
1, 导入数据
2, 插入BIPUBLISHER图
3, 选择分组的数据拖入框内
4, 选择类型(会根据数据提供可供选择的类型)
5, 设置相关参数就OK
三十五.加密,字体
<?PASSWORD?>
举例
This document issecured with a password - *********
This is a barcodefont: 12132435353
Thisis a MICR font: 121313&33433
Template Level Property Support
You can now embed any of the XML Publisherproperties into your RTF template <<reference to property lists>>These would then be resolved at runtime by the XML Publisher engine; you caneither use hard coded values or embed the values inside the incoming XML data.For example you might use a non standard font in your template and you wouldnormally have to use a configuration file to specify the font location atruntime for XML Publisher to use. Embedding the font property inside thetemplate you can avoid the use of the configuration file.
If you wanted to secure PDF outputgenerated from a template you can use the XML Publisher pdf security propertiesand obtain the password value from the incoming XML data.
To add an XML Publisher property to atemplate, use the Properties dialog (File -> Properties):
The XML Publisher properties need to have'xdo-' as a prefix to their regular names so 'pdf-open-password' becomes'xdo-pdf-open-password'. Just add the XML Publisher properties and their valueto the document using the dialog. If you want to reference a data element inthe XML, a password for instance then use the curly braces in enclose the pathto the XML element.
WorkedExample I – Embedding a font reference
Let’s assume you want to use a font in yourtemplate called 'XMLP Script', this is not available as a regular font on yourserver so XML Publisher requires that you tell it where the font is at runtime.If this location is known and fixed for wherever the template might bedeployed, let’s assume '/tmp/fonts' then you can set the font and its locationinto the template and XML Publisher will use it at runtime. In the propertiesdialog you would enter:
Name :xdo-font.XMLPScript.normal.normal
Type :Text
Value :truetype./tmp/fonts/XMLPScript.ttf
When the template is applied to the XMLdata on the server, XML Publisher will look for the font in the /tmp/fontsdirectory.
WorkedExample II – Securing a PDF output
Let’s assume that the XML data you areusing will contain a specific password that needs to be used to secure theoutput document. Again we can use the document properties to set the PDFsecurity password and reference a value in the XML. Assuming the following XMLdata:
<PO>
<security>true</security>
<password>welcome</password>
<PO_DETAILS>
..
<PO>
In the properties dialog we would enter twoproperties:
Name : xdo-pdf-security – this property sets whetherthe security feature is enabled or not
Type :Text
Value :{/PO/security}
Name : xdo-pdf-open-password – this property setsthe password
Type :Text
Value :{/PO/password}
Storing the password in the XML data couldbe a security problem if the XML is going to persist in the system for anylength of time. To avoid this you could achieve the same using a templateparameter value that is generated and passed into the template at runtime.Assuming your parameters were called 'PDFSec' and 'PDFPWD' you would enter thefollowing in the properties dialog:
Name : xdo-pdf-security – this property sets whetherthe security feature is enabled or not
Type :Text
Value :{$PDFSec}
Name : xdo-pdf-open-password – this property setsthe password
Type :Text
Value :{$PDFPWD}
Both of thesemethods would then secure the output PDF document with a password that wouldonly be known to the user.
三十六.动态列(Dynamic Columns)
Dynamic Data Columns
When the XML columns in thedata are dynamic (that is, the number of columns can vary) the following fourtags can be used in a template to accommodate the dynamic formatting requiredto render the data correctly.
Dynamic Column Header<?split–column–header:name?>
Usethis tag to define which group to split for the column headers of a table.
Dynamic Column<?split–column–data:name?>
Usethis tag to define which group to split for the column data of a table.
Dynamic Column Width<?split–column–name?>
Usethis tag to define the width of the column, if you have an element storing thespecific width for a column use this tag to define it.
Dynamic Column Width’s unitvalue (in points) <?split–column–width–unit:value?>
Usethis tag to define a multiplier for the column width i.e. if your column widthare defined in character cells then you will need a multiplier value ~6 torender the columns to the correct width in points. If the multiplier is notdefined, the widths of the columns are calculated as a percentage of the totalwidth of the table. See the following example:
|
Column 1 |
Column 2 |
Column 3 |
Width |
10 |
12 |
14 |
Multiplier not present - %width |
10/(10+12+14)*100 = 28% |
33% |
39% |
Multiplier = 6 – Width |
60pts |
72pts |
84pts |
Horizontal table break withrow header number<?horizontal–break–table:number?>
Ifthe width of the columns exceeds the page width and the columns need to breakacross more than one page, this tag allows you to specify how many row headingcolumns will repeat on subsequent pages with the continuing columns.
Worked Example
The following XML datadescribes test score ranges for a mathematics test; if we assume we did notknow how many ‘range’ columns there might be in the XML data. We would need a templatethat could handle any number of columns, this could vary depending on the data;in this case we have five columns, 0-20,21-40, 41-60, 61-80 and 81-100 (<TestScoreRange>) For each column there is anamount element (<NumOfStudents>) anda column width attribute (<TestScorewidth="15">). Using the tags describedabove we can construct a template to handle the dynamic data.
<?xmlversion="1.0" encoding="utf-8" ?>
<TestScoreTable>
<TestScores>
<TestCategory>Mathematics</TestCategory>
<TestScorewidth="15">
<TestScoreRange>0-20</TestScoreRange>
<NumOfStudents>30</NumOfStudents>
</TestScore>
<TestScorewidth="20">
<TestScoreRange>21-40</TestScoreRange>
<NumOfStudents>45</NumOfStudents>
</TestScore>
<TestScorewidth="15">
<TestScoreRange>41-60</TestScoreRange>
<NumOfStudents>50</NumOfStudents>
</TestScore>
<TestScorewidth="20">
<TestScoreRange>61-80</TestScoreRange>
<NumOfStudents>102</NumOfStudents>
</TestScore>
<TestScorewidth="15">
<TestScoreRange>81-100</TestScoreRange>
<NumOfStudents>22</NumOfStudents>
</TestScore>
</TestScores>
</TestScoreTable>
Thefollowing table describes the object required in the template to render thedata at runtime.
- The first column contains the row heading (<TestCategory>) i.e. ‘Mathematics’
- The second column is the one to be split dynamically, the width you specify will be divided by the number of columns of data i.e. 5.
- The second column will contain the dynamic ‘range’ data, the width of the column will be divided up according to the split column width and because there is no ‘multiplier’ present in this example the column will be split on a percentage basis. Wrapping of the data will occur if required.
- If the multiplier was present then the columns would have a specific width in ‘points’. If the total column widths were wider than the allotted space on the page then the table would break on to another page. The ‘horizontal–break–table’ tag could then be used to specify how many columns should be repeated on the subsequent page, with a value of ‘1’ the ‘TestScore’ column will be repeated then the additional columns that did not fit on the first page.
<?split-column-header:TestScore?> - split the TestScore col <?split-column-@width?> - set the width for the column <?TestScoreRange?>% - placeholder for % value heading |
TestScore |
Row Header and Splitting |
Column Header and Groups |
Content and Splitting |
<?for-each:TestScores?> - Start the TestScores group <?TestCategory?> - placeholder for category name i.e. Mathematics |
<?split-column-data:TestScore?> - split the TestScore column <?NumOfStudents?> - placeholder for # of students in this range <?end?> - end of group |
Theabove template will render the following result in the output:
TestScore |
0-20 |
21-40 |
41-60 |
61-80 |
81-100 |
Mathematics |
30 |
45 |
50 |
102 |
22 |
举例
TestScore |
Row Header and Splitting |
Column Header and Groups |
Content and Splitting |
别人总结
1.1. 布局格式化
1.1.1. 建议做法
充分利用Word的格式化功能:纸张自定义、颜色、字号、字体、标题样式、背景、水印、对齐、表格、分栏、模版日期、窗体域的数字/日期格式、文件图片、页眉页脚、自动图文集。
虽然可以代码控制,但既然依托Word作为可视化设计工具,我们就尽量使用Word功能来设计报表吧!
1.1.2. Word表格
和做网页一样,表格在报表布局中的地位至关重要,要熟练掌握,尤其是:
1、标题行重复,可以实现新页重复标题。
2、嵌套表格、行列合并、边框、底纹,可以实现特殊的布局。
3、固定列宽、自动调整、禁止跨页断行,可以实现一些严格的布局控制。
1.1.3. 行截断与禁止折行
单据打印中对格式的要求比较高,如果某一行过长或者出现多次折行,就会破坏版面,尤其是套打等要求较高的场合,这里把各种方法作个小结。
1、Word功能,不理想
固定列宽功能可以用,但固定行高不行,虽然设计时看到“固定”了,如果不加控制,运行后多出列宽的数据会自动折行。
2、单行+截断,即控制只有以行,多余截断,禁止折行
在字段后,再加两个命令:
<xsl:attribute xdofo:ctx="block"name="wrap-option">no-wrap</xsl:attribute>
<xsl:attribute xdofo:ctx="block"name="overflow">hidden</xsl:attribute>
3、多行+截断,难
如固定显示3行,多余部分截断,目前通过模版无法实现,只有在数据源中先将数据截至刚好3行的字符数,然后利用自动折行功能。这里还要注意空格,如果遇到空格,后面的单词又显示不下,将会提前自动折行。
1.1.4. 条件格式化
在不同的条件下显示不同的颜色、不同的列数、不同的标题、不同的布局风格等等,这些都属于条件格式化,需要借助IF命令。
<?if:CURRENCY_CODE="CNY"?>任何布局<?endif?>
<?if:CURRENCY_CODE!="CNY"?>任何布局<?endif?>
2、比如货币为CNY时才显示列,在目标列的单元格内写如下语句
<?if@column:CURRENCY_CODE="CNY"?>字段值和格式<?endif?>
注:这还不是真正的动态列。
3、比如偶数行底色为灰色,在行的任何单元格内写如下语句
<?if@row:position() mod 2=0?>
<xsl:attribute xdofo:ctx="incontext"name="background-color">gray</xsl:attribute>
<?end if?>
4、比如超过100单元格呈红色,在目标单元格内写如下语句
<?if:QUANTITY>100?>
<xsl:attribute xdofo:ctx="block"name="background-color">red</xsl:attribute>
<?end if?>
1.2. 字段计算技巧
1.2.1. 建议做法
1、计算字段可以在SQL中先完成。
2、如果使用Oracle Reports做数据源,那么计算字段、统计字段也可以先完成。
3、在SQL中的数据,都不带格式,格式在模版中设置;需要在模版中完成计算的字段,必须不带格式,主要指数字不能带千位符号。
1.2.2. 组内合计
N: Template Builder/插入/字段
向导可以完成基本的统计,目前支持分组内的:Sum、Count、Min、Max、Avarage。
自动生成的代码示例:<?sum (QUANTITY)?>。
1.2.3. 页内合计
要实现本页合计数,需分两步:声明合计变量、显示合计变量(可带格式)。
1、对QUANTITY进行本页合计,声明变量QTYTOTAL,注意写在QUANTITY对应的组内,不然引用不到
<?add-page-total:QTYTOTAL;’QUANTITY’?>
2、可在任意地方显示合计数
<?show-page-total:QTYTOTAL?>
那么如何实现组内+页内合计呢?
1.2.4. 结转合计
把上页的合计数显示到下页,与“页内合计”类似,需分两步:声明合计变量、显示合计变量。
用得少,可参考User Guide“Brought Forward/Carried Forward Totals”部分。
1.2.5. 累计数Running Totals
累计每行数字,实际上是这样完成的:先声明一个变量,初始化为0;累加;在需要的地方显示累计。
1、在分组标记前初始化,Set变量
<?xdoxslt:set_variable($_XDOCTX,’RTotalVar’,0)?>
2、计算累计值,通常写在欲累计的字段同一单元格内,比如下面的QUANTITY
<?xdoxslt:set_variable($_XDOCTX, ‘RTotalVar’,xdoxslt:get_variable($_XDOCTX,’RTotalVar’) + QUANTITY)?>
3、任意地方显示累计值,Get变量
<?xdoxslt:get_variable($_XDOCTX,’RTotalVar’)?>
1.3. 任何Page相关问题
1.3.1. 新组分页
分页是自然的,但如果想在某处强制分页如新组新页,那么可以使用Word的分页符(CTRL+ENTER快捷键),但会导致最后出现空白页;这样只能使用如下几种方式:
1、分组声明中加@section,如<?for-each@section:G_PO_HEADER?>。
2、<?end for-each?>前加<?split-by-page-break:?>。这个翻译后,实际上是:
<xsl:iftest="position()<last()">
<xsl:attribute name="break-before">page</xsl:attribute>
</xsl:if>
3、<?end for-each?>前加<xsl:attributename="break-after">page</xsl:attribute>,此法下RTF最后无空白页,但PDF有空白页。
4、<?end for-each?>前加<xsl:attributename="break-before">page</xsl:attribute>此法下RTF、PDF最后都有空白页。
1.3.2. 条件分页、固定行分页
1、 任意条件分页,需要借助IF + 上面的break-after或者break-before,如:
<?if:CURRENCY_CODE="CNY"?>
<xsl:attribute name="break-before">page</xsl:attribute>
<?end if?>
2、 固定行分页,需要借助IF + 上面的break-after或者break-before,在行<?end for-each?>前,如下语句控制每页5行:
<?if:position() mod 5 =0?>
<xsl:attribute name="break-before">page</xsl:attribute>
<?end if?>
1.3.3. 页眉页脚
1、标准的页眉页脚,即单个页眉页脚,使用Word的功能即可。
2、扩展的页眉页脚,可使用<?start:body?><?endbody?>把主体部分“框”起来,凡是在这两个标记之外的东西,都将被当作页眉页脚。
1.3.4. 页码和页数
1、可以用Word的“自动图文集”,在任意地方插入页码,这个是“自然页码”。
2、如果在某种情况下想让页码从特定值开始,比如新的组页码重新编号,则需要借助命令,如在for-each后写:<?initial-page-number:1?>。这里的“1”,实际上也可以用数据文件中的XML元素来替换。
1.3.5. 末页、奇偶页不同
1、Word可在页眉页脚部分实现首页不同或奇偶页不同,没法实现末页不同,即使借助代码控制,实际实现的也是末页布局不同,而非“页眉页脚”不同。
<?start@last-page:body?><?endbody?>
报表本身仅有一页时,则用<?start@last-page-first:body?><?endbody?>
例子“AdvancedLast Page”,注意布局需要独立成页,即之前需要加分页符。
2、以偶数页结束,主要目的是显示偶数页页眉页脚
<?section:force-page-count;’end-on-even-layout’?>
如果仅显示空白页,则用<?section:force-page-count;’end-on-even’?>
3、以奇数页结束,主要目的是显示奇数页页眉页脚
<?section:force-page-count;’end-on-odd-layout’?>
如果仅显示空白页,则用<?section:force-page-count;’end-on-odd’?>
1.4. 使用多媒体元素
1.4.1. Word功能
可以使用公式、绘图(如组织结构图、线条等)、艺术字、剪贴画。
如果想通过代码在有限范围内控制这些对象,比如显示文字、缩放、旋转、移动、复制,可参考User Guide中的“Drawing, Shape and Clip ArtSupport”。
1.4.2. 复选框
插入复选框窗体域,因其选中代表True,不选代表False,需要我们输入条件表达式,如:。不过运行后表现为菱形。
1.4.3. 下拉框
插入下拉框窗体域,定义下拉框的元素,并同样在“自己键入”内输入需要引用的XML标记如<%AREA_INDEX%>。这里要注意元素的顺序,因为是用顺序号和运行时的值进行匹配的,也就是XML数据中,AREA_INDEX是自然数1、2……。
1.4.4. 超链接
可以直接利用Word功能设置超链接,也可以在链接地址中,全部或部分引用XML数据文件中的标记,做到动态超链接:
{SUPPLIER_SITE_URL}或者
http://huajhua.leiko.com:8000/OA_MEDIA/{CURRENCY_CODE}.gif
1.4.5. 图片
可以直接利用Word功能插入图片,也可以仅将该图片当作占位图,在图片的“设置图片格式”的网站标签页内的“可选文字”,输入真正的图片地址:
1、来自网站的图片:url:{‘http://localhost:8000/OA_MEDIA/forms_logo.gif’}。
2、来自EBS的图片:url:{‘${OA_MEDIA}/forms_logo.gif’}。
3、动态指定地址:url:{IMAGE_URL}。
4、动态拼接的地址:url:{concat(SERVER,’/’,IMAGE_DIR,’/’,IMAGE_FILE)}。
5、直接来自内容为BLOB的XML元素,仅用于“DataTemplates”:
<fo:instream-foreign-object content-type="image/jpg">
<xsl:value-of select="IMAGE_ELEMENT"/>
</fo:instram-foreign-object>
1.4.6. 图表
可使用Template Builder向导插入图表,类型有:条形图-垂直、条形图-水平、饼图、线形图。
向导生成的代码,可在图片的“设置图片格式”网站标签页内的“可选文字”里看到,我们可以做进一步修改。
1.5. 其它常用语法
1.5.1. 字段引用
在前面的窗体域中,我们直接引用XML文件中的Tag标记,如<?QUANTITY?>。这种对XML元素的引用,是相对当前层次的组来说;如果上层组中,有个同名Tag,就要通过类似“相对路径”的方式引用,如<?../QUANTITY?>。这里的“../”个数,不是布局中的相对层测个数,而是XML数据文件中的相对层次!
转换为XSL-FO后,真正的语法分别是:
<xsl:value-of select=".//QUANTITY"xdofo:field-name="QUANTITY" />
<xsl:value-ofselect="../../QUANTITY" xdofo:field-name="../../QUANTITY"/>
1.5.2. 函数引用
1、行号,准确讲是分组中记录顺序号:<xsl:value-ofselect="position()"/>
2、总行号:<xsl:value-of select="last()"/>
更多函数请参考XSL手册。
1.5.3. 分组、排序、重新分组
1、可以通过向导完成分组、排序:
<?for-each:XML元素?><?sort:XML元素;’ascending’;data-type=‘text’?><?sort:XML元素;’ascending’;data-type=‘text’?>
……
<?endfor-each?>
2、数据重新分组,不再限制于原始XML数据文件的层次关系
数据为“Sales Report”,重新按年、月分组,理解如下实例,需要一点“想象力”:
GYEAR-GMONTH Sales
Category |
Sales (in thousand USD) |
FINDUSTRY |
999E |
EE
1.5.4. 变量、参数
1、模版变量
和普通的编程语言类似,模版中也可以使用变量,参考“累计数”部分。
2、模版参数,只能通过API调用传入,不能用于EBS并发请求
声明参数:<xsl:param name="P_NAME"xdofo:ctx="begin"/>
用$引用参数:<?if:AMOUNT>$P_NAME?>
传入参数:参考API部分。
1.5.5. 空值判断
1、有标记,值不空
<?if:Element_Name!=""?>Somethine Here<?end if?>
2、有标记,值空
<?if:Element_Name and Element_Name=""?>Somethine Here<?end if?>
3、无标记
<?if:not(Element_Name)?>Somethine Here<?end if?>
1.5.6. 数字和日期格式
可以使用Word窗体域中的格式化功能,也可以在窗体域中输入XMLP的格式化命令,这两者不能同时使用,建议使用前者;后者语法参考User Guide“Number and Date Formatting”。
1.5.7. 理解上下文
上下文代表XMLP语句的作用域,比如一个If语句,到底是针对一个单元格、一行、还是一列。在前面的介绍中,我们已经用过section、column、row,下面列出XMLP的所有上下文及其含义:
上下文 |
含义 |
等价XSL-FO |
|
|
|
section |
类似Word中节的概念,不同Section的页码将重新编号、页眉页脚也重新开始,通常用于for-each@section,使新组分页 |
|
column |
作用于表格中的整列,通常用来格式化列、动态显示列、交叉报表列 |
|
cell |
仅作用于表格中的一个单元格,通常与column配合使用,实现交叉报表 |
|
block |
作用于表格中的一个单元格或者RTF中的一个自然段 |
fo:blocks |
inline |
The context will become the single statement inside an block. This context is used for variables. |
fo:inline |
incontext |
The statement is inserted immediately after the surrounding statement. This is the default for <?sort?> statements that need to follow the surrounding for-each as the first element. |
|
inblock |
The statement becomes a single statement inside an fo:block (RTF paragraph). This is typically not useful for control statements (such as if and for-each) but is useful for statements that generate text, such as call-template. |
|
inlines |
The statement will affect multiple complete inline sections. An inline section is text that uses the same formatting, such as a group of words rendered as bold. See If Statements in Boilerplate Text, page 2-58. |
|
begin |
The statement will be placed at the beginning of the XSL stylesheet. This is required for global variables. See Defining Parameters, page 2-81. |
|
end |
The statement will be placed at the end of the XSL stylesheet. |
|
1.6. 高级布局
1.6.1. 动态列
动态列的含义是:设计时不知道有多少列,运行时XML数据文件中有确切的列数。如例子“AdvancedDynamic ColumnsTestScore”:
TestScore |
Row Header and Splitting |
Column Header and Groups |
Content and Splitting |
标题(必需):<?split-column-header:TestScore?><?TestScoreRange?>
列宽(可选):<?split-column-@width?>
数据(必需):<?split-column-data:TestScore?> <?NumOfStudents?>
1.6.2. Cross-Tab
交叉报表也叫矩阵报表、数据透视表,需要实现行列转换、数据汇总,实现机制和“动态列”完全不同,主要用重新分组的功能。我们使用“Sales Report”的数据,构建如下交叉报表,注意和普通重新分组的差异之处:
IndustryHEADER |
YEAR |
for:INDUSTRY |
sum(sales)end |
HEADER:<?horizontal-break-table:1?>
YEAR:<?for-each-group@column:ROW;YEAR?><?YEAR?><?endfor-each-group?>
for:<?for-each-group:ROW;INDUSTRY?>
INDUSTRY:<?INDUSTRY?>
sum(sales):<?for-each-group@cell:current-group();YEAR?><?sum(current-group()//SALES)?><?endfor-each-group?>
end:<?endfor-each-group?>
5.6.3之后,可以在TemplateBuilder中通过向导完成,不需要手工写代码。
1.6.3. 属性控制
对文档的控制,可以在服务器端统一配置,参见“服务器端配置”,也可以在模版级别进行控制,比如控制生成的PDF文件密码、字体路径,可以通过Word的“文件/属性”设置相关参数:
1.6.4. 嵌套模板/子模板
嵌套模板是在模板中定义一个子模板,然后在需要的地方调用它,如在页眉页脚中调用它,这样也可以突破页眉和页脚中不允许使用窗体域的限制。
1、定义子模板
子模板标记之间可以使用任何的标记和内容,和模板的主体部分没有任何区别。
<?template:internaltemplate YOUR_TEMPLATE_NAME?>
……
<?end template?>
2、调用子模板
<?call:internaltemplate YOUR_TEMPLATE_NAME?>
1.6.5. Word目录(TOC,Table of Content)
Word有自动产生目录的功能,那么在模版中如何实现呢?按照User Guide中的说明,TOC还是没法测试成功。
1.6.6. PDF标签(Bookmarks)
在TOC的基础上实现PDF标签:
1、静态TOC
<?copy-to-bookmark:?>
TOC
<?endcopy-to-bookmark:?>
1、动态TOC
<?convert-to-bookmark:?>
TOC
<?endconvert-to-bookmark:?>