打印功能的实现
近期農信項目后臺系統客戶新提出需求的其中一項涉及到“打印”功能,前期技術儲備時,發現網上相關資源甚少且混雜,特別是有關web打印技術,被碼農們一致稱為“老大難”。現整理了幾項經本人驗證的可行的打印方法,包括C/S和B/S的,供碼友們參考。
?
一、C/S
1.利用Java.awt中提供的打印API,繼承Printable實現接口方法print進行打印。
參考文獻:《Java實現打印功能》-----------百度文庫。
此方法實際是C/S的打印方法,但是在某些特殊情況下,B/S的打印依然可用,例如在某些特殊的管理系統,操作此系統的用戶可以非常方便的設置發布此系統的服務器,那么將服務器所連接的打印機設置成用戶指定的打印機,此時再將代碼設置成直接打印狀態(不彈出打印提示頁面),就可以順利完成打印操作。
該方法的弊端也比較明顯,java.awt所提供API實現接口的方法print,最后是用Graphics2D直接輸出,所以有關長篇文字的格式只能手動調整(可參考官方API文檔的格式調整算法),且參數中只有一個Graphics,以至于整篇文檔的字體、顏色都是統一格式,無法調整(也許是本人對Graphics實在不了解),且無法操作頁眉頁腳(當以Word文檔格式時);優點不用說,一般的打印還是可以實現的,且Graphics能畫出來的也就都能打印出來,所以,此種打印方式所適用的和不適用的情況也就比較明顯了吧。
?
以下是關鍵代碼,詳細請見文件夾下printHelp.java文件中內容。
package com.hepow.cbrc.help;
?
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
importjava.awt.Image;
importjava.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.awt.geom.Point2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
importjava.text.AttributedString;
?
publicclassprintHelpimplementsPrintable {
/**
* @param Graphic指明打印的圖形環境
* @param PageFormat指明打印頁格式(頁面大小以點為計量單位,1點為1英才的1/72,1英寸為25.4毫米。A4紙大致為595×842點)
* @param pageIndex指明頁號
**/
??? ?? publicintprint(Graphicsgra,PageFormatpf,intpageIndex)throws PrinterException {
??? ?????? System.out.println("pageIndex="+pageIndex);
??? ?????? Component c =null;
??? ????? //print string
??? ?????? String test = "根據國家勞動管理規定以及本公司員工聘用辦法,甲方招聘乙方為試用員<br/>工,雙方在平等、自愿的基礎上,經協商一致簽訂本試用合同,共同遵守本協議所列條款"
??? ??? ???? ???+ "根據國家勞動管理規定以及本公司員工聘用辦法,甲方招聘乙方為試用員工,雙方在平等、自愿的基礎上,經協商一致簽訂本試用合同,共同遵守本協議所列條款"
??? ??? ???? ???+ "根據國家勞動管理規定以及本公司員工聘用辦法,甲方招聘乙方為試用員工,雙<br/>方在平等、自愿的基礎上,經協商一致簽訂本試用合同,共同遵守本協議所列條款"
??? ??? ???? ???+ "根據國家勞動管理規定以及本公司員工聘用辦法,甲方招聘乙方為試用員工,雙方在平等、自愿的基礎上,經協商一致簽訂本試用合同,共同遵守本協議所列條款";
??? ?????? String head ="勞動合同范本(二)——試用期勞動合同范本";
??????? ????? String str ="";
??????? ????? String str01 ="甲方:______________________";
??????? ????? String str02 ="乙方: (身份證號)______________________";
??????? ????? String str03 ="?根據國家勞動管理規定以及本公司員工聘用辦法,甲方招聘乙方為試用員工,雙方在平等、自愿的基礎上,經協商一致簽訂本試用合同,共同遵守本協議所列條款";
??????? ????? String str033 ="基礎上,經協商一致簽訂本試用合同,共同遵守本協議所列條款。";
??????? ????? String str04 ="一、試用合同期限:試用期為個月,自_____年_____月_____日至_____年_____月_____日止。";
??????? ????? String str05 ="二、根據甲方的工作安排,聘用乙方在_______________工作崗位。";
??????? ????? String str06 ="三、甲方聘用乙方的月薪為_____元(含養老、醫療、住房公積金)。試用期滿后,并經考核合格,可";
??????? ????? String str066 ="根據平等協商的原則,簽訂正式勞動合同。";
??????? ????? String str07 ="四、甲方的基本權利與義務:";
??????? ????? String str08 ="1.甲方的權利";
??????? ????? String str09 ="?有權要求乙方遵守國家法律和公司各項規章制度;";
??????? ????? String str10 ="?在試用期間,乙方如嚴重違反勞動紀律或企業規章制度,甲方有權終止合同。乙方的行為給甲方";
??????? ????? String str100 ="造成損失的,由乙方賠償,情節嚴重的追究法律責任;";
??????? ????? String str11 ="?試用期間,乙方由于個人原因所發生的疾病以及傷殘等意外事故,乙方自行負責;";
??????? ????? String str12 ="2.甲方的義務";
??????? ????? String str13 ="?為乙方提供必要的工作條件;";
??????? ????? String str14 ="?負責對乙方進行職業道德、業務技能及公司規章制度的教育和培訓;";
??????? ????? String str15 ="五、乙方的基本權利和義務。";
??????? ????? String str16 ="1.乙方的權利";
??? ????????? String str17 ="?享有國家法律法規賦予的一切公民權利;";
??? ????????? String str18 ="?享有公司規章制度規定可以享有的福利待遇的權利;";
??? ????????? String str19 ="?試用期間如變更單位,須提前一個月通知甲方,雙方協商終止試用合同;";
??? ????????? String str20 ="2.乙方的義務";
??? ????????? String str21 ="?遵守國家法律法規、當地政府規定的公民義務;";
??? ????????? String str22 ="?遵守公司的各項規章制度、員工手冊、行為規范的義務;";
??? ????????? String str23 ="?維護公司的聲譽、利益的義務。";
??? ????????? String str24 ="六、甲方的其他權利、義務";
??? ????????? String str25 ="?試用期間,乙方不能勝任工作或弄虛作假不符合錄用條件,甲方有權提前解除本合同;";
??? ????????? String str26 ="?乙方有突出表現,甲方可提前結束試用,與乙方簽訂正式勞動合同;";
??? ?????? ???String str27 ="七、乙方的其他權利、義務";
??? ????????? String str28 ="?試用期滿,有權決定是否簽訂正式勞動合同;";
??? ????????? String str29 ="?具有參與公司民主管理、提出合理化建議的權利;";
??? ????????? String str30 ="?反對和投訴對乙方試用身份不公平的歧視。";
??? ????????? String str31 ="八、本合同如有未盡事宜,雙方本著友好協商原則處理。";
??? ????????? String str32 ="九、本合同一式兩份,甲、乙雙方各執一份,具有同等效力,經甲乙雙方簽章生效。";
??? ????????? String str33 ="甲方(蓋章)?????????????????????乙方(蓋章)";
??? ????????? String str35 ="法定代表人簽字:";
??? ????????? String str36 ="簽約日期:_____年_____月_____日";
??? ????????? String str37 ="簽約地點:";
??? ????? //轉換成Graphics2D
??? ????? Graphics2D g2 = (Graphics2D) gra;
??? ????? //設置打印顏色為黑色
??? ????? g2.setColor(Color.black);
??? ?????
??? ????? /*Paper paper =pf.getPaper();//得到頁面格式的紙張
??? ????? paper.setSize(500,500);//紙張大小
??? ????? paper.setImageableArea(0,0,500,500); //設置打印區域的大小
??? ????? System.out.println(paper.getWidth());
??? ????? System.out.println(paper.getHeight());
??? ????? pf.setPaper(paper);//將該紙張作為格式 */
?
??? ????? //打印起點坐標
??? ????? doublex =pf.getImageableX();
??? ????? doubley =pf.getImageableY();
??? ??????
??? ????? switch(pageIndex){
??? ???????? case 0:
??? ?????????? //設置打印字體(字體名稱、樣式和點大小)(字體名稱可以是物理或者邏輯名稱)
??? ?????????? //Java平臺所定義的五種字體系列:Serif、SansSerif、Monospaced、Dialog和 DialogInput
??? ?????????? Font font = new Font("新宋體", Font.PLAIN, 9);
??? ?????????? g2.setFont(font);//設置字體
??? ?????????? float[]dash1 = {4.0f};
??? ?????????? g2.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,4.0f,dash1,0.0f));
??? ?????????? floatheigth =font.getSize2D();//字體高度
??? ?????????? /*g2.drawString(head, 3*(float)x, (float)y + 1*heigth);
??? ?????????? g2.drawString(str, (float)x,(float)y + 2*heigth);
??? ?????????? g2.drawString(str01, (float)x,(float)y + 3*heigth+2);
??? ?????????? g2.drawString(str02, (float)x,(float)y + 4*heigth+2);
??? ?????????? g2.drawString(str03, (float)x,(float)y + 5*heigth+2);
??? ?????????? g2.drawString(str033, (float)x,(float)y + 6*heigth+2);
??? ?????????? g2.drawString(str04, (float)x,(float)y + 7*heigth+2);
??? ?????????? g2.drawString(str05, (float)x, (float)y+ 8*heigth+2);
??? ?????????? g2.drawString(str06, (float)x,(float)y + 9*heigth+2);
??? ?????????? g2.drawString(str066, (float)x,(float)y + 10*heigth+2);
??? ?????????? g2.drawString(str07, (float)x,(float)y + 11*heigth+2);
??? ?????????? g2.drawString(str08, (float)x,(float)y + 12*heigth+2);
??? ?????????? g2.drawString(str09, (float)x,(float)y + 13*heigth+2);
??? ?????????? g2.drawString(str10, (float)x,(float)y + 14*heigth+2);
??? ?????????? g2.drawString(str100, (float)x,(float)y + 15*heigth+2);
??? ?????????? g2.drawString(str11, (float)x,(float)y + 16*heigth+2);
??? ?????????? g2.drawString(str12, (float)x,(float)y + 17*heigth+2);
??? ?????????? g2.drawString(str13, (float)x,(float)y + 18*heigth+2);
??? ?????????? g2.drawString(str14, (float)x,(float)y + 19*heigth+2);
??? ?????????? g2.drawString(str15, (float)x,(float)y + 20*heigth+2);
??? ?????????? g2.drawString(str16, (float)x,(float)y + 21*heigth+2);
??? ?????????? g2.drawString(str17, (float)x,(float)y + 22*heigth+2);
??? ?????????? g2.drawString(str18, (float)x,(float)y + 23*heigth+2);
??? ?????????? g2.drawString(str19, (float)x,(float)y + 24*heigth+2);
??? ?????????? g2.drawString(str20, (float)x,(float)y + 25*heigth+2);
??? ?????????? g2.drawString(str21, (float)x,(float)y + 26*heigth+2);
??? ?????????? g2.drawString(str22, (float)x,(float)y + 27*heigth+2);
??? ?????????? g2.drawString(str23, (float)x,(float)y + 28*heigth+2);
??? ?????????? g2.drawString(str24, (float)x,(float)y + 29*heigth+2);
??? ?????????? g2.drawString(str25, (float)x,(float)y + 30*heigth+2);
??? ?????????? g2.drawString(str26, (float)x,(float)y + 31*heigth+2);
??? ?????????? g2.drawString(str27, (float)x,(float)y + 32*heigth+2);
??? ?????????? g2.drawString(str28, (float)x,(float)y + 33*heigth+2);
??? ?????????? g2.drawString(str29, (float)x,(float)y + 34*heigth+2);
??? ?????????? g2.drawString(str30, (float)x,(float)y + 35*heigth+2);
??? ?????????? g2.drawString(str31, (float)x,(float)y + 36*heigth+2);
??? ?????????? g2.drawString(str32, (float)x,(float)y + 37*heigth+2);
??? ??? ???????g2.drawString(str33, (float)x, (float)y+ 39*heigth+2);
??? ?????????? g2.drawString(str, (float)x,(float)y + 43*heigth);
??? ?????????? g2.drawString(str35, (float)x,(float)y + 44*heigth+2);
??? ?????????? g2.drawString(str36, (float)x,(float)y + 45*heigth+2);
??? ?????????? g2.drawString(str37, (float)x,(float)y + 46*heigth+2);*/
??? ?????????
??? ?????????? FontRenderContextfrc =g2.getFontRenderContext();
??? ?????????? TextLayout layout = new TextLayout(test,font,frc);
??? ?????????? AttributedString text = new AttributedString(test);
??? ?????????? text.addAttribute(TextAttribute.FONT,font);
??? ?????????? LineBreakMeasurerlineBreaker =new LineBreakMeasurer(text.getIterator(),frc);
??? ?????????? doublewidth =pf.getImageableWidth();????????????????????????????????????????//每行字符顯示長度(點)
??? ?????????? Point2D.Double pen = new Point2D.Double (100,y+3*heigth);????????????????????//首字符的基線位于用戶空間中的 (x, y)位置處
??? ?????????? while ( (layout =lineBreaker.nextLayout((float)width)) != null){
??? ????????????? layout.draw(g2, (float)x, (float)pen.y);
??? ????????????? pen.y +=layout.getAscent();
??? ?????????? }
??? ???????? returnPAGE_EXISTS;
??? ???????? default:
??? ???????? returnNO_SUCH_PAGE;
??? ????? }
??? ?}
}
?
調用時:
//獲取打印服務對象方法1
Book book =new Book();
PageFormat pageFormat =new PageFormat();????????//設置成豎打
pageFormat.setOrientation(PageFormat.PORTRAIT);
//通過Paper設置頁面的空白邊距和可打印區域。必須與實際打印紙張大小相符。
Paper pager =new Paper();???????????????????????
pager.setSize(590,840);??????????????????????????//紙張大小
//A4(595 X 842)設置打印區域,其實0,0應該是72,72,因為A4紙的默認X,Y邊距是72
pager.setImageableArea(72,72, 590, 840);????????
pageFormat.setPaper(pager);
//把 PageFormat和 Printable添加到書中,組成一個頁面
book.append(new printHelp(),pageFormat);????????
PrinterJob job = PrinterJob.getPrinterJob();?????//獲取打印服務對象
job.setPageable(book);???????????????????????????//設置打印類
try {
//Boolean a = job.printDialog();//顯示打印提示窗口
//if(a) {
job.print();
//}
?
} catch (Exceptione) {
e.printStackTrace();
}
?
//獲取打印服務對象方法2
PrinterJob job = PrinterJob.getPrinterJob();
PageFormat pageFormat =job.defaultPage();//得到默認頁格式
job.setPrintable(new printHelp());//設置打印類
?
try {
//Boolean a = job.printDialog();//顯示打印提示窗口
//if(a) {
job.print();
//}
} catch (PrinterExceptione) {
e.printStackTrace();
}
?
以上方法的弊端催生了關于打印的另一種思路,那就是利用Java操作Word(或其他文件),然后讓Word去打印這種曲線救國思路。一開始我真的以為這是個好想法,但是后來我發現確實只是個好的“想法”而已,我可以用Java POI實現對Word內容的讀取寫入,但是我實現不了通過java讓Word自己去觸發打印動作(網上資料說java不支持這種方法<純代碼方式實現>,可作者依然堅信這種方法是有大神可以實現的)。
對于該技術研究到此時算是遇到了瓶頸,作者不免在辦公室里小發牢騷目的是尋求身邊其他碼友的幫助,此時王琦(本社iOS碼神)幫我找到了網上的一份資源,讓我不禁感慨碼界里還是神多。不再啰嗦,請看:
?
2.史上最強大java Word(文件)打印方案
參考文獻:(1)《史上最強大Java Word打印方案》------- http://blog.csdn.net/ylz2007/article/details/41172653
(2)http://stackoverflow.com/questions/2446721/how-to-get-print-out-of-a-ms-word-file-from-java-application
?
publicvoidprintWordFile(Stringfilename){
try{
Runtime.getRuntime().exec("cmd.exe /c start /min winword " +filename+" /q /n /f /mFilePrint/mFileExit");
}catch(Exceptione){
logger.info("打印異常:" +e.getMessage());}}
?
調用代碼:
printWordFile("D:\\Users\\Desktop\\tomcat部署文檔-new.docx");
?
這個的具體解釋我就不再多說了,C/S打印中終極中的終極,曲線中的曲線!
?
小結:
利用com組件進行打印功能的實現由于本人沒有親試過,所以也就不敢造次,還請路過的你親自研究。
?
二、B/S
1.最直接,最科普的打印方式:window.print()以及WB.execWB()
用window.print()可以直接打印整個頁面的內容,也可以打印指定部分的內容。這個是比較科普的方式,但是,其功能之簡陋也是比較科普的。
網頁WB.ExecWB控件打印方法:
4,1保存網頁??
4,2保存網頁(可以重新命名)??
6,1直接打印??
6,2直接打印??
7,1打印預覽? 
 
