使用Web Datawindow ActiveX实现Web页面的打印功能

    想起以前说过要把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类型。

   
   

猜你喜欢

转载自blog.csdn.net/daixf_csdn/article/details/1469730
今日推荐