java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java打印Word

Java使用Spire.Doc for Java轻松搞定Word文档打印

作者:LSTM97

在 Java 应用程序中实现 Word 文档的直接打印功能是许多企业级应用的需求,本文将详细介绍如何使用 Spire.Doc for Java实现从加载 Word 文档到指定打印机打印的完整解决方案,感兴趣的小伙伴可以了解下

在 Java 应用程序中实现 Word 文档的直接打印功能是许多企业级应用的需求。本文将详细介绍如何使用 Spire.Doc for Java 库结合 Java 标准库中的 java.awt.print 包,实现从加载 Word 文档到指定打印机打印的完整解决方案。

准备工作

首先,确保您的项目中已经引入了必要的依赖。Spire.Doc for Java是一个强大的Word文档处理库,支持文档的创建、编辑、转换和打印。您可以通过Maven或手动下载方式添加该库。同时,java.awt.print是Java标准库的一部分,无需额外安装。

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.doc</artifactId>
        <version>14.1.3</version>
    </dependency>
</dependencies>

接下来,确保你的系统可以识别要使用的打印机,可以通过打印机控制面板进行测试。

代码实现

以下是一个完整的示例代码,展示了如何使用 Java 打印一个 Word 文档:

import com.spire.doc.Document;
import javax.print.PrintService;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

public class PrintWithSpecifiedPrinter {

    public static void main(String[] args) throws PrinterException {

        // 创建一个 PrinterJob 对象,初始与默认打印机关联
        PrinterJob printerJob = PrinterJob.getPrinterJob();

        // 指定打印机名称
        PrintService myPrintService = findPrintService("\\192.168.1.104\HP LaserJet P1007");
        printerJob.setPrintService(myPrintService);

        // 创建 PageFormat 实例,并设置默认大小和方向
        PageFormat pageFormat = printerJob.defaultPage();
        
        // 返回与此 PageFormat 相关的 Paper 对象的副本
        Paper paper = pageFormat.getPaper();

        // 设置 Paper 的可打印区域
        paper.setImageableArea(0, 0, pageFormat.getWidth(), pageFormat.getHeight());
        pageFormat.setPaper(paper);

        // 创建文档对象
        Document document = new Document();

        // 从文件中加载 Word 文档
        document.loadFromFile("C:\Users\Administrator\Desktop\Input.docx");

        // 设置打印文档的格式
        printerJob.setPrintable(document, pageFormat);

        // 执行打印操作
        try {
            printerJob.print();
        } catch (PrinterException e) {
            e.printStackTrace();
        }
    }

    // 查找打印服务
    private static PrintService findPrintService(String printerName) {
        PrintService[] printServices = PrinterJob.lookupPrintServices();
        for (PrintService printService : printServices) {
            if (printService.getName().equals(printerName)) {
                return printService;
            }
        }
        return null;
    }
}

代码解释

知识补充

本文介绍如何在Java程序中通过物理打印机和虚拟打印机来打印Word文档的方法。文中使用了类库Spire.Doc for Java,可通过官网下载jar文件并导入程序或者直接通过maven仓库安装导入。

【示例1】通过物理打印机打印

import com.spire.doc.Document;
import com.spire.ms.System.Drawing.Printing.PrinterSettings;

public class PrintWord {

    public static void main(String[] args) {

        //加载Word文档
        Document document = new Document();
        document.loadFromFile("C:\\Users\\Administrator\\Desktop\\DocoumentToPrint.docx");

        //创建PrinterSettings对象
        PrinterSettings printerSettings = new PrinterSettings();

        //指定物理打印机名称
        printerSettings.setPrinterName("\\\\192.168.1.104\\HP LaserJet P1007");

        //设置打印份数
        printerSettings.setCopies((short) 1);

        //设置打印范围
        printerSettings.setFromPage(2);
        printerSettings.setToPage(4);

        //应用打印设置
        document.getPrintDocument().setPrinterSettings(printerSettings);

        //执行打印
        document.getPrintDocument().print();
    }
}

【示例2】通过虚拟打印机打印

import com.spire.doc.Document;
import com.spire.ms.System.Drawing.Printing.PrinterSettings;

public class PrintWord {

