引言
iReport能处理绝大部分的报表,也包括图表报表,也能用躲着TTF字体设置显示文字,但只能处理汉字,涉及到藏文,彝文或者其他民族文字时,iReport也显得很无助,好不容易找到一种方法,即通过标注为html标签,这种方法在iReport自带的JRViewer预览是可以的,但是转换为jrxml或者jasper,与Java结合时,iReport又哇哇大哭,直报异常。
好在,iReport的底层也是调用的iText,iText在处理文字的基本单元为Chunk,可以设置为单独的字符,并可以为该字符设置相应的字体,于是,便直接面向iText编程,用他来处理并显示藏文,汉文混显报表。
通过iText提供的PdfPTable来轻松布局,如下为iText的报表部分效果(只有部分内容才涉及到多文字混合显示,处理与实现见后面)
此处的显示效果为汉文和英文都是应用的楷体文字,藏文应用的是喜马拉雅字体。
具体实现
iText提供的PdfPTable是通过AddCell的方式实现自动行计算,可设置列数与每个列宽度的比例,可实现Row Span, Col Span,跨行,跨列,可以为单元格设置样式,如边框,对齐方式,旋转等,提供的代码中都有样例。
1.可在项目目录下指定文件夹和文件名
public static final String BASE_DIR = "PDF/"; public static final String RESULT = BASE_DIR + "report.pdf"; static { File f = new File(BASE_DIR); if (!f.exists()) { f.mkdir(); } }2.创建PDF文档实例,并接收一个返回的表格对象
这里设置了文档的宽高,边框margin
public void build() throws Exception { Rectangle pagesize = new Rectangle(650f, 720f); Document document = new Document(pagesize, 5f,5f, 36f, 36f); //Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream(RESULT)); document.open(); //document.setPageSize(PageSize.A5); //document.setMargins(36, 36, 72, 72); document.setMarginMirroring(true); document.add(createPdfTable()); document.close(); }3.开始创建表格
设置样式的的方法,这里没有完整封装,没有合适规范,只做参考。
private static void setCellStyle(PdfPCell cell) { cell.setHorizontalAlignment(Element.ALIGN_CENTER); cell.setVerticalAlignment(Element.ALIGN_MIDDLE); cell.setNoWrap(false); cell.setPadding(10); } private static void setCellStyle2(PdfPCell cell) { cell.setHorizontalAlignment(Element.ALIGN_LEFT); cell.setNoWrap(false); cell.setPadding(5); } private static void setCellStyle3(PdfPCell cell) { cell.setHorizontalAlignment(Element.ALIGN_CENTER); cell.setNoWrap(false); } private static void setCellStyle4(PdfPCell cell) { cell.setHorizontalAlignment(Element.ALIGN_LEFT); cell.setPaddingLeft(20); cell.setPaddingBottom(10); cell.setPaddingRight(20); cell.setNoWrap(false); }在处理文字混显的时候,需要判断是否为汉文或者藏文,用到一个辅助方法,由于藏文字符,我们统一采用微软提供的喜马拉雅字体来显示,所以需要应用该字体,并应用为UTF-8编码。在UTF-8编码文字中,藏文区间为【 0x0F00--0x0FFF】,所以这里只须判断是否文藏文。由于汉字种类繁多,标点符号等还囊括了英文的编码范围,所以通过以下方法可直接做常规区分
public static final int getLang(char ch) { if ((ch >= 0x0F00) && (ch <= 0x0FFF) ? true : false) { return 1; //藏文 } return 0; //中文或英文获其他 }在代码实现中,把一段多文字的String(可以通过数据库查询,也可配置为文本文件),解析为多个块文本,同种文字的字符封装在一个Span中,最后存放于List中,用到了一个Span显示类
class Span { int lang; String chs; /** * @param lang * @param chs */ public Span(int lang, String chs) { super(); this.lang = lang; this.chs = chs; } public int getLang() { return lang; } public void setLang(int lang) { this.lang = lang; } public String getChs() { return chs; } public void setChs(String chs) { this.chs = chs; } @Override public String toString() { return "Span [lang=" + lang + ", chs=" + chs + "]"; } }最终算法为(此处算法可优化,希望能有人指点)
@Test public void ch() throws Exception { String str = "你好,这里是一段中文,这里是一段藏文。ལལསདབགསདབགས这里是一段英文དབ་འསདལབགཇ"; StringBuffer sb = new StringBuffer(); List<Span> list = new ArrayList<Span>(); int lang = 0; //默认是汉 for (int i = 0; i < str.length(); i++) { char ch = str.charAt(i); int res = CharacterHelper.getLang(ch); System.out.print(ch+"-" + res+"|"); if (res != lang) { list.add(new Span(lang, sb.toString())); lang = res; sb.setLength(0); } if (res == 0) { sb.append(ch); lang = 0; } else if (res == 1) { sb.append(ch); lang = 1; } } if (sb.length()>0) { list.add(new Span(lang, sb.toString())); } System.out.println(); for (Span s : list) { System.out.println(s); } }
/** * @return * @throws DocumentException */ public static PdfPTable createPdfTable() throws DocumentException { PdfPTable table = new PdfPTable(8); table.setWidths(new float[]{0.6f, 0.8f,1,1,1,1,1, 1}); Font titleFont = new Font(HelloWorldPdf.STKAIti); titleFont.setSize(26); PdfPCell cell = new PdfPCell(new Phrase(new Chunk("四川民族出版社书稿审读意见", titleFont))); cell.setColspan(8); cell.setHorizontalAlignment(Element.ALIGN_CENTER); cell.setVerticalAlignment(Element.ALIGN_MIDDLE); cell.setNoWrap(false); cell.setPadding(10); table.addCell(cell); //第二行 Font font = new Font(HelloWorldPdf.STKAIti); PdfPCell cell2 = new PdfPCell(new Phrase(new Chunk("书稿名", font))); setCellStyle(cell2); cell2.setColspan(2); table.addCell(cell2); cell2 = new PdfPCell(new Phrase(new Chunk("曲拉--藏地女性长篇小说第一部", font))); setCellStyle(cell2); cell2.setColspan(6); table.addCell(cell2); //${书稿名} //第三行 PdfPCell cell3 = new PdfPCell(new Phrase(new Chunk("类别", font))); setCellStyle(cell3); cell3.setColspan(2); table.addCell(cell3); cell3 = new PdfPCell(new Phrase(new Chunk("17.少数民族文字", font))); setCellStyle(cell3); cell3.setColspan(4); table.addCell(cell3); cell3 = new PdfPCell(new Phrase(new Chunk("千字数", font))); setCellStyle(cell3); table.addCell(cell3); cell3 = new PdfPCell(new Phrase(new Chunk("210", font))); setCellStyle(cell3); table.addCell(cell3); //第四行 PdfPCell cell4 = new PdfPCell(new Phrase(new Chunk("责编", font))); setCellStyle(cell4); cell4.setColspan(2); table.addCell(cell4); cell4 = new PdfPCell(new Phrase(new Chunk("林么周 才秀加", font))); setCellStyle(cell4); cell4.setColspan(3); table.addCell(cell4); cell4 = new PdfPCell(new Phrase(new Chunk("组稿者", font))); setCellStyle(cell4); table.addCell(cell4); cell4 = new PdfPCell(new Phrase(new Chunk("", font))); setCellStyle(cell4); cell4.setColspan(2); table.addCell(cell4); //第五行 Font mdFont = new Font(HelloWorldPdf.STKAIti); mdFont.setSize(20); PdfPCell cell5 = new PdfPCell(new Phrase(new Chunk("作\n者\n简\n介", mdFont))); cell5.setRowspan(3); setCellStyle(cell5); table.addCell(cell5); cell5 = new PdfPCell(new Phrase(new Chunk("姓名", font))); setCellStyle(cell5); table.addCell(cell5); cell5 = new PdfPCell(new Phrase(new Chunk("毛卡加", font))); setCellStyle(cell5); cell5.setColspan(2); table.addCell(cell5); cell5 = new PdfPCell(new Phrase(new Chunk("性别", font))); setCellStyle(cell5); table.addCell(cell5); cell5 = new PdfPCell(new Phrase(new Chunk("女", font))); setCellStyle(cell5); table.addCell(cell5); cell5 = new PdfPCell(new Phrase(new Chunk("年龄", font))); setCellStyle(cell5); table.addCell(cell5); cell5 = new PdfPCell(new Phrase(new Chunk("", font))); setCellStyle(cell5); table.addCell(cell5); //第六行 cell5 = new PdfPCell(new Phrase(new Chunk("职称", font))); setCellStyle(cell5); table.addCell(cell5); cell5 = new PdfPCell(new Phrase(new Chunk("", font))); setCellStyle(cell5); cell5.setColspan(2); table.addCell(cell5); cell5 = new PdfPCell(new Phrase(new Chunk("单位", font))); setCellStyle(cell5); table.addCell(cell5); cell5 = new PdfPCell(new Phrase(new Chunk("", font))); setCellStyle(cell5); cell5.setColspan(3); table.addCell(cell5); //第七行 cell5 = new PdfPCell(new Phrase(new Chunk("主要\n研究\n方向\n、\n成果", font))); setCellStyle(cell5); table.addCell(cell5); cell5 = new PdfPCell(new Phrase(new Chunk("卡毛加、女,青海省教育厅民族教材编译中心 副译审。主要学术成果有: 《妇女在藏族教育中的作"+ "用》和《浅谈发展藏语文的几点看法》在全省藏文教育教学论文评评选中荣获一等奖和二等奖。", font))); setCellStyle2(cell5); cell5.setColspan(6); table.addCell(cell5); //三审内容 Font xmFont = new Font(HelloWorldPdf.STKAIti); mdFont.setSize(16); PdfPCell cell6 = new PdfPCell(new Phrase(new Chunk("初审意见", mdFont))); cell6.setColspan(8); cell6.setPaddingBottom(10); setCellStyle3(cell6); cell6.setBorderWidthLeft(1); cell6.setBorderWidthRight(1); cell6.setBorderWidthBottom(0f); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("书稿的内容、特点及价值:", font))); cell6.setColspan(8); setCellStyle2(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk( ConfigUtil.getVal("report/content.properties").toString(), xmFont))); cell6.setColspan(8); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("书稿存在的问题(标出问题所在的页面) :", font))); cell6.setColspan(8); setCellStyle2(cell6); table.addCell(cell6); /**算法一:直接处理文本**/ String content = ConfigUtil.getVal("report/content2.properties") .toString(); Paragraph pc = new Paragraph(); StringBuffer sb = new StringBuffer(); List<Span> list = new ArrayList<Span>(); int lang = 0; //默认是汉 for (int i = 0; i < content.length(); i++) { char ch = content.charAt(i); int res = CharacterHelper.getLang(ch); System.out.print(ch+"-" + res+"|"); if (res != lang) { list.add(new Span(lang, sb.toString())); lang = res; sb.setLength(0); } if (res == 0) { sb.append(ch); lang = 0; } else if (res == 1) { sb.append(ch); lang = 1; } } if (sb.length()>0) { list.add(new Span(lang, sb.toString())); } System.out.println(); Chunk cc = null; for (Span s : list) { if (s.getLang() == 0) { cc = new Chunk(s.getChs(), HelloWorldPdf.STKAIti); } else if (s.getLang() == 1) { cc = new Chunk(s.getChs(), HelloWorldPdf.HIMALAYA); } pc.add(cc); } cell6 = new PdfPCell(pc); cell6.setColspan(8); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("提请复审解决的问题:", font))); cell6.setColspan(8); setCellStyle2(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("\n\n\n\n", xmFont))); cell6.setColspan(8); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("对复终审意见的处理:", font))); cell6.setColspan(8); setCellStyle2(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("\n\n\n\n", xmFont))); cell6.setColspan(8); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("初审时间:▁▁▁▁年▁▁▁▁月 ▁▁▁▁日", font))); cell6.setColspan(6); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("签名:▁▁▁▁▁", font))); cell6.setColspan(2); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("复审意见", mdFont))); cell6.setColspan(8); cell6.setPaddingBottom(10); setCellStyle3(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("对书稿及对初审意见的评价:", font))); cell6.setColspan(8); setCellStyle2(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk( ConfigUtil.getVal("report/content.properties").toString(), xmFont))); cell6.setColspan(8); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("对初审提出问题的处理:", font))); cell6.setColspan(8); setCellStyle2(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("\n\n\n\n", xmFont))); cell6.setColspan(8); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("提请终审解决的问题及对书稿的处理意见:", font))); cell6.setColspan(8); setCellStyle2(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("\n\n\n\n", xmFont))); cell6.setColspan(8); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("复审时间:▁▁▁▁年▁▁▁▁月 ▁▁▁▁日", font))); cell6.setColspan(6); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("签名:▁▁▁▁▁", font))); cell6.setColspan(2); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("终审意见", mdFont))); cell6.setColspan(8); cell6.setPaddingBottom(10); setCellStyle3(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("对书稿及初、复审意见的评价:", font))); cell6.setColspan(8); setCellStyle2(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk( ConfigUtil.getVal("report/content.properties").toString(), xmFont))); cell6.setColspan(8); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("处理意见:", font))); cell6.setColspan(8); setCellStyle2(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("\n\n\n\n", xmFont))); cell6.setColspan(8); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("终审时间:▁▁▁▁年▁▁▁▁月 ▁▁▁▁日", font))); cell6.setColspan(6); setCellStyle4(cell6); table.addCell(cell6); cell6 = new PdfPCell(new Phrase(new Chunk("签名:▁▁▁▁▁", font))); cell6.setColspan(2); setCellStyle4(cell6); table.addCell(cell6); table.completeRow(); table.setHorizontalAlignment(Element.ALIGN_CENTER); table.setSpacingBefore(10); return table; }
--- 2014-10-13 及于此