血翼残飞

导航

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;
    }
}

 

posted on 2020-10-10 16:33  血翼残飞  阅读(204)  评论(0编辑  收藏  举报