zoukankan      html  css  js  c++  java
  • 执法文书打印的实现(一)

        最近公司做质检的执法项目,牵涉到执法文书的打印。这个功能实现的时候走了不少弯路,简单记录下,以备后用。

        甲方的要求比较苛刻:1、打印功能不依赖于客户pc机上的word程序 2、打印功能不依赖于特定的浏览器插件 3、不依赖于其他商业程序。 这样,我只能通过调用IE内置的IEWebBrowser控件进行打印。大部分文书可以调整显示样式,来达到标准文书的要求,而一些比较特殊的文书如《现场检查笔录》,由于嵌套富文本,前台很难实现标准文书的打印效果。这类特殊文书的打印,我的思路是服务器生成打印图片,前台调用打印组件打印。

        打印图片的生成主要分为3步:1、根据word模板填充数据,生成新的word文件 2、word转pdf 3、pdf转图片

        生成word主要有两种方法:1、poi生成word(本例中使用的方法) 2、使用freemarker生成word

    照例先copy下poi项目介绍:POI项目的使命是创建和维护Java api操纵各种文件格式 基于Office Open XML标准(OOXML)和微软的OLE 2复合文档格式(OLE2)。 简而言之,您可以使用Java读写MS Excel文件。其中,HWPF提供对word97的支持,XWPF提供对word2007(ooxml国际标准)的支持。

    首先,参照官方代码写了测试方法:

    文本替换测试:

    @Test
        public void testPoi() {
            try {
                //docx文件的文档对象
                XWPFDocument xwpfDocument=new XWPFDocument(POIXMLDocument.openPackage("D:/testPoi.docx"));
                //XWPFParagraph 包含在文档/表格/标题中的段落(段落中包含很多样式信息)
                //需求:替换段落中的文本/图片等,不涉及新加段落
                //遍历文档的段落对象(不包括页眉页脚)
                for (XWPFParagraph xwpfParagraph : xwpfDocument.getParagraphs()) {
                    //XWPFRun对象定义了文本区域的一组公共的属性
                    for (XWPFRun xwpfRun : xwpfParagraph.getRuns()) {
                        //文本替换
                        if("${营业执照}".equalsIgnoreCase(xwpfRun.getText(xwpfRun.getTextPosition()))){
                            //{1}
                            xwpfRun.setColor("FF0000");//设置文本颜色
                            xwpfRun.setText("我的营业执照",0);//文本替换
                            //xwpfRun.setText("我的营业执照1",-1); //在当前文本后追加文本
                            //xwpfRun.setText("我的营业执照12",2); //在当前文本后追加文本
                            //xwpfRun.setText("我的营业执照11",1); //在“我的营业执照1”后追加文本
                        }
                        //图片替换添加
                        if("${二维码}".equalsIgnoreCase(xwpfRun.getText(xwpfRun.getTextPosition()))){
                            //{2}
                            xwpfRun.setText("",0);//文本替换
                            //在文档中插入图片失败
                            //xwpfParagraph.createRun().addPicture(new FileInputStream(new File("D:/二维码.PNG")), Document.PICTURE_TYPE_PNG, "二维码", Units.toEMU(200), Units.toEMU(200));
                            //xwpfRun.addPicture(new FileInputStream(new File("D:/二维码.PNG")), Document.PICTURE_TYPE_PNG, "二维码", Units.toEMU(200), Units.toEMU(200));
                            //create run需要结束当前循环
                            //break;
                        }
                    }
                }
                //文档create 添加图片失败
                //xwpfDocument.createParagraph().createRun().addPicture(new FileInputStream(new File("D:/二维码.PNG")), Document.PICTURE_TYPE_PNG, "二维码", Units.toEMU(200), Units.toEMU(200));
                FileOutputStream fos = new FileOutputStream(new File("D:/testPoi1.docx"));
                xwpfDocument.write(fos);
                fos.flush();
                fos.close();
            } catch (IOException e) {
                System.out.println("加载文件失败");
                e.printStackTrace();
            } catch (Exception e) {
                System.out.println("序列化图片失败");
                e.printStackTrace();
            }
        }
    文本替换

    比较坑的是word中写的标记会被ms解析成不同的run,需要自行修改:

    应为:

    Poi添加图片的方法存在bug,官方暂时还没有修复:

    执行添加图片方法后,打不开文档:

        文档插入图片bug修复并测试:

        新建类:CustomXWPFDocument继承XWPFDocument

      添加方法:createPic

      

     public void createPic(String blipId,int id, int width, int height,CTInline inline) {
             final int EMU = 9525;
             width *= EMU;
             height *= EMU;
             //String blipId = getAllPictures().get(id).getPackageRelationship().getId();
    
             //CTInline inline = createParagraph().createRun().getCTR().addNewDrawing().addNewInline();
    
             String picXml = "" +
                     "<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">" +
                     "   <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">" +
                     "      <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">" +
                     "         <pic:nvPicPr>" +
                     "            <pic:cNvPr id="" + id + "" name="Generated"/>" +
                     "            <pic:cNvPicPr/>" +
                     "         </pic:nvPicPr>" +
                     "         <pic:blipFill>" +
                     "            <a:blip r:embed="" + blipId + "" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"/>" +
                     "            <a:stretch>" +
                     "               <a:fillRect/>" +
                     "            </a:stretch>" +
                     "         </pic:blipFill>" +
                     "         <pic:spPr>" +
                     "            <a:xfrm>" +
                     "               <a:off x="0" y="0"/>" +
                     "               <a:ext cx="" + width + "" cy="" + height + ""/>" +
                     "            </a:xfrm>" +
                     "            <a:prstGeom prst="rect">" +
                     "               <a:avLst/>" +
                     "            </a:prstGeom>" +
                     "         </pic:spPr>" +
                     "      </pic:pic>" +
                     "   </a:graphicData>" +
                     "</a:graphic>";
    
             //CTGraphicalObjectData graphicData = inline.addNewGraphic().addNewGraphicData();
             XmlToken xmlToken = null;
             try
             {
                 xmlToken = XmlToken.Factory.parse(picXml);
             }
             catch(XmlException xe)
             {
                 xe.printStackTrace();
             }
             inline.set(xmlToken);
             //graphicData.set(xmlToken);
    
             inline.setDistT(0);
             inline.setDistB(0);
             inline.setDistL(0);
             inline.setDistR(0);
    
             CTPositiveSize2D extent = inline.addNewExtent();
             extent.setCx(width);
             extent.setCy(height);
    
             CTNonVisualDrawingProps docPr = inline.addNewDocPr();
             docPr.setId(id);
             docPr.setName("Picture " + id);
             docPr.setDescr("Generated");
        }
    CustomXWPFDocument
        @Test
        public void testPoi1() {
            try {
                //docx文件的文档对象
                CustomXWPFDocument xwpfDocument=new CustomXWPFDocument(POIXMLDocument.openPackage("D:/testPoi.docx"));
                //遍历页眉页脚
                for (XWPFHeaderFooter xwpfhf : xwpfDocument.getHeaderList()) {
                    //这部分可以作为方法提取出来
                    for (XWPFParagraph xwpfParagraph : xwpfhf.getParagraphs()) {
                        for (XWPFRun xwpfRun : xwpfParagraph.getRuns()) {
                            //图片替换添加  在页眉上添加图片没有实现
                            if("${二维码}".equalsIgnoreCase(xwpfRun.getText(xwpfRun.getTextPosition()))){
                                //{2}
                                //添加图片前,设置段落行角色为    自动
                                xwpfParagraph.setSpacingLineRule(LineSpacingRule.AUTO);
                                CTInline ctinline=xwpfRun.getCTR().addNewDrawing().addNewInline();
                                String id = xwpfDocument.addPictureData(new FileInputStream(new File("D:\erweima.jpg")), Document.PICTURE_TYPE_JPEG);
                                int id2=xwpfDocument.getAllPackagePictures().size()+111;
                                xwpfDocument.createPic(id,id2, 259, 259,ctinline);
                            }
                        }
                    }
                }
                //XWPFParagraph 包含在文档/表格/标题中的段落(段落中包含很多样式信息)
                //需求:替换段落中的文本/图片等,不涉及新加段落
                //遍历文档的段落对象(不包括页眉页脚)
                for (XWPFParagraph xwpfParagraph : xwpfDocument.getParagraphs()) {
                    //XWPFRun对象定义了文本区域的一组公共的属性
                    for (XWPFRun xwpfRun : xwpfParagraph.getRuns()) {
                        //文本替换
                        if("${营业执照}".equalsIgnoreCase(xwpfRun.getText(xwpfRun.getTextPosition()))){
                            //{1}
                            xwpfRun.setColor("FF0000");//设置文本颜色
                            xwpfRun.setText("我的营业执照",0);//文本替换
                            //xwpfRun.setText("我的营业执照1",-1); //在当前文本后追加文本
                            //xwpfRun.setText("我的营业执照12",2); //在当前文本后追加文本
                            //xwpfRun.setText("我的营业执照11",1); //在“我的营业执照1”后追加文本
                        }
                        //图片替换添加
                        if("${二维码}".equalsIgnoreCase(xwpfRun.getText(xwpfRun.getTextPosition()))){
                            //{2}
                            //添加图片前,设置段落行角色为    自动
                            xwpfParagraph.setSpacingLineRule(LineSpacingRule.AUTO);
                            CTInline ctinline=xwpfRun.getCTR().addNewDrawing().addNewInline();
                            String id = xwpfDocument.addPictureData(new FileInputStream(new File("D:\二维码.PNG")), Document.PICTURE_TYPE_JPEG);
                            int id2=xwpfDocument.getAllPackagePictures().size()+1;
                            xwpfDocument.createPic(id,id2, 259, 259,ctinline);
                        }
                    }
                }
                //文档create 添加图片失败
                //xwpfDocument.createParagraph().createRun().addPicture(new FileInputStream(new File("D:/二维码.PNG")), Document.PICTURE_TYPE_PNG, "二维码", Units.toEMU(200), Units.toEMU(200));
                FileOutputStream fos = new FileOutputStream(new File("D:/testPoi1.docx"));
                xwpfDocument.write(fos);
                fos.flush();
                fos.close();
            } catch (IOException e) {
                System.out.println("加载文件失败");
                e.printStackTrace();
            } catch (Exception e) {
                System.out.println("序列化图片失败");
                e.printStackTrace();
            }
        }
    添加图片测试

    图片添加经常出现如图的效果:

    这是图片空间不足引起的,在document.xml中查看是:

    <w:spacing w:line="500" w:lineRule="exact"/>

    所以设计模板时或者在代码中修改为  w:lineRule='auto'即可

    测试代码和word文件:http://yunpan.cn/cfKAtVfakJQpN (提取码:31a0)

    注:页眉页脚中添加/替换图片都没有实现,求探讨指教

    注:4/5年没写过文章了,特别生疏,勿怪

    注:做的时候出现不少错误,待添加

    另外,freemarker的实现会放在下一篇中。

  • 相关阅读:
    洛谷 P1508 Likecloud-吃、吃、吃
    Codevs 1158 尼克的任务
    2017.10.6 国庆清北 D6T2 同余方程组
    2017.10.6 国庆清北 D6T1 排序
    2017.10.3 国庆清北 D3T3 解迷游戏
    2017.10.3 国庆清北 D3T2 公交车
    2017.10.3 国庆清北 D3T1 括号序列
    2017.10.4 国庆清北 D4T1 财富
    2017.10.7 国庆清北 D7T2 第k大区间
    2017.10.7 国庆清北 D7T1 计数
  • 原文地址:https://www.cnblogs.com/chonghua/p/4148706.html
Copyright © 2011-2022 走看看