在日常办公自动化中,打印 Word 文档是个常见需求。无论是批量打印合同、报告,还是在后台服务中自动输出文档,都需要通过代码控制打印过程。手动打开 Word 再打印效率太低,特别是在需要处理大量文档或集成到自动化流程时。
今天分享一下如何用 Java 代码打印 Word 文档,从最简单的一行代码打印,到自定义纸张大小、边距、双面打印等高级设置。完全不需要打开 Microsoft Word,纯后台即可完成。
先说说应用场景
在实际工作中,程序化打印主要用在这些地方:
- 批量打印 - 一次性打印几十上百个文档
- 后台服务 - 在服务器端自动打印生成的报告
- 定时任务 - 按 schedule 自动打印日报/周报
- 自助打印系统 - 用户提交文档后自动排队打印
- 归档系统 - 打印后扫描存档
理解了用途,就知道什么时候该用程序化方式打印,而不是手动操作。
环境准备
Maven 依赖
如果你的项目使用 Maven,可以在 pom.xml 中添加以下配置:
xml
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
<version>14.6.0</version>
</dependency>
</dependencies>
导入常用类
在 Java 代码中,需要导入本文示例常用的类:
java
import com.spire.doc.*;
import com.spire.doc.documents.*;
import com.spire.doc.Printing.*;
import java.awt.print.*;
其中:
Document:用于加载 Word 文档;PrintDocument:Spire.Doc 提供的打印对象;PrinterJob:Java 标准打印任务对象;PageFormat和Paper:用于设置页面格式;Margins:用于设置页边距;Duplex:用于设置双面打印模式。
一、最基础的打印:一行代码搞定
先从最简单的开始------加载文档并直接打印:
typescript
import com.spire.doc.*;
public class SimplePrint {
public static void main(String[] args) {
// 创建文档对象
Document document = new Document();
// 加载 Word 文件
document.loadFromFile("data/report.docx");
// 打印文档(使用默认打印机和设置)
document.getPrintDocument().print();
// 释放资源
document.dispose();
System.out.println("文档已发送到打印机!");
}
}
就这么简单! 三行核心代码完成打印:
- 加载文档
- 获取打印对象并调用
print() - 释放资源
适用场景:
- 快速测试打印功能
- 使用默认打印机和设置
- 不需要自定义任何参数
- 内部办公环境,打印机已配置好
注意:
- 这会弹出打印对话框(取决于系统配置)
- 使用系统默认打印机
- 使用文档默认的页面设置
二、使用 PrinterJob 精确控制打印
如果需要更精细的控制(如设置份数、页边距、选择打印机等),可以使用 Java 标准的 PrinterJob API。
java
import com.spire.doc.*;
import java.awt.print.*;
public class PrintWithControl {
public static void main(String[] args) {
// 加载文档
Document document = new Document();
document.loadFromFile("data/report.docx");
// 创建打印任务
PrinterJob printerJob = PrinterJob.getPrinterJob();
// 获取默认页面格式
PageFormat pageFormat = printerJob.defaultPage();
// 获取纸张对象
Paper paper = pageFormat.getPaper();
// 设置可打印区域(移除默认边距)
paper.setImageableArea(0, 0, pageFormat.getWidth(), pageFormat.getHeight());
// 设置打印份数
printerJob.setCopies(2); // 打印 2 份
// 应用纸张设置
pageFormat.setPaper(paper);
// 设置可打印对象
printerJob.setPrintable(document, pageFormat);
try {
// 执行打印
printerJob.print();
System.out.println("打印成功!");
} catch (PrinterException e) {
System.err.println("打印失败: " + e.getMessage());
e.printStackTrace();
}
// 释放资源
document.dispose();
}
}
关键设置说明:
- 设置打印份数
scss
printerJob.setCopies(2); // 打印 2 份
- 移除默认边距
arduino
paper.setImageableArea(0, 0, width, height);
这样可以实现无边距打印,适合打印照片或特殊文档。
- 异常处理
php
try {
printerJob.print();
} catch (PrinterException e) {
// 处理打印错误
}
适用场景:
- 需要设置打印份数
- 需要自定义页边距
- 需要选择特定打印机
- 需要更精细的打印控制
优势:
- 使用 Java 标准 API,兼容性好
- 可以集成到现有的打印系统中
- 支持更多自定义选项
三、自定义纸张大小
有时候需要使用非标准纸张大小,例如自定义标签纸、特殊尺寸的报表等。Spire.Doc 允许你自定义纸张的宽度和高度。
arduino
import com.spire.doc.*;
import com.spire.doc.Printing.*;
public class CustomPaperSize {
public static void main(String[] args) {
// 加载文档
Document doc = new Document();
doc.loadFromFile("data/report.docx");
// 获取打印对象
PrintDocument printDoc = doc.getPrintDocument();
// 创建自定义纸张大小
PaperSize size = new PaperSize();
size.setWidth(900); // 宽度(单位:点,1点=1/72英寸)
size.setHeight(800); // 高度
// 应用自定义纸张大小
printDoc.getDefaultPageSettings().setPaperSize(size);
// 打印文档
printDoc.print();
// 释放资源
doc.dispose();
System.out.println("使用自定义纸张大小打印完成!");
}
}
纸张尺寸换算:
| 单位 | 换算关系 | 示例 |
|---|---|---|
| 点(Point) | 1 点 = 1/72 英寸 | A4: 595 x 842 点 |
| 英寸 | 1 英寸 = 72 点 | Letter: 612 x 792 点 |
| 厘米 | 1 厘米 ≈ 28.35 点 | 10cm ≈ 283 点 |
常见纸张尺寸(单位:点):
- A4: 595 x 842
- Letter: 612 x 792
- Legal: 612 x 1008
- A3: 842 x 1191
适用场景:
- 打印自定义标签
- 特殊尺寸的报表
- 名片、卡片打印
- 非标准纸张的文档
注意:
- 确保打印机支持自定义纸张大小
- 不同打印机的最大/最小纸张尺寸可能不同
- 建议在打印前测试实际效果
四、设置页边距和双面打印
专业的文档打印通常需要精确控制页边距,并且为了节省纸张,经常需要双面打印。
java
import com.spire.doc.*;
import com.spire.doc.documents.*;
import com.spire.doc.Printing.*;
public class SetMarginAndDuplex {
public static void main(String[] args) {
// 加载文档
Document doc = new Document();
doc.loadFromFile("data/report.docx");
// 获取打印对象
PrintDocument printDoc = doc.getPrintDocument();
// 1. 设置图形原点从页边距开始
printDoc.setOriginAtMargins(true);
// 2. 设置页边距为 0(无边距打印)
printDoc.getDefaultPageSettings().setMargins(new Margins(0, 0, 0, 0));
// 3. 设置双面打印 - 垂直翻转(长边装订)
printDoc.getPrinterSettings().setDuplex(Duplex.Vertical);
// 如果是短边装订(横向翻转),使用:
// printDoc.getPrinterSettings().setDuplex(Duplex.Horizontal);
// 打印文档
printDoc.print();
// 释放资源
doc.dispose();
System.out.println("双面打印完成!");
}
}
双面打印模式说明:
| 模式 | 说明 | 适用场景 |
|---|---|---|
Duplex.Vertical |
垂直翻转(长边装订) | 普通文档、书籍 |
Duplex.Horizontal |
水平翻转(短边装订) | 日历、便签本 |
Duplex.Simplex |
单面打印(默认) | 单页文档 |
页边距设置:
scss
// 设置四周边距(左、上、右、下),单位:点
new Margins(left, top, right, bottom)
// 示例:
new Margins(0, 0, 0, 0) // 无边距
new Margins(72, 72, 72, 72) // 各边 1 英寸
new Margins(36, 36, 36, 36) // 各边 0.5 英寸
setOriginAtMargins(true) 的作用:
true: 图形绘制原点从页边距开始(推荐)false: 图形绘制原点从物理纸张边缘开始
适用场景:
- 节省纸张的双面打印
- 专业文档的精确边距控制
- 制作小册子或手册
- 无边距照片打印
注意:
- 不是所有打印机都支持双面打印
- 双面打印前确认打印机支持该功能
- 某些打印机可能需要手动翻面
五、实战:批量打印多个文档
最后来个完整的实战例子------批量打印文件夹中的所有 Word 文档:
typescript
import com.spire.doc.*;
import java.io.File;
public class BatchPrintDocuments {
/**
* 批量打印指定文件夹中的所有 Word 文档
*
* @param folderPath 文件夹路径
* @param copies 每个文档打印的份数
*/
public static void batchPrint(String folderPath, int copies) {
File folder = new File(folderPath);
if (!folder.exists() || !folder.isDirectory()) {
System.err.println("错误:文件夹不存在 - " + folderPath);
return;
}
// 获取所有 .docx 文件
File[] docFiles = folder.listFiles((dir, name) ->
name.toLowerCase().endsWith(".docx") || name.toLowerCase().endsWith(".doc")
);
if (docFiles == null || docFiles.length == 0) {
System.out.println("未找到 Word 文档");
return;
}
System.out.println("找到 " + docFiles.length + " 个文档,开始批量打印...\n");
int successCount = 0;
int failCount = 0;
for (File docFile : docFiles) {
Document document = null;
try {
System.out.println("正在打印: " + docFile.getName());
// 加载文档
document = new Document();
document.loadFromFile(docFile.getAbsolutePath());
// 获取打印对象
PrintDocument printDoc = document.getPrintDocument();
// 设置打印份数
printDoc.getPrinterSettings().setCopies(copies);
// 执行打印
printDoc.print();
successCount++;
System.out.println("✓ " + docFile.getName() + " 打印成功\n");
} catch (Exception e) {
failCount++;
System.err.println("✗ " + docFile.getName() + " 打印失败: " + e.getMessage() + "\n");
} finally {
// 确保释放资源
if (document != null) {
document.dispose();
}
}
}
// 输出统计结果
System.out.println("========== 批量打印完成 ==========");
System.out.println("成功: " + successCount);
System.out.println("失败: " + failCount);
}
public static void main(String[] args) {
// 批量打印文件夹中的所有文档,每个打印 1 份
batchPrint("C:\Documents\ToPrint", 1);
}
}
这个例子展示了:
- ✅ 自动扫描文件夹中的所有 Word 文档
- ✅ 支持
.doc和.docx格式 - ✅ 设置打印份数
- ✅ 完整的错误处理
- ✅ 资源管理(确保
dispose()被调用) - ✅ 详细的进度反馈和统计
使用场景:
- 月底批量打印所有员工报告
- 打印一批合同文档
- 自动打印生成的发票
- 定期打印日报/周报
六、常见问题与解决方案
问题1:打印时弹出对话框
原因: 默认打印行为可能会显示打印对话框。
解决方案:
scss
// 方法1:使用 PrinterJob 静默打印
PrinterJob printerJob = PrinterJob.getPrinterJob();
printerJob.setPrintable(document, pageFormat);
printerJob.print(); // 不会弹出对话框
// 方法2:设置打印机属性
printDoc.getPrinterSettings().setPrintToFile(false);
问题2:找不到打印机
原因: 系统没有配置默认打印机,或指定的打印机不可用。
解决方案:
ini
// 检查可用打印机
PrinterJob printerJob = PrinterJob.getPrinterJob();
PrintService[] services = PrinterJob.lookupPrintServices();
if (services.length == 0) {
System.err.println("未找到可用打印机");
return;
}
// 选择特定打印机
for (PrintService service : services) {
System.out.println("可用打印机: " + service.getName());
}
问题3:打印内容偏移或裁剪
原因: 页边距设置不正确,或纸张大小不匹配。
解决方案:
scss
// 调整页边距
printDoc.getDefaultPageSettings().setMargins(new Margins(36, 36, 36, 36));
// 或者移除边距
paper.setImageableArea(0, 0, width, height);
// 确认纸张大小正确
printDoc.getDefaultPageSettings().setPaperSize(PaperSize.A4);
问题4:双面打印不生效
原因: 打印机不支持双面打印,或驱动未正确配置。
解决方案:
ini
// 检查打印机是否支持双面打印
PrintService service = printerJob.getPrintService();
boolean supportsDuplex = service.isAttributeCategorySupported(Duplex.class);
if (!supportsDuplex) {
System.out.println("打印机不支持双面打印");
// 降级为单面打印
printDoc.getPrinterSettings().setDuplex(Duplex.Simplex);
}
问题5:内存占用过高
原因: 批量打印时未及时释放资源。
解决方案:
javascript
// 始终在 finally 块中释放资源
Document document = null;
try {
document = new Document();
document.loadFromFile(filePath);
// ... 打印操作 ...
} finally {
if (document != null) {
document.dispose();
}
}
// 对于大量文档,考虑分批处理
// 每处理 10 个文档后触发垃圾回收
if (count % 10 == 0) {
System.gc();
}
七、最佳实践总结
1. 始终释放资源
javascript
Document document = new Document();
try {
document.loadFromFile("file.docx");
// ... 打印操作 ...
} finally {
document.dispose(); // 确保资源被释放
}
2. 添加异常处理
php
try {
printDoc.print();
} catch (PrinterException e) {
System.err.println("打印失败: " + e.getMessage());
// 记录日志、通知用户等
}
3. 打印前验证
go
// 检查文件是否存在
if (!new File(filePath).exists()) {
System.err.println("文件不存在: " + filePath);
return;
}
// 检查打印机是否可用
PrinterJob printerJob = PrinterJob.getPrinterJob();
if (printerJob == null) {
System.err.println("无法获取打印任务");
return;
}
4. 选择合适的打印方法
| 场景 | 推荐方法 |
|---|---|
| 简单快速打印 | document.getPrintDocument().print() |
| 需要精确控制 | 使用 PrinterJob API |
| 自定义纸张 | 使用 PrintDocument + PaperSize |
| 双面打印 | 使用 PrintDocument + Duplex |
| 批量打印 | 循环 + 资源管理 |
5. 性能优化
scss
// 批量打印时,考虑异步处理
ExecutorService executor = Executors.newFixedThreadPool(2);
for (File file : files) {
executor.submit(() -> {
printDocument(file.getAbsolutePath());
});
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);
小结
使用 Spire.Doc for Java 打印 Word 文档非常灵活,可以根据需求选择不同的打印方式:
核心要点:
- ✅ 基础打印只需一行代码:
document.getPrintDocument().print() - ✅ 使用
PrinterJob可以获得更精细的控制 - ✅ 可以自定义纸张大小、页边距、打印份数
- ✅ 支持双面打印(垂直/水平翻转)
- ✅ 批量打印时注意资源管理和异常处理
常见操作速查:
| 操作 | 代码示例 |
|---|---|
| 基础打印 | doc.getPrintDocument().print() |
| 设置份数 | printerJob.setCopies(2) |
| 自定义纸张 | printDoc.getDefaultPageSettings().setPaperSize(size) |
| 设置边距 | printDoc.getDefaultPageSettings().setMargins(new Margins(0,0,0,0)) |
| 双面打印 | printDoc.getPrinterSettings().setDuplex(Duplex.Vertical) |
| 移除边距 | paper.setImageableArea(0, 0, width, height) |
适用场景:
- 批量打印办公文档
- 后台服务自动打印
- 定时任务打印报告
- 自助打印系统
- 文档归档系统
注意事项:
- 始终调用
dispose()释放资源 - 添加适当的异常处理
- 确认打印机支持所需功能(如双面打印)
- 批量打印时注意内存管理
- 测试不同打印机的兼容性
希望这篇文章能帮你更好地理解和实现 Java 打印 Word 文档。有问题欢迎在评论区交流讨论!