web打印技术选型的烦恼与折衷方案

 


一、 讨论范围:

 

基于web网页、浏览器限于IE

 

二、  引子:

 

我们团队在做项目的过程中,碰到不同情况的打印需求;我这里把打印需求分成四种。

1)、复杂的报表打印,需要做套打。

2)、最简单的网页内容打印。

3)、简单设置后的网页内容打印。

4)、简单设置后(包括横向、纵向)自动设置后的网页内容打印。

之所以把34分开,是因为这两者研究的过程中两者看似小的差别,但技术实现上还是有不一样的地方,我们团队在项目过程中刚好碰到了第4种需求,进行一翻技术研究后,发觉第4种需求技术解决方案着实让人烦恼。但是再进一步在用户体验的角度来看,第4种和第3种虽说都能实现,但体验差不多一样糟糕。因此最终的折衷方案适合于第3、4种需求。

                   这里先对前两种需求的技术选型做出简单说明,然后再进一步讨论第3、4种需求及我们的折衷方案。

        

1)复杂的报表打印,需要做套打

开发ActiveX控件;或者使用开源;或者购买商用控件。我们团队使用的是自己开发的ActiveX控件。

2)最简单的网页内容打印

使用IE自带的打印,或者简单的使用js调用

Webbrowser

 

三、 展开讨论--web页面设置

 

ie浏览器->打印->页面设置界面,可以看到有以下元素可以设置:

1)纸张大小

2)纵向/横向

3)打印背景颜色和图像

4)启用缩小字体填充

5)页眉

6)页脚

7)左边距

8)右边距

9)上边距

10)下边距

11)字体大小

在设置并保存后,退出ie后,再次进入界面会发现纵向/横向和纸张大小这两个保存会丢掉,其他的都能保存住上次设置的状态。或许因为纵向/横向和纸张大小在打印设置那里还可以设置,所以这个值就没有被存入注册表。来看一下注册表

HKEY_CURRENT_USER/SOFTWARE/Microsoft/Internet Explorer/PageSetup,可以看到以下键值(中文作者加上)

font(字体大小)

footer(页脚)

header(页眉)

margin_bottom(下边距)

margin_left(左边距)

margin_right(右边距)

margin_top(下边距)

Print_Background(打印背景颜色和图像)

Shrink_To_Fit(启用缩小字体填充)

通过页面设置和注册表对比,可以很清楚看到纸张大小和纵向/横向不被存入注册表。因此就有了引子里讲到的第3和第4种需求的区别,第3种需求是指不设置纸张大小和纵向/横向设置。第4种需求则多了这两项。

 

四、如何修改页面设置注册表

 

基于第3种需求,主要是修改注册表,javascript代码如下:

 

<script type="text/javascript">
    var hkey_root,hkey_path,hkey_key  
    hkey_root="HKEY_CURRENT_USER";
    hkey_path="\\Software\\Microsoft\\Internet Explorer\\PageSetup\\";
      //这个是用来设置打印页眉页脚的,你可以设置为空或者其它
      try{  
            var RegWsh = new ActiveXObject("WScript.Shell");
             
            hkey_key="header";
            RegWsh.RegWrite(hkey_root+hkey_path+hkey_key,"");
           
            hkey_key="footer";
            RegWsh.RegWrite(hkey_root+hkey_path+hkey_key,"");
      }catch(e){
      alert(e.description);
      }
</script>
 

 

五、 如何修改页面设置纵向/横向及纸张大小

 

能否不通过第三方的activeX,直接利用javascript直接修改这两个属性呢?在网上折腾了两天后,只找到一种办法,还是使用WScript.Shell,代码例子如下

 

<script type="text/javascript">
                   try{
var RegWsh = new ActiveXObject("WScript.Shell");
RegWsh.sendKeys('%fu');//按下Alt+F+U键
RegWsh.sendKeys('%a');//按下了ALT+A键
RegWsh.sendKeys('{ENTER}');//按下Enter键
}catch(e){
      alert(e.description);
}
</script>
 

 

在执行时,可以看到有弹出页面设置的界面然后保存关闭的过程。

如果大家有其他体验更好的解决方案,希望能补充。

 

六、用户体验带来的烦恼

 

1、以上不管是哪种方案,都会提示用户安全上的确认,如果我们的ActiveX是通过官方认证的,相对来说安全级别是较高的,大部分用户是能接受的。

2、而第四、五点的实现在一般用户的安全设置情况下,会报出错误提示”automation服务器不能创建对象

客户端可以通过以下三种办法排查:

1)、如果是Scripting.FileSystemObject (FSO 文本文件读写)被关闭了, 开启FSO功能即可,在“运行”中执行regsvr32 scrrun.dll即可。

2)、安全模式设置成“中”,如果javascript脚本中报这个错误,还应将IE的安全设置“不允许运行未标记为安全的activeX控件”启用即可。注意如果您将相应的网站设成“受信任的站点”, 必须对“受信任的站点”进行相应的IE安全设置,此时如果对“InternetIE设置将是徒劳的。

3)、有些脚本需要微软的 MSXML 控件才能进入。当使用 IE 5 以上版本的缺省安全模式时,会提示是否接受 MSXML 控件, 如果接受,MSXML 将自动安装到您的机器上(得等上几分钟) 如果自动安装不成功,可以自行下载和安装 MSXML 3.0 SP7。有时是由于msxml 3服务被关掉了,使用regsvr32 msxml3.dll即可。

但是这样的体验无疑是用户无法忍受的,除非你的系统是后台内部少数人使用的场景,即便客户端的设置不弹出错误提示”automation服务器不能创建对象,但第五点的实现会看到打开页面时,自动弹出页面设置窗口并自动关闭的过程,我想这样的体验也是用户所厌恶的。

 

七、令人不爽的折衷方案

 

         讲了这么多,可能还没讲清楚我到底想要个什么样的打印需求,再次描述:我们想要一个简单的页面打印,比如某个网页上有个打印按钮,然后点击打印,能自动设置好纸张大小、纵向/横向及其他页面设置元素,并直接打印出页面上某个对象(其他不打印的对象可以通过cssjs控制不被打印出来)。

     令人遗憾的是,通过以上的阐述,通过JavascriptWScript.Shell直接实现的方式,用户体验太差。放弃!

折衷方案一、降低需求标准,通过javascript调用Webbrowser弹出打印设置,让用户自行设置纵向/横向及其他设置后再打印。体验较差,我们在项目过程中,由于时间的原因,做为临时解决方案。

折衷方案二、采用ActiveX,一般第三方的打印控件比较大,而我们的第34种需求方案实际上非常简单,用不到一般商用的庞大复杂的报表功能,因此可以做个简单但够用的体积又很小的ActiveX控件是最好的解决方案。ActiveX控件,免不了客户端第一次打开时下载和信任确认问题,这是ActiveX都无法避免的问题,但这种方案完全满足了用户的需求,但ActiveX开发需要的时间多,正式签名等过程复杂。我们将在下个sprint中考虑采用ActiveX

 

八、发文目的

 

         因为花了我2天多时间,本想通过javascript来实现本文中简单的自动打印设置并打印(即本文所提到的第34种需求),结果引出了这一系列技术问题及用户体验问题,如果大家有更好的解决方案,请予以分享。如果有碰到我同样需求又需要做出技术选型的朋友,希望本文能让你有所参考少走弯路。

 

--董柏 于2011.11.15中午

 

你可能感兴趣的:(打印,横向,ActiveX,WScript.Shell,ScriptX)