java 导出pdf 座次表
工具类
package org.jeecg.common.util; import com.itextpdf.text.*; import com.itextpdf.text.pdf.*; import lombok.extern.slf4j.Slf4j; import java.io.*; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Map; import static org.jeecg.common.util.Base64ImageUtil.checkPic3; /** * 座次表 pdf */ @Slf4j public class PDFZCBUtil { private static Font headfont;// 设置字体大小 private static Font headfontfu;// 设置字体大小 private static Font textfont;// 设置字体大小 static { BaseFont bfChinese; try { bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); headfont = new Font(bfChinese, 14, Font.BOLD);// 设置字体大小 headfontfu = new Font(bfChinese, 8, Font.BOLD);// 设置字体大小 textfont = new Font(bfChinese, 8, Font.NORMAL);// 设置字体大小 } catch (Exception e) { e.printStackTrace(); } } /** * 创建座次表 * * @param imgFilePath * @param fileName * @param map * @throws DocumentException * @throws IOException */ public static void creatPdfZCB(String imgFilePath, String savepath, String fileName, Map<String, List<Map<String, Object>>> map) throws DocumentException, IOException { File savepathF = new File(savepath); if (!savepathF.exists()) { savepathF.mkdirs(); } Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String curDate = sdf.format(date); Rectangle rectangle = new Rectangle(PageSize.A4); Document document = new Document(rectangle); // 页边空白 document.setMargins(10, 10, 30, 30); // 左,右,上,下 PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(savepath + fileName));
//文档允许打印
pdfWriter.setEncryption(null,password,PdfWriter.ALLOW_PRINTING, true);
//不允许用户打印文档,但不提供allow_printing质量(128位加密)
pdfWriter.setEncryption(null,password,PdfWriter.ALLOW_DEGRADED_PRINTING, false);
//不允许用户修改内容,例如 更改页面内容,或插入或删除页
pdfWriter.setEncryption(null,password,PdfWriter.ALLOW_MODIFY_CONTENTS , false);
//不允许用户插入、删除和旋转页面和添加书签。页面的内容不能更改,除非也授予allow_modify_contents权限,(128位加密)
pdfWriter.setEncryption(null,password,PdfWriter.ALLOW_ASSEMBLY, false);
//不允许用户复制或以其他方式从文档中提取文本和图形,包括使用辅助技术。例如屏幕阅读器或其他可访问设备
pdfWriter.setEncryption(null,password,PdfWriter.ALLOW_COPY, false);
//不允许用户提取文本和图形以供易访问性设备使用,(128位加密)
pdfWriter.setEncryption(null,password,PdfWriter.ALLOW_SCREENREADERS, false);
//不允许用户添加或修改文本注释和交互式表单字段
pdfWriter.setEncryption(null,password,PdfWriter.ALLOW_MODIFY_ANNOTATIONS, false);
//不允许用户填写表单字段,(128位加密)
pdfWriter.setEncryption(null,password,PdfWriter.ALLOW_FILL_IN, false);
document.open(); if (map.size() > 0) { map.forEach((k, v) -> { List<Map<String, Object>> conList = v; document.newPage(); try { //主标题 String headTitle = " " + String.valueOf(conList.get(0).get("KSLBMC")) + String.valueOf(conList.get(0).get("QXMC")) + "考场座次表"; String headTitleFu = " 座次表编号:" + String.valueOf(conList.get(0).get("BMH")) + " 首考生末五位:" + String.valueOf(conList.get(0).get("SKSMWW")); String qxmc = String.valueOf(conList.get(0).get("QXMC")); PdfPTable headTable = creatPdfptable(3, 550, new int[]{40, 40, 20}); Phrase phrase = creatPhrase(headTitle, headfont); phrase.add(creatPhrase(headTitleFu, headfontfu)); PdfPCell headCell = setCellBoserAndLeading(3, 0, 15, 14, creatPdfCell(phrase, Element.ALIGN_CENTER)); headCell.setPaddingBottom(10); headTable.addCell(headCell); headTable.addCell(setCellBoserAndLeading(0, 0, 15, 8, creatPdfCell(creatPhrase("考试时间:" + String.valueOf(conList.get(0).get("KSSJ")), headfontfu), Element.ALIGN_LEFT))); headTable.addCell(setCellBoserAndLeading(0, 0, 15, 8, creatPdfCell(creatPhrase("课程名称:" + String.valueOf(conList.get(0).get("KCMC")), headfontfu), Element.ALIGN_LEFT))); //作弊说明 PdfPTable zibiTab = creatPdfptable(2, 100, new int[]{30, 70}); zibiTab.addCell(setCellBoserAndLeading(0, 0, 10, 0, creatPdfCell(creatPhrase("说明:", headfontfu), Element.ALIGN_RIGHT))); String zibiImgPath = imgFilePath + "qkzb.png"; //String zibiImgPath = imgFilePath + "1.jpg"; zibiTab.addCell(setCellBoserAndLeading(0, 0, 6, 0, creatPdfImageCell(zibiImgPath))); PdfPCell zi1Cell = creatPdfCell(creatPhrase("(请在序号上标注)", headfontfu), Element.ALIGN_CENTER); zi1Cell.setPaddingBottom(5); zibiTab.addCell(setCellBoserAndLeading(3, 0, 1, 0, zi1Cell)); PdfPCell ziBiCell = new PdfPCell(zibiTab); ziBiCell.setPaddingBottom(5); headTable.addCell(setCellBoserAndLeading(0, 2, 15, 8, ziBiCell)); PdfPCell kdCell = setCellBoserAndLeading(0, 0, 15, 8, creatPdfCell(creatPhrase("考点:" + String.valueOf(conList.get(0).get("KDDM")) + " " + String.valueOf(conList.get(0).get("KDMC")), headfontfu), Element.ALIGN_LEFT)); kdCell.setPaddingBottom(5); headTable.addCell(kdCell); Phrase xhPhrase = creatPhrase("考场序号:" + String.valueOf(conList.get(0).get("KCH")), headfontfu); xhPhrase.add(creatPhrase(" 应考人数:" + String.valueOf(conList.get(0).get("YKRS")), headfontfu)); xhPhrase.add(creatPhrase(" 实考人数:", headfontfu)); PdfPCell xhrs = setCellBoserAndLeading(0, 0, 15, 8, creatPdfCell(xhPhrase, Element.ALIGN_LEFT)); xhrs.setPaddingBottom(5); headTable.addCell(xhrs); document.add(headTable); //页数 int numZ = (conList.size() - 35) / 40;//求整 数据减去第一页35 ,/40取整 获取每页40 的页数 int numY = (conList.size() - 35) % 40;//求余 数据减去第一页35 ,/40取余 有值页数加一 int total = numZ + 1; //40 页数 + 35的 页数 if (numY > 0) { total += 1; //有余 + 1 } for (int i = 0; i < total; i++) { if (i == 0) { //列表内容 第一页 7行 5列 其他页8行 5列 PdfPTable conTable = creatPdfptable(5, 550, new int[]{20, 20, 20, 20, 20}); for (int j = 0; j < conList.size(); j++) { //第一页 循环35个停止 if (j == 35) { break; } Map<String, Object> con = conList.get(j); conTable.addCell(createContentCellTable(con, imgFilePath, savepath)); } //未行单元格内容不足5个 补充 if (conList.size() < 35) { if (conList.size() % 5 < 5) { for (int j = 0; j < 5 - conList.size() % 5; j++) { conTable.addCell(setCellBoserAndLeading(0, 0, 15, 0, new PdfPCell())); } } } document.add(conTable); createPageFooter(writer, curDate, qxmc); document.newPage(); } else { //列表内容 第一页 7行 5列 其他页8行 5列 PdfPTable conTable = creatPdfptable(5, 550, new int[]{20, 20, 20, 20, 20}); conTable.deleteBodyRows(); for (int j = 35 + 40 * (i - 1); j < conList.size(); j++) { if (j == 35 + 40 * i) { break; } Map<String, Object> con = conList.get(j); conTable.addCell(createContentCellTable(con, imgFilePath, savepath)); } if (i == total - 1) { //未行单元格内容不足5个 补充 if (conList.size() % 5 < 5) { for (int j = 0; j < 5 - conList.size() % 5; j++) { conTable.addCell(setCellBoserAndLeading(0, 0, 15, 0, new PdfPCell())); } } } document.add(conTable); createPageFooter(writer, curDate, qxmc); document.newPage(); } } } catch (DocumentException | IOException e) { e.printStackTrace(); } }); } else { document.add(new Phrase("没有查询到信息!", headfont)); } document.close(); } /** * 内容列表 画出每个单元格 左侧图片 右边内容 */ private static PdfPTable createContentCellTable(Map<String, Object> con, String imgFilePath, String savepath) throws DocumentException, IOException { //一个单元格中 添加2列 table PdfPTable cellTab = creatPdfptable(2, 110, new int[]{52, 48}); //左侧image //String imgPath = imgFilePath + String.valueOf(con.get("PIC1")); //String imgPath = String.valueOf(con.get("PICNET")); //String imgPath = imgFilePath + "3.jpg"; String picurl = String.valueOf(con.get("PICURL")); String zkzh = String.valueOf(con.get("ZKZH")); String cutImgPath = checkPic3(imgFilePath + picurl, savepath + picurl, zkzh); if ("".equals(cutImgPath) || cutImgPath == null) { cutImgPath = imgFilePath + picurl ; } cellTab.addCell(setCellBoserAndLeading(0, 0, 15, 0, creatPdfImageCell(cutImgPath + zkzh + ".jpg"))); //右侧文本 PdfPTable rightTab = new PdfPTable(1); rightTab.setSplitLate(false); rightTab.setSplitRows(true); rightTab.getDefaultCell().setBorderWidth(0f); Phrase kshPhrase = creatPhrase("考试号:", headfontfu); kshPhrase.add(creatPhrase(String.valueOf(con.get("ZCH")), headfontfu)); rightTab.addCell(setCellBoserAndLeading(0, 0, 15, 8, creatPdfCell(kshPhrase, Element.ALIGN_LEFT))); rightTab.addCell(setCellBoserAndLeading(0, 0, 15, 8, creatPdfCell(creatPhrase("准考证号:", headfontfu), Element.ALIGN_LEFT))); rightTab.addCell(setCellBoserAndLeading(0, 0, 15, 8, creatPdfCell(creatPhrase(String.valueOf(con.get("ZKZH")), headfontfu), Element.ALIGN_LEFT))); rightTab.addCell(setCellBoserAndLeading(0, 0, 15, 8, creatPdfCell(creatPhrase("姓 名:", headfontfu), Element.ALIGN_LEFT))); rightTab.addCell(setCellBoserAndLeading(0, 0, 15, 8, creatPdfCell(creatPhrase(String.valueOf(con.get("XM")), headfontfu), Element.ALIGN_LEFT))); PdfPCell ksqmcell = setCellBoserAndLeading(0, 0, 15, 8, creatPdfCell(creatPhrase("考生签名:", headfontfu), Element.ALIGN_LEFT)); ksqmcell.setPaddingBottom(25); rightTab.addCell(ksqmcell); cellTab.addCell(setCellBoserAndLeading(0, 0, 15, 0, new PdfPCell(rightTab))); return cellTab; } /** * 创建页脚 */ private static void createPageFooter(PdfWriter writer, String curDate, String qxmc) throws DocumentException { PdfPTable footTable1 = creatPdfptable(3, 550, new int[]{180, 120, 250}); footTable1.addCell(setCellBoserAndLeading(0, 0, 15, 0, creatPdfCell(creatPhrase("制表单位:" + qxmc + "自学考试办公室", headfontfu), Element.ALIGN_LEFT))); footTable1.addCell(setCellBoserAndLeading(0, 0, 15, 0, creatPdfCell(creatPhrase("打印日期:" + curDate, headfontfu), Element.ALIGN_CENTER))); footTable1.addCell(setCellBoserAndLeading(0, 0, 15, 0, creatPdfCell(creatPhrase("主监考:_____________ 副监考:_____________", headfontfu), Element.ALIGN_RIGHT))); /* rowStart 0 起始行 * rowEnd -1 表示全部行 * xPos 表格横坐标- 从左向右开始计算 * yPos 表格纵坐标- 从下向上开始计算 * canvas 画布*/ footTable1.writeSelectedRows(0, -1, 20, 50, writer.getDirectContent()); } /** * 创建Phrase * * @param text 文本 * @param font 字号 * @return */ private static Phrase creatPhrase(String text, Font font) { Phrase phrase = new Phrase(text, font); return phrase; } /** * 创建cell * * @param align 位置 * @return */ private static PdfPCell creatPdfCell(Phrase phrase, int align) { PdfPCell cell = new PdfPCell(phrase); //cell.setPaddingBottom(20); //cell.setMinimumHeight(30); //设置单元格高度 cell.setUseAscender(true); //设置可以居中 cell.setHorizontalAlignment(align); cell.setVerticalAlignment(Element.ALIGN_MIDDLE); return cell; } /** * 创建 imagecell * * @param imgPath * @return */ private static PdfPCell creatPdfImageCell(String imgPath) throws IOException, BadElementException { PdfPCell imageCell = new PdfPCell(); imageCell.setVerticalAlignment(Element.ALIGN_MIDDLE); imageCell.setHorizontalAlignment(Element.ALIGN_CENTER); File file = new File(imgPath); if (file.exists()) { Image image = Image.getInstance(imgPath); imageCell.setImage(image); //image.scaleToFit(60,80); return imageCell; } else { log.info("==生成座次表图片不存在============================================" + imgPath); return imageCell; } } /** * 创建table * * @param numColumns table 列数 * @param tabWidth tab总宽度 * @param tabColwidth tab 列宽度 百分比 * @return */ private static PdfPTable creatPdfptable(int numColumns, int tabWidth, int[] tabColwidth) throws DocumentException { PdfPTable pdfPTable = new PdfPTable(numColumns); pdfPTable.setTotalWidth(tabWidth);//设置表格bai的总宽度 pdfPTable.setWidths(tabColwidth); pdfPTable.setLockedWidth(true); pdfPTable.setSplitLate(false); pdfPTable.setSplitRows(true); return pdfPTable; } /** * @param colSpan * @param rowSpan * @param disBorder * @param cell * @Name: setCellBoserAndLeading * @Description: 设置单元格的边框和行距 */ private static PdfPCell setCellBoserAndLeading(int colSpan, int rowSpan, int disBorder, int lead, PdfPCell cell) { cell.disableBorderSide(disBorder); // 设置行距 固定行距 可变行距:固定行距+可变行距*最大字体大小 cell.setLeading(lead, 0); if (colSpan > 1) { cell.setColspan(colSpan); } if (rowSpan > 1) { cell.setRowspan(rowSpan); } return cell; } }
controller 执行调用方法
private void performZCBPDF(Map<String,Object> conditionMap) throws Exception { Future<String> future = bskczcbService.creatBskczcbPdf(conditionMap); while (true) { ///这里使用了循环判断,等待获取结果信息 if (future.isDone()) { //判断是否执行完毕 System.out.println("Result from asynchronous process - ======================" + future.get()); //downloadFile(response, savepath, future.get()); File tempFile = new File(pdfpath + "tem/" + future.get()); File file = new File(pdfpath); if (!file.exists()) { file.mkdirs(); } //目的文件路径=目的目录路径+源文件名称 File endFile = new File(pdfpath + future.get()); if (endFile.exists()){ endFile.delete(); } try { if (tempFile.renameTo(endFile)) { System.out.println("文件移动成功!目标路径:{" + endFile.getAbsolutePath() + "}"); } else { System.out.println("文件移动失败!起始路径:{" + tempFile.getAbsolutePath() + "}"); } } catch (Exception e) { System.out.println("文件移动出现异常!起始路径:{" + tempFile.getAbsolutePath() + "}"); } break; } System.out.println("Continue doing something else. "); Thread.sleep(5000); } }
service
package org.jeecg.modules.kqdbb.service; import javax.servlet.http.HttpServletResponse; import java.util.Map; import java.util.concurrent.Future; public interface BSKCZCBService { /** * 生成笔试课程座次表 pdf * @param conditionMap * @return */ Future<String> creatBskczcbPdf(Map<String, Object> conditionMap) throws Exception; }
serviceImpl
package org.jeecg.modules.kqdbb.service.impl; import org.jeecg.modules.kqdbb.controller.BSKCZCBAsyncTask; import org.jeecg.modules.kqdbb.service.BSKCZCBService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletResponse; import java.util.Map; import java.util.concurrent.Future; import static org.jeecg.common.util.Base64ImageUtil.downloadFile; @Service public class BSKCZCBServiceImpl implements BSKCZCBService { @Autowired private BSKCZCBAsyncTask bskczcbAsyncTask; @Override public Future<String> creatBskczcbPdf(Map<String, Object> conditionMap) throws Exception { Future<String> future = bskczcbAsyncTask.asyncTaskCreateZCBPdf(conditionMap); return future; } }
异步执行接口
package org.jeecg.modules.kqdbb.controller; import org.jeecg.common.util.ConditionMapUtils; import org.jeecg.common.util.PDFZCBUtil; import org.jeecg.modules.kqdbb.service.KQDBBService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.util.*; import java.util.concurrent.Future; import static org.jeecg.common.util.Base64ImageUtil.downloadFile; @Service public class BSKCZCBAsyncTask { @Autowired private KQDBBService kqdbbService; @Value("${img.zuoci.httppath}") private String httppath; @Value("${img.zuoci.savepath}") private String savepath; @Value("${img.zuoci.pdfpath}") private String pdfpath; @Async public Future<String> asyncTaskCreateZCBPdf(Map<String, Object> conditionMap) throws Exception { List<Map<String, Object>> bskczcbList = kqdbbService.getBskczcbList(conditionMap); Map<String, List<Map<String, Object>>> listGroupMap = listGroup(bskczcbList, "QXDMKDDMKSDYDMKCDMKCH"); System.out.print("数据分组完成================================"); String fileName = String.valueOf(conditionMap.get("qxmc")) + String.valueOf(conditionMap.get("ksq")) + "笔试课程座次表.pdf"; PDFZCBUtil.creatPdfZCB(httppath, pdfpath + "tem/", fileName, listGroupMap); return new AsyncResult<String>(fileName); } private static Map<String, List<Map<String, Object>>> listGroup(List<Map<String, Object>> list, String key) throws Exception { Map<String, List<Map<String, Object>>> resultMap = new HashMap<>(); try { for (Map map : list) { String mapKey = String.valueOf(map.get(key)); // map中key已存在,将该数据存放到同一个key(key存放的是一级品种code + 交货地code)的map中 if (resultMap.containsKey(mapKey)) { resultMap.get(mapKey).add(map); } else { // map中不存在,新建key,用来存放数据 List<Map<String, Object>> tmpList = new ArrayList<>(); tmpList.add(map); resultMap.put(mapKey, tmpList); } } } catch (Exception e) { throw new Exception("按照一级品种code加交货地code进行分组时出现异常", e); } TreeMap<String, List<Map<String, Object>>> paramTreeMap = new TreeMap<>(resultMap);; return paramTreeMap; } }