很久沒(méi)更新 blog 了,工作和一些事情占用了大部分精力,實(shí)在是身不由己。今天終于有空整理一下最近用到的東西。
有個(gè)朋友的項(xiàng)目需要用到 PDF 報(bào)表下載,之前我只做過(guò) Excel 的,相信再做一次 PDF 的下載一定很有趣吧。在網(wǎng)上找了一大圈,似乎 iText 比較符合我的要求,而且這個(gè)工具很早很早以前就有了,生命力很旺盛。進(jìn)入 iText 的主頁(yè)(http://www.lowagie.com/iText/),發(fā)現(xiàn)作者很勤勞,最近2個(gè)月都有新版本發(fā)布。哪知道現(xiàn)在高興得太早了,一堆問(wèn)題接踵而至。
下載倒是很簡(jiǎn)單,一個(gè)iText in a Web Application正是我要找的,不過(guò)這個(gè)例子很簡(jiǎn)單。通過(guò) Google 之后,又發(fā)現(xiàn)要下載一個(gè) CJK 的包(iTextAsian.jar)才能正確顯示中文,好吧我去找。很幸運(yùn)的是在 iText by Example 里找到了這個(gè) jar 的 link,興致勃勃的跑去下載,結(jié)果這是個(gè)無(wú)效鏈接,最后在 sourceForge 上才找到,不容易啊。解決了這些問(wèn)題,想必能夠安穩(wěn)的使用了吧,由于這個(gè)項(xiàng)目比較急,沒(méi)什么耐心一個(gè)個(gè)的翻閱 iText by Example,想找點(diǎn)捷徑,據(jù)說(shuō) iText 可以從 html 直接生成 PDF,竊喜!找了 apache common 的 httpclient,動(dòng)態(tài)模擬 http 請(qǐng)求來(lái)抓 html,根據(jù)控制臺(tái)的 print,的確把 html 抓到了,然后開(kāi)始轉(zhuǎn)換到 PDF,先解決了中文顯示問(wèn)題,可是后面的問(wèn)題解決不了了,html 的 table 和 div 這些,轉(zhuǎn)換到 PDF 都走樣了... ...
很不爽,看來(lái)還是只有老老實(shí)實(shí)的啃 iText by Example實(shí)在點(diǎn)。這次稍微耐心點(diǎn),一點(diǎn)點(diǎn)的看,首先搞清楚了它的 Font 設(shè)置,然后是 Table 和 Cell 的關(guān)系,經(jīng)過(guò)反復(fù)調(diào)試,有點(diǎn)效果了。把代碼貼出來(lái),做個(gè)標(biāo)記吧。以免以后又抓狂。

代碼結(jié)構(gòu)清晰,本來(lái)也沒(méi)什么東西,就是通過(guò) Spring 調(diào)用 service 方法,獲取數(shù)據(jù)后按照 iText 結(jié)構(gòu)輸出即可。不過(guò)代碼里面有個(gè)很愚蠢的動(dòng)作:document.add(new?Paragraph("?",f6)),主要是找不到如何輸出空白行,所以只好出此下策。如果哪位有解法,請(qǐng)告知一下。
做技術(shù)的確不能太著急,慢慢來(lái),總會(huì)找到出口的。
請(qǐng)注意!引用、轉(zhuǎn)貼本文應(yīng)注明原作者:Rosen Jiang 以及出處:http://www.aygfsteel.com/rosen
有個(gè)朋友的項(xiàng)目需要用到 PDF 報(bào)表下載,之前我只做過(guò) Excel 的,相信再做一次 PDF 的下載一定很有趣吧。在網(wǎng)上找了一大圈,似乎 iText 比較符合我的要求,而且這個(gè)工具很早很早以前就有了,生命力很旺盛。進(jìn)入 iText 的主頁(yè)(http://www.lowagie.com/iText/),發(fā)現(xiàn)作者很勤勞,最近2個(gè)月都有新版本發(fā)布。哪知道現(xiàn)在高興得太早了,一堆問(wèn)題接踵而至。
下載倒是很簡(jiǎn)單,一個(gè)iText in a Web Application正是我要找的,不過(guò)這個(gè)例子很簡(jiǎn)單。通過(guò) Google 之后,又發(fā)現(xiàn)要下載一個(gè) CJK 的包(iTextAsian.jar)才能正確顯示中文,好吧我去找。很幸運(yùn)的是在 iText by Example 里找到了這個(gè) jar 的 link,興致勃勃的跑去下載,結(jié)果這是個(gè)無(wú)效鏈接,最后在 sourceForge 上才找到,不容易啊。解決了這些問(wèn)題,想必能夠安穩(wěn)的使用了吧,由于這個(gè)項(xiàng)目比較急,沒(méi)什么耐心一個(gè)個(gè)的翻閱 iText by Example,想找點(diǎn)捷徑,據(jù)說(shuō) iText 可以從 html 直接生成 PDF,竊喜!找了 apache common 的 httpclient,動(dòng)態(tài)模擬 http 請(qǐng)求來(lái)抓 html,根據(jù)控制臺(tái)的 print,的確把 html 抓到了,然后開(kāi)始轉(zhuǎn)換到 PDF,先解決了中文顯示問(wèn)題,可是后面的問(wèn)題解決不了了,html 的 table 和 div 這些,轉(zhuǎn)換到 PDF 都走樣了... ...
很不爽,看來(lái)還是只有老老實(shí)實(shí)的啃 iText by Example實(shí)在點(diǎn)。這次稍微耐心點(diǎn),一點(diǎn)點(diǎn)的看,首先搞清楚了它的 Font 設(shè)置,然后是 Table 和 Cell 的關(guān)系,經(jīng)過(guò)反復(fù)調(diào)試,有點(diǎn)效果了。把代碼貼出來(lái),做個(gè)標(biāo)記吧。以免以后又抓狂。
??1?package?org.rosenjiang.servlet;
??2?
??3?import?java.awt.Color;
??4?import?java.io.IOException;
??5?import?java.util.HashMap;
??6?import?java.util.List;
??7?import?java.util.Map;
??8?
??9?import?javax.servlet.ServletException;
?10?import?javax.servlet.http.HttpServlet;
?11?import?javax.servlet.http.HttpServletRequest;
?12?import?javax.servlet.http.HttpServletResponse;
?13?
?14?import?org.springframework.web.context.WebApplicationContext;
?15?import?org.springframework.web.context.support.WebApplicationContextUtils;
?16?
?17?import?org.rosenjiang.service.UserService;
?18?import?com.lowagie.text.Document;
?19?import?com.lowagie.text.DocumentException;
?20?import?com.lowagie.text.Font;
?21?import?com.lowagie.text.Paragraph;
?22?import?com.lowagie.text.pdf.BaseFont;
?23?import?com.lowagie.text.pdf.PdfPCell;
?24?import?com.lowagie.text.pdf.PdfPTable;
?25?import?com.lowagie.text.pdf.PdfWriter;
?26?
?27?/*
?28??*?ReportServlet
?29??*?@author?rosen?jiang
?30??*?@since?2008-12
?31???*/?
?32?public?class?ReportServlet?extends?HttpServlet?{
?33????????
?34?????/**
?35??????*?Return?a?PDF?document?for?download.
?36??????*?
?37??????*/
?38?????public?void?doGet?(HttpServletRequest?request,?HttpServletResponse?response)
?39?????throws?IOException,?ServletException?{
?40?????????String?account_id?=?request.getParameter("account_id");
?41?????????String?search_date_from?=?request.getParameter("search_date_from");
?42?????????String?to?=?request.getParameter("to");
?43?????????WebApplicationContext?ctx?=?WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
?44?????????UserService?userService?=?(UserService)ctx.getBean("userService");
?45?????????List<Map<String,?Object>>?list?=?userService.getAccountActivity(account_id,?search_date_from,?to);
?46?????????//?create?PDF?document
?47?????????Document?document?=?new?Document();
?48?????????try?{
?49?????????????//set?response?info
?50?????????????response.setContentType("application/x-msdownload;charset=UTF-8");
?51?????????????response.setHeader("Content-Disposition","attachment;filename=report.pdf");
?52?????????????//open?output?stream
?53?????????????PdfWriter.getInstance(document,?response.getOutputStream());
?54?????????????//?open?PDF?document
?55?????????????document.open();
?56?????????????//?set?chinese?font
?57?????????????BaseFont?bfChinese?=?BaseFont.createFont("STSong-Light",?"UniGB-UCS2-H",?BaseFont.NOT_EMBEDDED);??
?58?????????????Font?f2?=?new?Font(bfChinese,?2,?Font.NORMAL);
?59?????????????Font?f6?=?new?Font(bfChinese,?6,?Font.NORMAL);
?60?????????????Font?f8?=?new?Font(bfChinese,?8,?Font.NORMAL);
?61?????????????Font?f10?=?new?Font(bfChinese,?10,?Font.NORMAL);
?62?????????????Font?f12?=?new?Font(bfChinese,?12,?Font.BOLD);
?63?????????????//set?title
?64?????????????document.add(new?Paragraph("金融報(bào)表",?f12));?
?65?????????????//<br>
?66?????????????document.add(new?Paragraph("?",f6));?
?67?????????????//set?sub?title
?68?????????????document.add(new?Paragraph("賬戶(hù)信息",?f10));?
?69?????????????//<br>
?70?????????????document.add(new?Paragraph("?",?f2));
?71?????????????//process?business?data
?72?????????????if(list.size()>0?&&?list.get(0).get("bankbook_no")!=null){
?73?????????????????float?openBalance?=?0;
?74?????????????????//create?table?with?7?columns
?75?????????????????PdfPTable?table?=?new?PdfPTable(7);
?76?????????????????//100%?width
?77?????????????????table.setWidthPercentage(100);
?78?????????????????table.setHorizontalAlignment(PdfPTable.ALIGN_LEFT);
?79?????????????????//create?cells
?80?????????????????PdfPCell?cell?=?new?PdfPCell();
?81?????????????????//set?color
?82?????????????????cell.setBackgroundColor(new?Color(213,?141,?69));
?83?????????????????cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
?84?????????????????//
?85?????????????????cell.setPhrase(new?Paragraph("交易日",?f8));
?86?????????????????table.addCell(cell);
?87?????????????????cell.setPhrase(new?Paragraph("類(lèi)型",?f8));
?88?????????????????table.addCell(cell);
?89?????????????????cell.setPhrase(new?Paragraph("備注",?f8));
?90?????????????????table.addCell(cell);
?91?????????????????cell.setPhrase(new?Paragraph("ID",?f8));
?92?????????????????table.addCell(cell);
?93?????????????????cell.setPhrase(new?Paragraph("票號(hào)",?f8));
?94?????????????????table.addCell(cell);
?95?????????????????cell.setPhrase(new?Paragraph("合計(jì)",?f8));
?96?????????????????table.addCell(cell);
?97?????????????????cell.setPhrase(new?Paragraph("余額",?f8));
?98?????????????????table.addCell(cell);
?99?????????????????//create?another?cell
100?????????????????PdfPCell?newcell?=?new?PdfPCell();
101?????????????????newcell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
102?????????????????
103?????????????????Map<String,?Object>?map?=?new?HashMap<String,?Object>();
104?????????????????for(int?i?=?0;?i?<?list.size();?i++){
105?????????????????????map?=?list.get(i);
106?????????????????????String?cashInout?=?map.get("cash_inout").toString();
107?????????????????????newcell.setPhrase(new?Paragraph(map.get("trade_date").toString(),?f8));
108?????????????????????table.addCell(newcell);
109?????????????????????newcell.setPhrase(new?Paragraph(map.get("bankbook_type").toString(),?f8));
110?????????????????????table.addCell(newcell);
111?????????????????????newcell.setPhrase(new?Paragraph(map.get("memo").toString(),?f8));
112?????????????????????table.addCell(newcell);
113?????????????????????newcell.setPhrase(new?Paragraph(map.get("account_id").toString(),?f8));
114?????????????????????table.addCell(newcell);
115?????????????????????newcell.setPhrase(new?Paragraph(map.get("ticket_no").toString(),?f8));
116?????????????????????table.addCell(newcell);
117?????????????????????newcell.setPhrase(new?Paragraph(map.get("amount").toString(),?f8));
118?????????????????????table.addCell(newcell);
119?????????????????????newcell.setPhrase(new?Paragraph(openBalance+"",?f8));
120?????????????????????table.addCell(newcell);
121?????????????????????if(cashInout.equals("I")){
122?????????????????????????openBalance?=?openBalance?+?Float.valueOf(map.get("amount").toString());
123?????????????????????}else?if(cashInout.equals("O")){
124?????????????????????????openBalance?=?openBalance?-?Float.valueOf(map.get("amount").toString());
125?????????????????????}
126?????????????????}
127?????????????????//print?total?column
128?????????????????newcell.setPhrase(new?Paragraph("合計(jì)"+openBalance,?f8));
129?????????????????table.addCell("");
130?????????????????table.addCell("");
131?????????????????table.addCell("");
132?????????????????table.addCell("");
133?????????????????table.addCell("");
134?????????????????table.addCell("");
135?????????????????table.addCell(newcell);
136?????????????????document.add(table);
137?????????????}else{
138?????????????????PdfPTable?table?=?new?PdfPTable(1);
139?????????????????table.setWidthPercentage(100);
140?????????????????table.setHorizontalAlignment(PdfPTable.ALIGN_LEFT);
141?????????????????PdfPCell?cell?=?new?PdfPCell(new?Paragraph("暫無(wú)數(shù)據(jù)"));
142?????????????????cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
143?????????????????table.addCell(cell);
144?????????????????document.add(table);
145?????????????}
146?????????}
147?????????catch(DocumentException?de)?{
148?????????????de.printStackTrace();
149?????????????System.err.println("document:?"?+?de.getMessage());
150?????????}finally{
151?????????????//?close?the?document?and?the?outputstream?is?also?closed?internally
152?????????????document.close();
153?????????}????????
154?????}
155?}
??2?
??3?import?java.awt.Color;
??4?import?java.io.IOException;
??5?import?java.util.HashMap;
??6?import?java.util.List;
??7?import?java.util.Map;
??8?
??9?import?javax.servlet.ServletException;
?10?import?javax.servlet.http.HttpServlet;
?11?import?javax.servlet.http.HttpServletRequest;
?12?import?javax.servlet.http.HttpServletResponse;
?13?
?14?import?org.springframework.web.context.WebApplicationContext;
?15?import?org.springframework.web.context.support.WebApplicationContextUtils;
?16?
?17?import?org.rosenjiang.service.UserService;
?18?import?com.lowagie.text.Document;
?19?import?com.lowagie.text.DocumentException;
?20?import?com.lowagie.text.Font;
?21?import?com.lowagie.text.Paragraph;
?22?import?com.lowagie.text.pdf.BaseFont;
?23?import?com.lowagie.text.pdf.PdfPCell;
?24?import?com.lowagie.text.pdf.PdfPTable;
?25?import?com.lowagie.text.pdf.PdfWriter;
?26?
?27?/*
?28??*?ReportServlet
?29??*?@author?rosen?jiang
?30??*?@since?2008-12
?31???*/?
?32?public?class?ReportServlet?extends?HttpServlet?{
?33????????
?34?????/**
?35??????*?Return?a?PDF?document?for?download.
?36??????*?
?37??????*/
?38?????public?void?doGet?(HttpServletRequest?request,?HttpServletResponse?response)
?39?????throws?IOException,?ServletException?{
?40?????????String?account_id?=?request.getParameter("account_id");
?41?????????String?search_date_from?=?request.getParameter("search_date_from");
?42?????????String?to?=?request.getParameter("to");
?43?????????WebApplicationContext?ctx?=?WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
?44?????????UserService?userService?=?(UserService)ctx.getBean("userService");
?45?????????List<Map<String,?Object>>?list?=?userService.getAccountActivity(account_id,?search_date_from,?to);
?46?????????//?create?PDF?document
?47?????????Document?document?=?new?Document();
?48?????????try?{
?49?????????????//set?response?info
?50?????????????response.setContentType("application/x-msdownload;charset=UTF-8");
?51?????????????response.setHeader("Content-Disposition","attachment;filename=report.pdf");
?52?????????????//open?output?stream
?53?????????????PdfWriter.getInstance(document,?response.getOutputStream());
?54?????????????//?open?PDF?document
?55?????????????document.open();
?56?????????????//?set?chinese?font
?57?????????????BaseFont?bfChinese?=?BaseFont.createFont("STSong-Light",?"UniGB-UCS2-H",?BaseFont.NOT_EMBEDDED);??
?58?????????????Font?f2?=?new?Font(bfChinese,?2,?Font.NORMAL);
?59?????????????Font?f6?=?new?Font(bfChinese,?6,?Font.NORMAL);
?60?????????????Font?f8?=?new?Font(bfChinese,?8,?Font.NORMAL);
?61?????????????Font?f10?=?new?Font(bfChinese,?10,?Font.NORMAL);
?62?????????????Font?f12?=?new?Font(bfChinese,?12,?Font.BOLD);
?63?????????????//set?title
?64?????????????document.add(new?Paragraph("金融報(bào)表",?f12));?
?65?????????????//<br>
?66?????????????document.add(new?Paragraph("?",f6));?
?67?????????????//set?sub?title
?68?????????????document.add(new?Paragraph("賬戶(hù)信息",?f10));?
?69?????????????//<br>
?70?????????????document.add(new?Paragraph("?",?f2));
?71?????????????//process?business?data
?72?????????????if(list.size()>0?&&?list.get(0).get("bankbook_no")!=null){
?73?????????????????float?openBalance?=?0;
?74?????????????????//create?table?with?7?columns
?75?????????????????PdfPTable?table?=?new?PdfPTable(7);
?76?????????????????//100%?width
?77?????????????????table.setWidthPercentage(100);
?78?????????????????table.setHorizontalAlignment(PdfPTable.ALIGN_LEFT);
?79?????????????????//create?cells
?80?????????????????PdfPCell?cell?=?new?PdfPCell();
?81?????????????????//set?color
?82?????????????????cell.setBackgroundColor(new?Color(213,?141,?69));
?83?????????????????cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
?84?????????????????//
?85?????????????????cell.setPhrase(new?Paragraph("交易日",?f8));
?86?????????????????table.addCell(cell);
?87?????????????????cell.setPhrase(new?Paragraph("類(lèi)型",?f8));
?88?????????????????table.addCell(cell);
?89?????????????????cell.setPhrase(new?Paragraph("備注",?f8));
?90?????????????????table.addCell(cell);
?91?????????????????cell.setPhrase(new?Paragraph("ID",?f8));
?92?????????????????table.addCell(cell);
?93?????????????????cell.setPhrase(new?Paragraph("票號(hào)",?f8));
?94?????????????????table.addCell(cell);
?95?????????????????cell.setPhrase(new?Paragraph("合計(jì)",?f8));
?96?????????????????table.addCell(cell);
?97?????????????????cell.setPhrase(new?Paragraph("余額",?f8));
?98?????????????????table.addCell(cell);
?99?????????????????//create?another?cell
100?????????????????PdfPCell?newcell?=?new?PdfPCell();
101?????????????????newcell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
102?????????????????
103?????????????????Map<String,?Object>?map?=?new?HashMap<String,?Object>();
104?????????????????for(int?i?=?0;?i?<?list.size();?i++){
105?????????????????????map?=?list.get(i);
106?????????????????????String?cashInout?=?map.get("cash_inout").toString();
107?????????????????????newcell.setPhrase(new?Paragraph(map.get("trade_date").toString(),?f8));
108?????????????????????table.addCell(newcell);
109?????????????????????newcell.setPhrase(new?Paragraph(map.get("bankbook_type").toString(),?f8));
110?????????????????????table.addCell(newcell);
111?????????????????????newcell.setPhrase(new?Paragraph(map.get("memo").toString(),?f8));
112?????????????????????table.addCell(newcell);
113?????????????????????newcell.setPhrase(new?Paragraph(map.get("account_id").toString(),?f8));
114?????????????????????table.addCell(newcell);
115?????????????????????newcell.setPhrase(new?Paragraph(map.get("ticket_no").toString(),?f8));
116?????????????????????table.addCell(newcell);
117?????????????????????newcell.setPhrase(new?Paragraph(map.get("amount").toString(),?f8));
118?????????????????????table.addCell(newcell);
119?????????????????????newcell.setPhrase(new?Paragraph(openBalance+"",?f8));
120?????????????????????table.addCell(newcell);
121?????????????????????if(cashInout.equals("I")){
122?????????????????????????openBalance?=?openBalance?+?Float.valueOf(map.get("amount").toString());
123?????????????????????}else?if(cashInout.equals("O")){
124?????????????????????????openBalance?=?openBalance?-?Float.valueOf(map.get("amount").toString());
125?????????????????????}
126?????????????????}
127?????????????????//print?total?column
128?????????????????newcell.setPhrase(new?Paragraph("合計(jì)"+openBalance,?f8));
129?????????????????table.addCell("");
130?????????????????table.addCell("");
131?????????????????table.addCell("");
132?????????????????table.addCell("");
133?????????????????table.addCell("");
134?????????????????table.addCell("");
135?????????????????table.addCell(newcell);
136?????????????????document.add(table);
137?????????????}else{
138?????????????????PdfPTable?table?=?new?PdfPTable(1);
139?????????????????table.setWidthPercentage(100);
140?????????????????table.setHorizontalAlignment(PdfPTable.ALIGN_LEFT);
141?????????????????PdfPCell?cell?=?new?PdfPCell(new?Paragraph("暫無(wú)數(shù)據(jù)"));
142?????????????????cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
143?????????????????table.addCell(cell);
144?????????????????document.add(table);
145?????????????}
146?????????}
147?????????catch(DocumentException?de)?{
148?????????????de.printStackTrace();
149?????????????System.err.println("document:?"?+?de.getMessage());
150?????????}finally{
151?????????????//?close?the?document?and?the?outputstream?is?also?closed?internally
152?????????????document.close();
153?????????}????????
154?????}
155?}
代碼結(jié)構(gòu)清晰,本來(lái)也沒(méi)什么東西,就是通過(guò) Spring 調(diào)用 service 方法,獲取數(shù)據(jù)后按照 iText 結(jié)構(gòu)輸出即可。不過(guò)代碼里面有個(gè)很愚蠢的動(dòng)作:document.add(new?Paragraph("?",f6)),主要是找不到如何輸出空白行,所以只好出此下策。如果哪位有解法,請(qǐng)告知一下。
做技術(shù)的確不能太著急,慢慢來(lái),總會(huì)找到出口的。
請(qǐng)注意!引用、轉(zhuǎn)貼本文應(yīng)注明原作者:Rosen Jiang 以及出處:http://www.aygfsteel.com/rosen