7,2 打印預覽??
8,1選擇參數??
8,2選擇參數??
10,1查看頁面屬性??
10,2查看頁面屬性??
17,1全選??
17,2全選??
22,1重新載入當前頁??
22,2重新載入當前頁
?
<OBJECT???classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2??? height=0???id=WebBrowser??? width=0></OBJECT>???
?? <input???name=Button???onClick=document.all.WebBrowser.ExecWB(1,1)??? type=button??? value=打開>??
?? <input???name=Button??? onClick=document.all.WebBrowser.ExecWB(2,1)??? type=button??? value=關閉所有>??
?? <input???name=Button???onClick=document.all.WebBrowser.ExecWB(4,1)??? type=button??? value=另存為>????
?? <input???name=Button???onClick=document.all.WebBrowser.ExecWB(6,1)??? type=button??? value=打印>??
?? <input???name=Button???onClick=document.all.WebBrowser.ExecWB(6,6)??? type=button??? value=直接打印>??
?? <input???name=Button???onClick=document.all.WebBrowser.ExecWB(8,1)??? type=button??? value=頁面設置>??
?? <input???name=Button? ??onClick=document.all.WebBrowser.ExecWB(10,1)??? type=button??? value=屬性>??
?? <input???name=Button???onClick=document.all.WebBrowser.ExecWB(17,1)??? type=button??? value=全選>??
?? <input???name=Button???onClick=document.all.WebBrowser.ExecWB(22,1)? ??type=button???value=刷新>??
?? <input???name=Button???onClick=document.all.WebBrowser.ExecWB(45,1)??? type=button??? value=關閉>
?
開篇里提到web 打印是“老大難”,這個難度究竟如何?這么說吧,有一個公司為了解決WEB打印的問題,專門組織了一個強大的團隊,并得到全國1000多家軟件公司的技術支持,經N年嘔心瀝血,制作出了“露肚皮”,開發團隊稱:“她是全國1000多家軟件公司的智慧結晶,誕生7年了,幾乎每個功能細節都蘊藏著無數開發者的期待和汗水”。
2. 作者推薦:WEB開發必選伴侶 ——LODOP
泰安夢泰爾軟件有限公司旗下產品,Lodop(標音:勞道譜,俗稱:露肚皮)是專業WEB控件,用它既可裁剪輸出頁面內容,又可用程序代碼直接實現復雜打印。控件功能強大,支持頁面打印、報表打印、條碼打印、圖表打印、套打等,簡單易用。
<script language="JavaScript"src="<s:url value="/style/script/LodopFuncs.js"/>"></script>
<object? id="LODOP_OB" classid="clsid:2105C259-1E0C-4534-8141-A753534CB4CA" width=0 height=0>
<embed id="LODOP_EM"type="application/x-print-lodop" width=0 height=0></embed>
</object>
function prn3_preview(){
LODOP=getLodop();
LODOP.PRINT_INIT("打印控件功能演示_Lodop功能_全頁");
LODOP.ADD_PRINT_HTM(0,0,"100%","100%",document.getElementById("print").innerHTML);
LODOP.PREVIEW();
};
?
幾行簡單的JS,便實現了復雜的WEB打印。
其具體使用方法以及例子請見LODOP文件夾內的文件。
?
總結
 
                            
                        - 上一篇: 安卓9.0添加服务修改SELinux
- 下一篇: 走了,又回来了