    public static void main(String[] args) {

        //加载Word文档
        Document document = new Document();
        document.loadFromFile("C:\\Users\\Administrator\\Desktop\\DocumentToPrint.docx");

        //创建PrinterSettings对象
        PrinterSettings printerSettings = new PrinterSettings();

        //指定虚拟打印机
        printerSettings.setPrinterName("Microsoft Print to PDF");

        //打印到文档
        printerSettings.setPrintToFile(true);

        //指定打印文档的保存路径和名称
        printerSettings.setPrintFileName("output/PrintToPDF.pdf");

        //应用打印设置
        document.getPrintDocument().setPrinterSettings(printerSettings);

        //执行打印
        document.getPrintDocument().print();
    }
}

java操作word并通过打印机打印

1.本文使用工具类为Jacob 来操作word文档,  优点是功能强大, 直接操作word, 方便控制样式,缺点是配置复杂,只能用在windows平台,需要电脑上有wps或office

2.首先下载Jacob压缩包,将其中的 jacob-1.17-M2-x64.dll 文件放在 %JAVA_HOME%/jre/bin目录下 ,win7放在System32 目录下。(如果win7是32位系统,则放在 System64目录下,有点诡异)

3.在项目的resource目录下新建lib文件夹,将Jacob.jar 放在lib目录下

4.引入pom依赖

<dependency>
    <groupId>com.jacob</groupId>
    <artifactId>jacob</artifactId>
    <version>1.17</version>
    <scope>system</scope>
    <systemPath>${basedir}/src/main/resources/lib/jacob.jar</systemPath>
</dependency>

5.打开要操作的word,其中要填充的数据位使用占位符填充,格式为 {{变量名}},此处变量名需要与java中相应的变量名一致

6.在数据库中取出想要的数据,创建一个相对应的map

/**
     * 生成收据
     */
    @GetMapping("/contract")
    public AjaxResult Contract() {
        String fileName = DateUtils.timechuo() + ".docx";  //根据模板生成的文件名
 
        String templateFilePath = null;  
        String printerName = null;  //打印机的名字,也可以不指定
 
 
        //从数据库中查询订单信息
        /通过你自己的service在数据库中查询想要的数据
        
        for (Object o : jsonArray) {  //如果是多条数据  使用循环遍历  根据业务进行修改
            JSONObject ob = (JSONObject) o;
 
            String houseid = ob.getString("houseid");  
            String amount = ob.getString("shouldamount");
            String outtradeno = ob.getString("outtradeno");
           
 
            String houseNo = getHouseNo(houseid);
 
            //创建一个map 将数据库中的数据写进去
            Map<String,String> map = new HashMap<>();
            //map的键必须与word中的占位符一致, 如word中{{houseid}}则map键名为 "houseid"
            map.put("houseid",houseid);  
            map.put("Amount",amountUp);
            map.put("outtradeno",outtradeno);
 
 
            String path1 =  "D:/模板.docx";  //模板word路径
            String outFilePath = "D:/" + fileName;  //生成的word文件输出路径
            templateFilePath = path1;  //模板word路径
 
 
            //调用接口生成收据
            try {
                  //可以指定打印机
//                insertAndOutFile2(templateFilePath,outFilePath,map,printerName);
                //不指定打印机会选择默认打印机)
                insertAndOutFile2(templateFilePath,outFilePath,map);
                //修改打印状态
                ob.put("status",1);
                //这里调用你自己的service修改状态就可以了
                
            }catch (Exception e){
                System.out.println(e.getMessage());
            }
        }
 
 
        return AjaxResult.success();
 
    }
 
    /**
     * 生成一个新的收据
     * @param templateFilePath word模板文件路径
     * @param outFilePath 填充后输出文件路径
     * @param map  key:word中的占位标签,value对应标签要替换的值。
     * @throws IOException
     */
    public void insertAndOutFile2(String templateFilePath, String outFilePath, Map<String,String> map, String printerName) throws Exception {
//        Map<String,Object> data = new HashMap<String, Object>();
//        data.put("title", "Poi-tl 模板引擎");//添加数据,键是 模板中的{{title}},值在渲染的时候会替换掉对应的标签
 
        XWPFTemplate template = XWPFTemplate.compile(templateFilePath).render(map); //编译模板,把数据塞入模板中,找到对应标签替换
        FileOutputStream out = new FileOutputStream(outFilePath);//新建导出文件
        template.write(out); //输出到流
        out.flush();
        out.close();
        template.close();
        PrintWordUtiil.printWord(outFilePath,printerName);
 
    }
 
    //重载 不需要传打印机名字的方法
    public void insertAndOutFile2(String templateFilePath, String outFilePath, Map<String,String> map) throws Exception {
//        Map<String,Object> data = new HashMap<String, Object>();
//        data.put("title", "Poi-tl 模板引擎");//添加数据,键是 模板中的{{title}},值在渲染的时候会替换掉对应的标签
 
        XWPFTemplate template = XWPFTemplate.compile(templateFilePath).render(map); //编译模板,把数据塞入模板中,找到对应标签替换
        FileOutputStream out = new FileOutputStream(outFilePath);//新建导出文件
        template.write(out); //输出到流
        out.flush();
        out.close();
        template.close();
        PrintWordUtiil.printWord(outFilePath);
 
    }
 
    //下边两个方法是生成文件夹和命名的  可用可不用
 
        /**
         * 以当前日期为名,创建新文件夹
         *
         * @return
         */
        private static String createNewDir() {
            SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
            return fmt.format(new Date());
        }
 
    /**
     * 为文件重新命名,命名规则为当前系统时间毫秒数
     *
     * @return string
     */
    private static String getFileNameNew() {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        return fmt.format(new Date());
    }
 

