想起以前说过要把Web Datawindow ActiveX使用经验整理后发出来,由于项目实在是太忙,又想偷懒一直没搞。
转眼间2006快过去了,今年的事情还是把它做了吧。
其实,使用ActiveX本身实在是没有什么难度,Datawindow大家都很熟悉。这也是我没有把它写下来的动力的原因之一。不过在实施过程中,确实 还碰到过一些问题,也有一些心得,也还有解决不了的问题存在。我就做个总结吧,今天吃的比较饱,有些絮絮叨叨,希望大家忍了,哈哈。
大家都知道,Web页面中做打印一般就两种方法:
首先是写纯Web的打印,也就是使用Web自己的打印功能,用ExecWB命令,直接打印页面。说实在的我对HTML的语法是有些怵的,也只能算小半桶 水,经过一些了解,知道直接做Web页面打印难度对我来说很大,尤其是你要实现多层次的分组合计等等功能。项目紧迫也没有这个时间。
那接下来,只能选择客户端打印控件了,我还真想去买一个好的控件用用,那多好啊,代码可以写的少些,代码执行效率,开发效率肯定也高,可惜我深知Boss的为人,这几K钱就给他省了吧。
幸好我一直对PB的Web开发方案一直保持着兴趣,本人在n年前从PB6.5开始起就研究Web.PB,Window ActiveX,Datawindow ActiveX,到PowerJ,再到后来的Web Datawindow,虽然说,有些东东看起来象是玩具,有些么闭门造车,无法流行。不过勉为其难,土法上马还是可以解决些问题的。
本来Web Datawindow还象个样子,不过Web Datawindow需要EAServer的支持。那就罢了,只有选择Web Datawindow ActiveX了。说实在的,它作为一个Web客户端打印工具还是非常好的,因为Datawindow功能是太强大了,哪怕ActiveX没有包含 Datawindow全部的功能,但是也足够打印使用了。其缺点就是界面比较难看单调,配不上那绚丽的Web页面效果。
进入正题。
首先要说明一下,我选择的是PB10版本的ActiveX控件。因为据我测试,从PB8到10都有些问题,PB8的ActiveX不支持WinXP, PB9的ActiveX竟然是已经过期了,IE上装不了(当然可能和我用盗版PB有关系,哦弥陀佛,罪过),而PB10是不支持Win98系统的。最后只 能不管Win98了,反正现在很少人用98了。
首先必须有个页面来安装控件,把如下代码添加到html页面中。别忘记了将psdwc100.cab放到相应服务器目录下,因为Cab包比较大(2M多),这个页面作为一个独立的安装页面比较好。
<OBJECT id="webdw" width="0" height="0" codeBase="/tmsweb/include/dwprint/psdwc100.cab#Version=10,0,1,3600" classid="CLSID:AAAA1503-AAAA-1000-8000-080009AC61A9" name="webdw">
安装Web DataWindow控件失败!</OBJECT>
页面写好了,发布到Web服务器,在客户端访问这个页面,安装插件即可。
接下来在打印页面w_print.jsp中引用此控件:
<OBJECT id="dw_print" height="0" width="0" classid="CLSID:AAAA1503-AAAA-1000-8000-080009AC61A9" name="dw_print">
<PARAM NAME="SourceFileName" VALUE="">
</PARAM>
<PARAM NAME="DataWindowObject" VALUE="">
</PARAM>
<PARAM NAME="SuppressEvents" VALUE="false">
</PARAM>
<PARAM NAME="VScrollBar" VALUE="true">
</PARAM>
<PARAM NAME="HScrollBar" VALUE="true">
</PARAM>
<PARAM NAME="HSplitScroll" VALUE="true">
</PARAM>
以下都是javacript脚本:
然后,设置打印用的dataobject:
dw_print.SourceFileName="/tmsweb/pdwo/trafficorder_record.pbd"
dw_print.DataWindowObject="trafficorder_record"
//我所使用的是有两个子报表的NestReport作为例子,其他报表更简单
//这里获取子报表控件
dw_print.GetChild("dw_header")
print_h=dw_print.GetChildObject()
dw_print.GetChild("dw_detail")
print_d=dw_print.GetChildObject()
//开始填入打印用的数据
//因为是ActiveX客户端控件,因此不方便直接连接数据库来取数据,所以我这里是首先通过Web的方式
//获取到打印用的数据到客户端的一个类似datawindow的对象中,然后复制给dw_print的。
print_h.reset();print_d.reset()
dw_header.rowscopy_a(1,1,print_h)
dw_detail.rowscopy_a(1,dw_detail.rowcount(),print_d)
其中,dw_header,dw_detail是页面中的htc客户端控件,rowscopy_a我想就不用解释了,后续会贴出其完整代码。
在rowscopy后,如果还需要对dw_print中的某些字段赋值,则比如调用:
setitem(print_h,1,"year_1",“2006”)
其中setitem方法是一个js函数,稍后贴出其代码。
现在,dw_print的子报表的数据都已经填充好了,可以预览打印了,
因为这里是复合报表,datawindow自动预览的,因此就不需要设置预览属性了,
如果是一般的grid类型窗口,最好是设置预览属性,这样可以看得出页面的大小,打印页数等。
设置的时候用dw_print.modify()方法,用dw_print.Object.DataWindow.Print.Preview的方式是不行的,
Activex不支持。
最后,就可以打印了。
if (confirm("是否打印?"))
{
dw_print.print(false)
}
很简单,是不是?
附录:
setitem方法:
function setitem(dw_print,row,column,value)
{
var datavalue,datatype
datatype = dw_print.Describe(column+".Coltype")
if (datatype.indexOf("char",0)>=0)
{
datavalue=value
}else if (datatype.indexOf("decimal",0)>=0 || datatype.indexOf("number",0)>=0||datatype.indexOf("long",0)>=0)
{
datavalue=parseFloat(value)
}else if (datatype.indexOf("integer",0)>=0)
{
datavalue=parseInt(value)
}else if (datatype.indexOf("date",0)>=0)
{
alert("有系统不支持的Date,Datetime类型["+column+"],请检查打印数据源")
}else
{
datavalue=value
}
dw_print.setitem(row,column,datavalue);
}
rowscopy_a方法:
function RowsCopy_A(ai_start,ai_end,aobj_dw)
{
var ll_columncount
var datatype
var datavalue
if (ai_start<=0) return -1;
if (ai_end >RowCount()) ai_end=RowCount();
ll_columncount=getColumnCount();
for (var i=ai_start;i<=ai_end;i++)
{
row=aobj_dw.insertrow(0);
for (var k=0;k<ll_columncount;k++)
{
if ((Columns[k].ColumnType!=null)&&
(Columns[k].ColumnType.Trim().toLowerCase()=="computed")&&
(typeof(Columns[k].ColumnType)!="undefined")) continue
datatype = aobj_dw.Describe(Columns[k].ColumnName+".Coltype")
if (datatype.indexOf("char",0)>=0)
{
datavalue=getItemWithID(i,k+1)
}else if (datatype.indexOf("decimal",0)>=0 || datatype.indexOf("number",0)>=0||datatype.indexOf("long",0)>=0)
{
datavalue=parseFloat(getItemWithID(i,k+1))
}else if (datatype.indexOf("integer",0)>=0)
{
datavalue=parseInt(getItemWithID(i,k+1))
}else if (datatype.indexOf("date",0)>=0)
{
alert("有系统不支持的Date,Datetime类型["+Columns[k].ColumnName+"],请检查打印数据源")
}else
{
datavalue=getItemWithID(i,k+1)
}
datavalue = getDisplayValue(row,Columns[k].ColumnName,datavalue)
aobj_dw.setitem(row,Columns[k].ColumnName,datavalue);
}
}
return 1;
}
这里要说明一下,现在维一解决不了的问题是,我在javascript中无法找到一个类型能够匹配Datawindow的datatime类型列,而如果 不转换直接赋值,是没有效果的。可能是我对javascript的研究还不够吧?如果有那位兄弟知道解决办法,请告诉我。我现在只能在pbl中把 datatime列都先用convert转换为string类型。