欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用其他方式实现润乾报表的静默打印

程序员文章站 2022-07-12 10:03:02
...

思路分析

静默打印:在页面上点击打印按钮,不需要选择预览,也不需要选择打印机,直接向打印机发送打印任务。

润乾现有方法

润乾报表目前网页端支持三种打印方式:applet打印、flash打印、PDF打印

  1. applet打印
    支持静默打印,但是仅仅在IE流程中可以使用applet打印,局限性太大。而且浏览器的配置较复杂,且不能轻易升级jar的版本,如果升级则打印失效。
  2. flash打印
    不支持静默打印,谷歌浏览器将于2020年末停止支持flash。
  3. PDF打印
    打印效果很好,但是依然不支持静默打印。

新方案

  1. 思路借鉴:
    浏览器实现静默打印的难点在于浏览器无法获取打印机的相关配置,探索阶段了解了lodop软件,它是通过插件来实现打印,原理类似在本地安装一个windows NT服务,然后html页面将需要打印的内容发送到NT服务,再由服务去调用打印执行打印任务。

  2. 受到上面的思路启发,我在想我们是不是也可以做成这样的:用户在前台点击打印按钮,我们将需要打印的数据记录到数据库打印任务中(字段包括打印机名称、打印报表名称、打印参数等),然后再写一个【客户端】运行在服务器上,定时查询打印任务去调用打印机进行打印。这个方案适用于我们当前的项目,项目是一个仓库软件位于局域网中。

具体实现

下面展示客户端的主要代码

  1. 主要打印代码
public class RaqPrint {
    
    static final Logger logger = Logger.getLogger(RaqPrint.class);
    
    /**
     * TODO 执行单个打印任务
     * @param exepath
     * @param printTask
     * @author kaixin
     * @throws Throwable
     */
    public static void ChildPrint(String exepath, Map<String, String> printTask) throws Throwable {
        // 如果是打印模板不为空
        if (printTask.get("printtemplate") != null && !"".equals(printTask.get("printtemplate"))) {
            // 1.设置润乾报表授权
            	setRaqLicense();
            // 2.计算报表
            IReport report = CalculateIReport.getReport(exepath, printTask);
            // 3.执行打印任务;查询该机器是否配置有该打印机
            logger.info("打印机名称:" + printTask.get("printer"));
            if (PrintUtil.getPrinterNames().contains(printTask.get("printer"))) {
                ReportUtils3.print(report, false, printTask.get("printer"));
                // 返回结果
                logger.info(printTask.toString()+"打印任务下发成功");
            } else {
                logger.error("找不到打印机:" + printTask.get("printer") + "。。。。。");
            }
        }
    }
 
    /**
     * 内部的授权文件
     * @throws Exception
     */
    public static void setRaqLicense() throws Exception {
        InputStream lis = ClassLoader.getSystemResourceAsStream("reportLicense20190531.xml");
        Sequence.readLicense(Sequence.P_RPT, lis);
    }
}

注:润乾报表测试版授权可在
润乾试用产品授权下载
2. 计算报表

// An highlighted block
/**
* TODO 计算并返回报表
* 
* @author kaixin
*
*/
public class CalculateIReport {

   static IConnectionFactory connFactory = new ConnFactory(); // 构造数据源工厂类,一般为自定义类
   
   static final Logger logger = Logger.getLogger(CalculateIReport.class);

   /**
    * @title: getReport
    * @Description: 运算报表并返回报表啊
    * @param path  当前运行路径
    * @param reportParams  报表参数以及报表名称以及打印机等信息
    * @throws Exception
    * @return
    */
   public static IReport getReport(String exepath, Map<String, String> reportParams) throws Exception {
       String templateAddress = exepath + "/PrintTemplate/" + reportParams.get("printtemplate") + ".rpx";
       //创建报表
       ReportDefine rd = (ReportDefine) ReportUtils.read(templateAddress);
       System.out.println(templateAddress);
       //创建报表运行环境
       Context cxt = new Context();
       //设置数据源工厂
       cxt.setConnectionFactory("ds1", connFactory);
       
       //获取报表所需要参数名称
       ParamMetaData pmd = rd.getParamMetaData();
       
       //获取print task 任务给定的参数集合
       String paramOrMocrName[] = reportParams.get("templateparams").split(",");
       Map<String, String> paramOrMocrNameMap = new HashMap<String, String>();
       for (int i = 0; i < paramOrMocrName.length; i++) {
           String key = paramOrMocrName[i].split("=")[0];
           String value = paramOrMocrName[i].split("=")[1];
           paramOrMocrNameMap.put(key, value);
       }
       logger.info("打印任务id:" + reportParams.get("id") + "任务参数如下"
               + paramOrMocrNameMap);
       
       //给报表参数赋值
       if (pmd != null) {
           for (int i = 0, count = pmd.getParamCount(); i < count; i++) { // 讲究优化的写法
               String param = pmd.getParam(i).getParamName(); // 获取参数名
               cxt.setParamValue(param, paramOrMocrNameMap.get(param)); // 设参数值
           }
       }
       // 构造报表引擎
       Engine engine = new Engine(rd, cxt); 
       
       // 运算报表
       IReport iReport = engine.calc(); 
       return iReport;
   }
}
  1. 执行打印
// An highlighted block
import javax.swing.JFrame;

import com.raqsoft.report.control.PrintFrame;
import com.raqsoft.report.usermodel.IReport;

public class ReportUtils3 {

   public static void print(final IReport report, final boolean needSelectPrinter, String printerName)
           throws Throwable , Exception{
       final PrintFrame frame = new PrintFrame(report, (JFrame) null);
       frame.setModal(false);
       frame.setLocation(-1000, -1000);
       //判断是否需要指定打印机名称
       if (!needSelectPrinter) {
           frame.setPrinterName(printerName);
       }
       frame.show();
       frame.directPrint(needSelectPrinter);
   }
}
  1. 获取本机打印机列表
import java.util.ArrayList;
import java.util.List;

import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;

import org.apache.log4j.Logger;

public class PrintUtil {
   
   static final Logger logger = Logger.getLogger(PrintUtil.class);
   /**
    * @title: getPrinterNames
    * @Description: 获取打印机列表
    * @return List<String>
    * @author kaixin
    */
   public static List<String>  getPrinterNames() throws Exception{
        PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
        DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
        List<String> printNames = new ArrayList<String>();
        //可用的打印机列表(字符串数组)
        PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor, pras);
        
        //当前默认打印机
        for (int i = 0; i < printService.length; i++) {
            String serviceName = printService[i].getName();
            printNames.add(serviceName);
        }
        return printNames;
   }
   
}

末尾

以上是自己探索的一些拐着弯实现的静默打印,不适用大多数互联网场景,只适用于部分特定场景。
如果小伙伴有什么好的建议,欢迎评论告诉小弟。

后记

为了防止用户不慎关闭或者多开,目前在考虑有没有可能实现成网页版本,用tomcat的manager去管理

类似:在前台点击打印按钮,然后服务器后台弹出Jframe(润乾打印的PrintFrame是实现了Jframe的),然后调用服务器配置的打印机进行打印。

已经实现点击startup.bat启动的时候,可以弹出Jframe弹窗。但是通过service.bat把tomcat写成一个NT服务的时候就不能弹出弹窗了。

看到一种方法,打开服务的属性,选中【允许服务与桌面交互】,重启服务即可。不知道是否在win10下可行,有机会试一下。
使用其他方式实现润乾报表的静默打印

相关标签: 公开 学习笔记