7.打印工具类,核心,需要打印的文件只需要调用 PrintWordUtil.printWord()方法,传入相应参数就可以了

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
 
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.standard.Sides;
import java.awt.print.*;
import java.io.File;
import java.io.IOException;
 
public class PrintWordUtiil {
 
    //这个方法是需要传打印机名字的(即指定打印机) 下边有个重载的方法不需要传打印机名字
    public static void printWord(String filePath,String printerName) throws PrinterException {
 
//        初始化线程
 
        ComThread.InitSTA();
        ActiveXComponent word = new ActiveXComponent("Word.Application");
        //设置打印机名称
        if (printerName == null && printerName == ""){
            //如果打印机的名字为空,则默认机器首个打印机
            //  创建一个PrinterJob对象
            PrinterJob printerJob  =  PrinterJob.getPrinterJob();
 
            //  设置打印机
            PrintService printService  =  PrintServiceLookup.lookupDefaultPrintService();
            printerJob.setPrintService(printService);
            printerName = printService.getName();
            System.out.println("发现的打印机名名称为:"+printerName);
        }
 
        word.setProperty("ActivePrinter", new Variant(printerName));
 
        // 这里Visible是控制文档打开后是可见还是不可见,若是静默打印,那么第三个参数就设为false就好了
        Dispatch.put(word, "Visible", new Variant(false));
        // 获取文档属性
        Dispatch document = word.getProperty("Documents").toDispatch();
        // 打开激活文挡
        Dispatch doc=Dispatch.call(document, "Open", filePath).toDispatch();
        //Dispatch doc = Dispatch.invoke(document, "Open", Dispatch.Method,
        //  new Object[] { filePath }, new int[1]).toDispatch();
        try{
            Dispatch.callN(doc, "PrintOut");
            System.out.println("打印成功!");
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("打印失败");
        }finally {
            try {
                if (doc != null) {
                    Dispatch.call(doc, "Close", new Variant(0));//word文档关闭
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
            //退出
            word.invoke("Quit", new Variant[0]);
 
            //释放资源
            ComThread.Release();
            ComThread.quitMainSTA();
        }
    }
 
 
    public static void printWord(String filePath) throws PrinterException {
 
//        初始化线程
 
        ComThread.InitSTA();
        ActiveXComponent word = new ActiveXComponent("Word.Application");
        //设置打印机名称
 
        PrinterJob printerJob  =  PrinterJob.getPrinterJob();
 
        //  设置打印机
        PrintService printService  =  PrintServiceLookup.lookupDefaultPrintService();
        printerJob.setPrintService(printService);
        String printerName = printService.getName();
        System.out.println("发现的打印机名名称为:"+printerName);
        printWord(filePath,printerName);
 
    }
}

结论

通过以上步骤,你可以轻松地在 Java 应用程序中集成打印功能。利用 Spire.Doc for Javajava.awt.print 库,你可以实现对 Word 文档的自动打印,提升用户体验和工作效率。在开发过程中,务必确保打印机连接正常,以及文件路径的正确性,以避免运行时错误。

您可能感兴趣的文章:
阅读全文