一、整体思路
1.因为项目中打印pdf多为表格,所以将所有组件统一使用表格处理。对单格的边框做处理,达到普通文本的目的
2.xml定义表格的格式及普通文本内容,使用{ {变量名称}}来表示需要使用变量替换。
3.考虑到一个pdf中可能有多个数据源,所以使用map来传递参数。
二、实现
1.xml及dtd定义。
这里有一个问题没有解决,那就是dtd文件的位置。先附上代码,待会说问题
我用eclipse新建的java project,新建文件夹xml-config并加入build path,然后在xml-config下直接存储xml文件,NewFile.xml文件内容如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE tablepage SYSTEM "tablepage.dtd"> <tablepage> <!-- <title align="center" v-align="middle" font-family="STSong-Light"> --> <!-- <text>测试标题</text> --> <!-- </title> --> <tables> <table cols="12" font-family="STSong-Light" entity="cpafInfo" rotate="false"> <title align="center" v-align="middle" font-family="STSong-Light"> <text>事务所基本信息</text> </title> <trs> <tr> <tds> <td colspan="12" align="center" v-align="middle" border-width="1 1 1 1"> <text>基本情况</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle" border-width="2 2"> <text>名称</text> </td> <td colspan="10" align="left" v-align="middle"> <text>{
{cpafName}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle" border-width="3"> <text>所属行政区划</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{divisionProvince}}</text> </td> <td colspan="2" align="left" v-align="middle" border-width="0 0"> <text>组织形式</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{orgForm}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>执业许可批准日期</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{approDate}}</text> </td> <td colspan="2" align="left" v-align="middle"> <text>统一社会信用代码</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{regisCno}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>执业许可批准文号</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{rna}}</text> </td> <td colspan="2" align="left" v-align="middle"> <text>执业证书编号</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{cpafCno}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" rowspan="2" align="left" v-align="middle"> <text>注册资本(出资总额)(单位:万)</text> </td> <td colspan="4" rowspan="2" align="left" v-align="middle"> <text>{
{totalInves}}</text> </td> <td colspan="2" align="left" v-align="middle"> <text>分所数量</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{cpafbNum}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>国际网络名称(如有)</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{internetName}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>经营场所</text> </td> <td colspan="10" align="left" v-align="middle"> <text>{
{officeLocation}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>通讯地址</text> </td> <td colspan="10" align="left" v-align="middle"> <text>{
{address}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>报备业务联系人</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{reporter}}</text> </td> <td colspan="2" align="left" v-align="middle"> <text>电子邮箱</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{email}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>报备业务联系电话</text> </td> <td colspan="10" align="left" v-align="middle"> <text>{
{phone}}</text> </td> </tds> </tr> </trs> </table> <table cols="12" font-family="STSong-Light" entity="cpafInfo" rotate="true"> <title align="center" v-align="middle" font-family="STSong-Light"> <text>测试横向页面</text> </title> <trs> <tr> <tds> <td colspan="12" align="center" v-align="middle"> <text>基本情况</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>名称</text> </td> <td colspan="10" align="left" v-align="middle"> <text>{
{cpafName}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>所属行政区划</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{divisionProvince}}</text> </td> <td colspan="2" align="left" v-align="middle"> <text>组织形式</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{orgForm}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>执业许可批准日期</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{approDate}}</text> </td> <td colspan="2" align="left" v-align="middle"> <text>统一社会信用代码</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{regisCno}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>执业许可批准文号</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{rna}}</text> </td> <td colspan="2" align="left" v-align="middle"> <text>执业证书编号</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{cpafCno}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" rowspan="2" align="left" v-align="middle"> <text>注册资本(出资总额)(单位:万)</text> </td> <td colspan="4" rowspan="2" align="left" v-align="middle"> <text>{
{totalInves}}</text> </td> <td colspan="2" align="left" v-align="middle"> <text>分所数量</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{cpafbNum}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>国际网络名称(如有)</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{internetName}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>经营场所</text> </td> <td colspan="10" align="left" v-align="middle"> <text>{
{officeLocation}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>通讯地址</text> </td> <td colspan="10" align="left" v-align="middle"> <text>{
{address}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>报备业务联系人</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{reporter}}</text> </td> <td colspan="2" align="left" v-align="middle"> <text>电子邮箱</text> </td> <td colspan="4" align="left" v-align="middle"> <text>{
{email}}</text> </td> </tds> </tr> <tr> <tds> <td colspan="2" align="left" v-align="middle"> <text>报备业务联系电话</text> </td> <td colspan="10" align="left" v-align="middle" border-width='0 0.5 0 0'> <text>{
{phone}}</text> </td> </tds> </tr> </trs> </table> </tables> </tablepage>
dtd文件内容如下
<!ELEMENT tablepage (title,tables)> <!ELEMENT tables (table)> <!ELEMENT table (trs)> <!ELEMENT trs (tr)> <!ELEMENT tr (tds)> <!ELEMENT tds (td)> <!ELEMENT td (text)> <!ATTLIST title align CDATA "center" v-align CDATA "middle" font-family CDATA #IMPLIED> <!ATTLIST table entity CDATA #REQUIRED rows CDATA #IMPLIED font CDATA "微软雅黑" rotate CDATA "false"> <!ATTLIST td align CDATA "center" v-align CDATA "middle" rowspan CDATA #IMPLIED colspan CDATA "微软雅黑">
dtd主要是对xml内容的约束与检查。问题是,不管是单独将dtd放在xml-config,还是工程根目录下,都会报错,说在另一个位置找不到dtd,但是在两个位置都放dtd,则可以运行。至今不知道为什么。
2.将xml中的内容翻译为bean
Tablepage
package com.ufgov.pdf.entity; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; / * 对应xml中的tablepage标签 * * @author lihh * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "tablepage") @XmlType(propOrder = { "title", "tableList" }) public class Tablepage { @XmlElement(name = "title") private Title title; @XmlElementWrapper(name = "tables") @XmlElement(name = "table") private List<Table> tableList; public Title getTitle() { return title; } public void setTitle(Title title) { this.title = title; } public List<Table> getTableList() { return tableList; } public void setTableList(List<Table> tableList) { this.tableList = tableList; } }
Title
package com.ufgov.pdf.entity; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = { "text" }) public class Title { @XmlElement(name = "text", required = true) private String text; @XmlAttribute(name = "align") private String align; @XmlAttribute(name = "v-align") private String vAlign; @XmlAttribute(name = "font-family") private String fontFamily; public String getText() { return text; } public void setText(String text) { this.text = text; } public String getAlign() { return align; } public void setAlign(String align) { this.align = align; } public String getvAlign() { return vAlign; } public void setvAlign(String vAlign) { this.vAlign = vAlign; } public String getFontFamily() { return fontFamily; } public void setFontFamily(String fontFamily) { this.fontFamily = fontFamily; } }
Table
package com.ufgov.pdf.entity; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlType; / * 对应xml中的table标签 * * @author lihh * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "table", propOrder = { "title", "trList" }) public class Table { @XmlElement(name = "title") private Title title; @XmlElementWrapper(name = "trs") @XmlElement(name = "tr") private List<Tr> trList; @XmlAttribute(name = "cols") private String cols; @XmlAttribute(name = "font-family") private String fontFamily; @XmlAttribute(name = "entity") private String entity; @XmlAttribute(name = "rotate") private String rotate; public String getRotate() { return rotate; } public void setRotate(String rotate) { this.rotate = rotate; } public Title getTitle() { return title; } public void setTitle(Title title) { this.title = title; } public List<Tr> getTrList() { return trList; } public void setTrList(List<Tr> trList) { this.trList = trList; } public String getCols() { return cols; } public void setCols(String cols) { this.cols = cols; } public String getFontFamily() { return fontFamily; } public void setFontFamily(String fontFamily) { this.fontFamily = fontFamily; } public String getEntity() { return entity; } public void setEntity(String entity) { this.entity = entity; } }
Tr
package com.ufgov.pdf.entity; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlType; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "tr",propOrder= {"tdList"}) public class Tr { @XmlElementWrapper(name = "tds") @XmlElement(name = "td") private List<Td> tdList; public List<Td> getTdList() { return tdList; } public void setTdList(List<Td> tdList) { this.tdList = tdList; } }
Td
package com.ufgov.pdf.entity; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "td", propOrder = { "text" }) public class Td { @XmlAttribute(name = "rowspan") private String rowspan; @XmlAttribute(name = "border-width") private String borderWidth; @XmlAttribute(name = "colspan") private String colspan; @XmlAttribute(name = "align") private String align; @XmlAttribute(name = "v-align") private String vAlign; @XmlElement(name = "text") private String text; public String getBorderWidth() { return borderWidth; } public void setBorderWidth(String borderWidth) { this.borderWidth = borderWidth; } public String getSText() { return text; } public void setString(String text) { this.text = text; } public String getRowspan() { return rowspan == null ? "1" : rowspan; } public void setRowspan(String rowspan) { this.rowspan = rowspan; } public String getColspan() { return colspan == null ? "1" : colspan; } public void setColspan(String colspan) { this.colspan = colspan; } public String getText() { return text; } public void setText(String text) { this.text = text; } public String getAlign() { return align; } public void setAlign(String align) { this.align = align; } public String getvAlign() { return vAlign; } public void setvAlign(String vAlign) { this.vAlign = vAlign; }; }
上述实体需要用到XmlAccessorType等注解,不懂的话可以百度。
3.下边是工具类
a.xml转为bean
这个是从网上找的jaxb2的用法
package com.ufgov.pdf.util; import java.io.StringReader; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; / * Jaxb2工具类 */ public class JaxbUtil { / * xml转换成JavaBean * * @param xml * @param c * @return */ @SuppressWarnings("unchecked") public static <T> T converyToJavaBean(String xml, Class<T> c) { T t = null; try { JAXBContext context = JAXBContext.newInstance(c); Unmarshaller unmarshaller = context.createUnmarshaller(); t = (T) unmarshaller.unmarshal(new StringReader(xml)); } catch (Exception e) { e.printStackTrace(); } return t; } // / // * JavaBean转换成xml 默认编码UTF-8 // * // * @param obj // * @param writer // * @return // */ // public static String convertToXml(Object obj) { // return convertToXml(obj, "UTF-8"); // } // / // * JavaBean转换成xml // * // * @param obj // * @param encoding // * @return // */ // public static String convertToXml(Object obj, String encoding) { // String result = null; // try { // JAXBContext context = JAXBContext.newInstance(obj.getClass()); // Marshaller marshaller = context.createMarshaller(); // marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding); // // StringWriter writer = new StringWriter(); // marshaller.marshal(obj, writer); // result = writer.toString(); // } catch (Exception e) { // e.printStackTrace(); // } // // return result; // } }
b.数据库测试用类
package com.ufgov.pdf.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.HashMap; import java.util.Map; public class DBHelper { / * 将下划线风格替换为驼峰风格 * * @param inputString * @return */ private static String underlineToCamelhump(String inputString) { StringBuilder sb = new StringBuilder(); boolean nextUpperCase = false; for (int i = 0; i < inputString.length(); i++) { char c = inputString.charAt(i); if (c == '_') { if (sb.length() > 0) { nextUpperCase = true; } } else { if (nextUpperCase) { sb.append(Character.toUpperCase(c)); nextUpperCase = false; } else { sb.append(Character.toLowerCase(c)); } } } return sb.toString(); } public static Map<String, Object> getData(String sql) throws ClassNotFoundException, SQLException { Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl"; String user = "test"; String password = "1"; Connection conn = DriverManager.getConnection(url, user, password); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); ResultSetMetaData data = rs.getMetaData(); Map<String, Object> map = null; while (rs.next()) { map = new HashMap<String, Object>(); for (int i = 1; i <= data.getColumnCount(); i++) {// 数据库里从 1 开始 String c = data.getColumnName(i); String v = rs.getString(c); System.out.println(c + ":" + v + "\t"); map.put(underlineToCamelhump(c), v); } System.out.println("======================"); } rs.close(); stmt.close(); conn.close(); return map; } public static void main(String[] args) throws ClassNotFoundException, SQLException { String sql = "select * from cpa_cpaf_bir t where t.report_no ='CG5'"; System.out.println(getData(sql)); } }
c.核心转换类
package com.ufgov.pdf.util; import java.io.File; import java.io.FileOutputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import com.itextpdf.text.Document; import com.itextpdf.text.Element; import com.itextpdf.text.Font; import com.itextpdf.text.PageSize; import com.itextpdf.text.Paragraph; import com.itextpdf.text.Rectangle; import com.itextpdf.text.pdf.BaseFont; import com.itextpdf.text.pdf.PdfPCell; import com.itextpdf.text.pdf.PdfPTable; import com.itextpdf.text.pdf.PdfWriter; import com.ufgov.pdf.entity.Table; import com.ufgov.pdf.entity.Tablepage; import com.ufgov.pdf.entity.Td; import com.ufgov.pdf.entity.Title; import com.ufgov.pdf.entity.Tr; / * 到处pdf帮助类 Created by lihhz on 2017/10/16. */ public class PdfHelper { / * xml与数据装配页面<br> * 核心方法,负责输出文档 * * @param tablepage * xml结构 * @param map * 数据结构 * @throws Exception */ public static void convert(Tablepage tablepage, Map<String, Map<String, Object>> map) throws Exception { // TODO:这里要设置一个文件名称,暂时先写死 // Title title = tablepage.getTitle(); // String fileName = title.getText() + ".pdf"; String fileName = "测试文档.pdf"; BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); Font font = new Font(baseFont, 10, Font.NORMAL); // TODO:这个地方如果拿到注会用的话,要改成使用response输出 File file = new File(fileName); FileOutputStream out = new FileOutputStream(file); // TODO:这个A4要不要做配置? Rectangle rectPageSize = new Rectangle(PageSize.A4); Document document = new Document(rectPageSize, -50, -50, 10, 20); PdfWriter.getInstance(document, out); document.open(); // PdfPTable table_title1 = new PdfPTable(1); // setTitle(document, title, table_title1); List<Table> tableList = tablepage.getTableList(); // TODO:这个地方可以做成静态数据,也可以不做,只是为了输出的时候更简单 Map<String, Integer> posMap = new HashMap<String, Integer>(); posMap.put("center", Element.ALIGN_CENTER); posMap.put("left", Element.ALIGN_LEFT); posMap.put("right", Element.ALIGN_RIGHT); posMap.put("top", Element.ALIGN_TOP); posMap.put("middle", Element.ALIGN_MIDDLE); posMap.put("bottom", Element.ALIGN_BOTTOM); int size = tableList.size(); if (tableList == null || size < 1) { return; } for (Table table : tableList) { String rotate = table.getRotate(); Rectangle rect = new Rectangle(PageSize.A4); // 添加横向支持 if (rotate.equals("true")) { document.setPageSize(rect.rotate()); } document.newPage(); PdfPTable table1 = new PdfPTable(12); // table1.addCell("测试一下"); // table1.getDefaultCell().setBorder(PdfPCell.NO_BORDER); // table1.setLockedWidth(true); Title t = table.getTitle(); PdfPTable tableTitle = new PdfPTable(1); if (t != null && t.getText() != null) { setTitle(document, t, tableTitle); } List<Tr> trList = table.getTrList(); String entity = table.getEntity(); Map<String, Object> obj = map.get(entity); if (null == obj) { System.out.println("警告:出现空值!"); } if (trList == null || trList.size() < 1) { document.add(table1); continue; } for (Tr tr : trList) { List<Td> tdList = tr.getTdList(); if (tdList == null || tdList.size() < 1) { continue; } for (Td td : tdList) { String text = td.getText(); if (text.startsWith("{
{") && text.endsWith("}}")) { String key = text.replace("{
{", "").replace("}}", ""); text = obj.containsKey(key) && obj.get(key) != null ? obj.get(key).toString() : ""; } PdfPCell cell = new PdfPCell(new Paragraph(text, font)); String borderWidth = td.getBorderWidth(); float[] borderArr = getBorder(borderWidth); if (borderArr != null) { cell.setBorderWidthTop(borderArr[0]); cell.setBorderWidthRight(borderArr[1]); cell.setBorderWidthBottom(borderArr[2]); cell.setBorderWidthLeft(borderArr[3]); } cell.setColspan(Integer.parseInt(td.getColspan())); cell.setRowspan(Integer.parseInt(td.getRowspan())); cell.setHorizontalAlignment(posMap.get(td.getAlign())); cell.setVerticalAlignment(posMap.get(td.getvAlign())); cell.setMinimumHeight(20f); table1.addCell(cell); } } document.add(table1); } document.close(); } / * TODO:在这里设置边框。暂时没有什么好的方法 */ private static float[] getBorder(String borderWidth) { if (borderWidth == null) { return null; } float[] borderArr = new float[4]; String[] borderWidths = borderWidth.split("\\s+"); // 校验边框 int borderNum = borderWidths.length; switch (borderNum) { case 1: borderArr[0] = Float.parseFloat(borderWidths[0]); borderArr[1] = borderArr[0]; borderArr[2] = borderArr[0]; borderArr[3] = borderArr[0]; break; case 2: borderArr[0] = Float.parseFloat(borderWidths[0]); borderArr[1] = borderArr[0]; borderArr[2] = Float.parseFloat(borderWidths[1]); borderArr[3] = borderArr[2]; break; case 3: borderArr[0] = Float.parseFloat(borderWidths[0]); borderArr[1] = Float.parseFloat(borderWidths[1]); borderArr[2] = Float.parseFloat(borderWidths[2]); borderArr[3] = 0; break; case 4: borderArr[0] = Float.parseFloat(borderWidths[0]); borderArr[1] = Float.parseFloat(borderWidths[1]); borderArr[2] = Float.parseFloat(borderWidths[2]); borderArr[3] = Float.parseFloat(borderWidths[3]); break; default: borderArr[0] = borderArr[1] = borderArr[2] = borderArr[3] = 1; break; } return borderArr; } private static void setTitle(Document document, Title title, PdfPTable tableTitle) throws Exception { PdfPCell cell = new PdfPCell(new Paragraph(title.getText(), new Font( BaseFont.createFont(title.getFontFamily(), "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED), 17, Font.NORMAL))); // TODO:这个地方要设置标题的位置,暂时先不写 cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 设置单格中文本位置(居中:ALIGN_CENTER;靠左:ALIGN_LEFT;靠右:ALIGN_RIGHT) cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 文本垂直方向位置(靠上:ALIGN_TOP;居中:ALIGN_MIDDLE;靠下:ALIGN_BOTTOM;) cell.setBorderWidth(0f); // 设置单格边框,参数都为float cell.setPaddingBottom(20f); // 设置单格文本内边距 tableTitle.addCell(cell); document.add(tableTitle); } }
其它测试类
package com.ufgov.pdf.util; import java.math.BigDecimal; import java.text.NumberFormat; import java.util.Locale; / * 测试用的工具类,在cpams中已经存在,可以删除了 * @author lihh * */ public class CanDel { / * * @param number * 要转换的数字 * @param digit * 保留小数点位数 * @return * @author zhangdand at 2018年3月1日下午4:10:52 */ public static String numberFormat(BigDecimal number, int digit) { String result = "0"; // 小数点后边的数字(不包括.) String digitStr = ""; NumberFormat usFormat = NumberFormat.getIntegerInstance(Locale.US); if (number == null || number.compareTo(new BigDecimal(0)) == 0) { if (digit > 0) { for (int i = 0; i < digit; i++) { digitStr += "0"; } result += "." + digitStr; } } else { // 保留两位小数 usFormat.setMaximumFractionDigits(digit); result = usFormat.format(number); if (result.indexOf(".") < 0 && digit > 0) { for (int i = 0; i < digit; i++) { digitStr += "0"; } result += "." + digitStr; } else if (result.indexOf(".") > 0) { String[] tmpArry = result.split("\\."); digitStr = tmpArry[1]; // 处理小数点结尾0不显示的情况 if (digitStr.length() < digit) { int tmpN = digit - digitStr.length(); for (int i = 0; i < tmpN; i++) { digitStr += "0"; } result = tmpArry[0] + "." + digitStr; } } } return result; } }
4.实体基类
所有需要转pdf的实体继承基类,主要是toMap方法,不过在main方法中并没有用到
package com.ufgov.pdf.entity; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; import com.ufgov.pdf.util.CanDel; / * pdf bean基类. 将需要转换为Map的bean继承自此抽象类 * 如果所需要的类型在toMap方法中不存在,可以添加; * 如果基类的toMap方法实在不能满足您的需求,您可以重写此方法 * * @author lihh * */ public abstract class BaseMapBean { / * 转化为Map * @return */ public Map<String, Object> toMap() { Map<String, Object> map = new HashMap<String, Object>(); try { // 内省是 Java 语言对 Bean 类属性、事件的一种缺省处理方法。例如类 PersonBean中有属性 name, 那我们可以通过 // getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。 Java // 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则(但你最好还是要搞清楚),这些 // API 存放于包 java.beans 中。注意: // PersonBean中属性mN的getter/setter方法必须满足javaBean命名规范,即getmN,不能写作getMN,否则转换失败。 BeanInfo beanInfo = Introspector.getBeanInfo(this.getClass()); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor property : propertyDescriptors) { String key = property.getName(); // 过滤class属性 if (!key.equals("class")) { // 得到property对应的getter方法 Method getter = property.getReadMethod(); Object value = getter.invoke(this); if (value != null) { if (value instanceof BigDecimal) { value = CanDel.numberFormat((BigDecimal) value, 2); } else { System.out.println(value.getClass().toString()); } } map.put(key, value); } } } catch (Exception e) { e.printStackTrace(); System.out.println("transBean2Map Error " + e); } return map; } }
main测试方法
package com.ufgov.pdf.util; import java.io.File; import java.util.HashMap; import java.util.Map; import org.dom4j.Document; import org.dom4j.io.SAXReader; import com.ufgov.pdf.entity.Tablepage; / * 导出PDF的Main方法 * * @author lihh * */ public class ExportPdfImpl { / * 这个在注会中写成一个方法,该方法接受一个xml文件路径参数,一个map * @param args */ public static void main(String[] args) { SAXReader sax = new SAXReader();// 创建一个SAXReader对象 File xmlFile = new File("xml-config/NewFile.xml");// 根据指定的路径创建file对象 try { // 获取document对象,如果文档无节点,则会抛出Exception提前结束 Document document = sax.read(xmlFile); Tablepage tablepage = JaxbUtil.converyToJavaBean(document.asXML(), Tablepage.class); Map<String, Map<String, Object>> map = new HashMap<String, Map<String, Object>>(); String sql = "select * from cpa_cpaf_bir t where t.report_no ='CG5'"; map.put("cpafInfo", DBHelper.getData(sql)); PdfHelper.convert(tablepage, map); } catch (Exception e) { e.printStackTrace(); } } // public static void getRoot() { // SAXReader sax = new SAXReader();// 创建一个SAXReader对象 // File xmlFile = new File("xml-config/NewFile.xml");// 根据指定的路径创建file对象 // try { // // 获取document对象,如果文档无节点,则会抛出Exception提前结束 // Document document = sax.read(xmlFile); // Element root = document.getRootElement();// 获取根节点 // Tablepage tablepage = new Tablepage(); // getNodes(root, tablepage);// 从根节点开始遍历所有节点 // } catch (DocumentException e) { // e.printStackTrace(); // } // // } // // / // * 从指定节点开始,递归遍历所有子节点 // * // * @author chenleixing // */ // public static void getNodes(Element node, Tablepage tablepage) { // System.out.println("--------------------"); // if (node.getName().equals("title")) { // tablepage.setTitle(node.getText()); // } else if (node.getName().equals("table")) { // Table table = new Table(); // } // // 当前节点的名称、文本内容和属性 // System.out.println("当前节点名称:" + node.getName());// 当前节点名称 // System.out.println("当前节点的内容:" + node.getTextTrim());// 当前节点名称 // List<Attribute> listAttr = node.attributes();// 当前节点的所有属性的list // for (Attribute attr : listAttr) {// 遍历当前节点的所有属性 // String name = attr.getName();// 属性名称 // String value = attr.getValue();// 属性的值 // System.out.println("属性名称:" + name + "属性值:" + value); // } // // // 递归遍历当前节点所有的子节点 // List<Element> listElement = node.elements();// 所有一级子节点的list // for (Element e : listElement) {// 遍历所有一级子节点 // // getNodes(e);// 递归 // } // } }
至此,整个项目结束
导出的pdf还有一个问题就是,在设置边框后,放大pdf,会看到设置的边框外侧和其它没有手动设置、正常的cell边框有细微的距离,这个不知道怎么解决
今天的文章 使用itext将xml转换为pdf(一)分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/98760.html