前言:公司最新需要使用到Java 打印,且项目属于C/S结构。故本文讲述的并不是Java Web打印。 说起来也比较头疼,上网查资料,发现示例都不太完善,总会有这样那样的问题。故想把自己的心得写出来供大家分享,学习!
实现打印的几种方式
- 1.使用 Java原生自带打印功能打印
- 2.使用 jacob 工具包打印
- 3.使用 PDFBox 打印
有一下几种实现方式:
实现打印对象:
打印工作:
基本都是调用print();方法进行打印。
废话不多说,上代码
**实现Printable接口:**
// 此种方式必须实现 Printable接口
private void printTextAction(String printStr)
{
printStr = area.getText().trim(); // 打印字符串
if (printStr != null && printStr.length() > 0)
{
PAGES = getPagesCount(printStr);// 分页
// 创建打印对象
PrinterJob myPrtJob = PrinterJob.getPrinterJob();
// 页面格式
PageFormat pageFormat = myPrtJob.defaultPage();
myPrtJob.setPrintable(this, pageFormat);
if (myPrtJob.printDialog()) // 显示打印对话框
{
try
{
myPrtJob.print(); // 开始打印
}
catch(PrinterException pe)
{
pe.printStackTrace();
}
}
}
else
{
JOptionPane.showConfirmDialog(null, "Sorry, Printer Job is Empty, Print Cancelled!", "Empty"
, JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);
}
}
/* 分页 */
public int getPagesCount(String curStr)
{
int page = 0;
int position, count = 0;
String str = curStr;
while(str.length() > 0) // 文本尚未计算完毕
{
position = str.indexOf('\n');
count += 1; // 统计行数
if (position != -1)
str = str.substring(position + 1); // 截取尚未计算的文本
else
str = "";
}
if (count > 0)
page = count / 54 + 1; // 以总行数除以 54 获取总页数
return page; // 返回需打印的总页数
}
Java 原生方式2
// 打印字符
private void printText2Action(String printStr)
{
if (printStr != null && printStr.length() > 0)
{
try
{
PAGES = getPagesCount(printStr);
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
PrintService printService = PrintServiceLookup.lookupDefaultPrintService(); // 静默打印
DocPrintJob job = printService.createPrintJob();
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
DocAttributeSet das = new HashDocAttributeSet();
Doc doc = new SimpleDoc(this, flavor, das);
job.print(doc, pras);
}
catch(PrintException pe)
{
pe.printStackTrace();
}
}
else
{
JOptionPane.showConfirmDialog(null, "Sorry, Printer Job is Empty, Print Cancelled!", "Empty"
, JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);
}
}
原生方式3:也是本文的一个重点
// 打印文件
private void printFileAction()
{
// 创建一个文件选择器,构造函数存放的是当前用户路径
JFileChooser fileChooser = new JFileChooser(SystemProperties.USER_DIR);
// 显示文件选择对话框
int state = fileChooser.showOpenDialog(this);
// 选择完成
if (state == fileChooser.APPROVE_OPTION)
{
// 获取选择到的文件
File file = fileChooser.getSelectedFile();
// 打印属性,可为空
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
// 设置打印格式:自动
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
// 查询所有可打印服务
PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor, pras);
// 定位默认打印服务
PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
// 显示打印对话框
PrintService service = ServiceUI.printDialog(null, 200, 200, printService
, defaultService, flavor, pras);
if (service != null)
{
try
{
// 创建打印作业
DocPrintJob job = service.createPrintJob();
FileInputStream fis = new FileInputStream(file);
DocAttributeSet das = new HashDocAttributeSet();
pras.add(Chromaticity.MONOCHROME);
// 请求横向模式
// pras.add(OrientationRequested.LANDSCAPE);
// Letter大小
pras.add(MediaSizeName.NA_LETTER);
// European A4 paper
pras.add(MediaSizeName.ISO_A4);
// 请求双面
// pras.add(Sides.DUPLEX);
Doc doc = new SimpleDoc(fis, flavor, das);
job.print(doc, pras);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
原生方式3:本来想用这种方式,结果发现其有一个非常严重的短板。就是txt,html,pdf等类型的文件,虽然其API提供了这些打印类型,但是发现,大部分打印机都不能正常打印,或者打印的内容为空白! 这可坑死老衲了,网上找原因,发现大家都反应这个问题,却没有解决。 因此笔者提供两种实现思路, 1.原生打印方式,图片,文字都是百分百能打印的。所以,可以将pdf转成图片,再进行打印。这无疑又绕了远路,但可以实现。 2. 采用其他方式实现打印。下文将继续介绍。
优点:可以打印 excel,word 等复杂文档类型
缺点:电脑必须安装office,需要将库导入到指定位置。
所需环境:
库:jacob.dll
jar包:jacob.jar
jacob环境下载
private void doPrintDoc(List fileList) {
if (null == fileList || fileList.isEmpty()) {
return;
}
// 初始化组件
ComThread.InitSTA();
for (File file : fileList) {
if (file == null || !file.exists()) {
return;
}
int index = file.getName().indexOf(".");
String extName = file.getName().toUpperCase().substring(index + 1);
String comApp = "Word.Application";
String property = "Documents";
if (extName.equals("DOC") || extName.equals("DOCX") || extName.equals("WPS")) {
comApp = "Word.Application";
property = "Documents";
} else if (extName.equals("XLS") || extName.equals("XLSX") || extName.equals("ET")) {
comApp = "Excel.Application";
property = "Workbooks";
} else if (extName.equals("PPT") || extName.equals("PPTX") || extName.equals("DPS")) {
comApp = "PowerPoint.Application";
property = "Presentations";
}
ActiveXComponent axc = new ActiveXComponent(comApp);
try {
if (!property.equals("Presentations")) {
Dispatch.put(axc, "Visible", new Variant(false));
}
Dispatch document = axc.getProperty(property).toDispatch();
Dispatch doc = null;
if (property.equals("Presentations")) {
doc = Dispatch.call(document, "Open", file.getAbsolutePath(), true, true, false).toDispatch();
} else {
doc = Dispatch.invoke(document, "Open", Dispatch.Method, new Object[] { file.getAbsolutePath() }, new int[1]).toDispatch();
}
Dispatch.call(doc, "PrintOut");
Dispatch.call(doc, "Close");
if (!property.equals("Presentations")) {
axc.invoke("Quit", new Variant[] {});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
comApp = "";
property = "";
}
}
ComThread.Release();
}
这种方式,缺点太明显,不予采纳
所需资源:pdfbox.jar/fontbox.jar 依赖包:commons-logging.jar
下载pdfbox(完整版),含源码和commons-logging.jar
private static void print() {
try {
File file = new File("C:/Users/Jason/Desktop/打印测试.pdf");
PDDocument document = PDDocument.load(file);
// 加载成打印文件
PDFPrintable printable = new PDFPrintable(document);
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(printable);
job.print();
} catch (InvalidPasswordException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (PrinterException e) {
e.printStackTrace();
}
}
这种方式简直太爽了,代码简洁,功能强大!推荐大家使用这个。不需要引用动态库 ,只需加入jar包即可!
终于完美交差! 有问题的小伙伴可以在下方评论哦。