spring整合导出excle和PDF

导出excle表格

  • 添加依赖
    使用apache的开源框架POI

            org.apache.poi
            poi
            3.16
        
  • springmvc中配置
    springmvc配置自定义的视图解析器

    
    
        
    
    
    
    

BeanNameViewResolver:自定义视图,通过视图名解析

  • 编写自定义的excel视图
import com.chenx.domain.District;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.servlet.view.document.AbstractXlsView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

/**
 * Created by ChenX on 2017/8/13.
 */
//想要导出excel,需要继承AbstractXlsView(office2007之前的版本依然可以识别)
// ,AbstractXlsxView(office2007版之后的版本才能打开),为了满足大部分人,选择第一种继承
public class DistrictExcelView extends AbstractXlsView {
    //重写方法
    @Override
    protected void buildExcelDocument(Map model,
                                      Workbook workbook,
                                      HttpServletRequest request,
                                      HttpServletResponse response) throws Exception {
        //url中传中文必须转成%编码才能识别
        String filename = URLEncoder.encode("省市表格.xls","utf-8");
        response.setHeader("Content-Disposition","attachment; filename="+filename);
        HSSFWorkbook book = (HSSFWorkbook) workbook;//对应一个excel文件
        HSSFSheet sheet = book.createSheet("省市区汇总");//在webbook中添加一个sheet,对应Excel文件中的sheet
        HSSFRow row = sheet.createRow(0);//设置表头第0行
        String[] colNames = {"省名字","市名字","地区名字"};
        for (int i = 0; i < colNames.length ; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellValue(colNames[i]);
        }
        List districts = (List) model.get("districts");
        int rowIndex = 1;//第0行是表头,所以设置从第一行开始
        String[] propNames = { "city.province.name", "city.name", "name" };
        for (District district : districts
                ) {
            HSSFRow sheetRow = sheet.createRow(rowIndex);
            for (int i = 0; i < propNames.length; i++) {
                HSSFCell cell = sheetRow.createCell(i);
                //使用反射取值
                cell.setCellValue(BeanUtils.getProperty(district,propNames[i]));
            }
            rowIndex++;
        }
    }
}
  • 编写控制器
@GetMapping("/exp")
    public String exportDistricts(ModelMap map) {
        List districts = distService.listAllDistricts();
        map.put("districts", districts);
        return "distExcel";
    }
  • 直接访问地址


    excel
excel

内容如下:

spring整合导出excle和PDF_第1张图片
excel

PDF文档

  • 添加依赖
    itext的版本最新已经是5.x了,但是要在spring中使用itex只能支持使用2.x的版本

            com.lowagie
            itext
            2.1.7
        
  • springmvc中配置自定义视图

    
    
        
    
    
    
    
  • 编写自定义的PDF视图
import com.chenx.domain.District;
import com.chenx.utils.PDFUtil;
import com.lowagie.text.*;
import com.lowagie.text.pdf.PdfPTable;

import com.lowagie.text.pdf.PdfWriter;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.web.servlet.view.document.AbstractPdfView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

/**
 * Created by ChenX on 2017/8/13.
 */
public class DistrictPdfView extends AbstractPdfView {
    private final String title_content = "省市区详情";
    private final String[] table_head = {"省名字","市名字","区名字"};
    @Override
    protected void buildPdfDocument(Map model,
                                    Document document,
                                    PdfWriter writer,
                                    HttpServletRequest request,
                                    HttpServletResponse response) throws Exception {
        String filename = URLEncoder.encode("省市区详情.pdf","utf-8");
        response.setHeader("Content-Disposition", "inline; filename=" + filename);
        document.open();
        //标题
        Paragraph title = PDFUtil.getParagraph(
                new Chunk(title_content,new Font(PDFUtil.bfChinese,16,Font.BOLD)));
        title.setAlignment(Paragraph.ALIGN_CENTER);
        document.add(title);
        //表格标题
        PdfPTable table = new PdfPTable(table_head.length);
        table.setSpacingBefore(20);
        table.setSpacingAfter(30);
        for (String str: table_head
             ) {
            table.addCell(PDFUtil.getParagraph(str));
        }
        String[] propNames = {"city.province.name", "city.name", "name"};
        //表格内容
        List distList = (List) model.get("districts");
        if (null!=distList){
            for (District district:distList
                    ) {
                for (int i = 0; i < propNames.length; i++) {
                    String content = BeanUtils.getProperty(district, propNames[i]);
                    table.addCell(PDFUtil.getParagraph(content));
                }
            }
        }
        document.add(table);
        document.close();
    }
}

因为itex默认是不支持中文字体的,所以必须给它添加中文字体,用了一个PDFUtil工具类封装了字体,样式等功能

  • PDFUtil工具类
import com.lowagie.text.Chunk;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.BaseFont;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class PDFUtil {
    // 对参数的封装形式比如{name}
    public static final String BEGIN = "{";
    public static final String END = "}";
    // 换行形式{#}
    public static final String NEW_LINE = "#";
    // 默认的行间距、首行距离等,自己添加
    public static final float DEFAULT_LEADING = 20;
    public static final float DEFAULT_LINE_INDENT = 30;


    // 基本字体和样式
    public static BaseFont bfChinese;
    public static Font fontChinese;
    public static Font UNDER_LINE = null;
    static{
        try {
            // SIMKAI.TTF 默认系统语言,这里没使用第三方语言包
            //bfChinese = BaseFont.createFont(PDFTest.class.getResource("/content/")+"SIMKAI.TTF",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
            bfChinese = BaseFont.createFont("c:/Windows/Fonts/STXINWEI.TTF",BaseFont.IDENTITY_H,true);

            fontChinese = new Font(bfChinese, 14, Font.NORMAL);
            UNDER_LINE = new Font(bfChinese, 14,Font.UNDERLINE);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 默认样式
    public static Paragraph getParagraph(String context){
        return getParagraph(context,fontChinese);
    }

    public static Paragraph getParagraph(Chunk chunk){
        return new Paragraph(chunk);
    }

    // 指定字体样式
    public static Paragraph getParagraph(String context,Font font){
        return new Paragraph(context,font);
    }

    // 获得新行,首行缩进,和行间距
    public static Paragraph getNewParagraph(String context,float fixedLeading,float firstLineIndent){
        Paragraph p = getParagraph(context);
        p.setLeading(fixedLeading);
        p.setFirstLineIndent(firstLineIndent);
        return p;
    }

    public static Paragraph getParagraph(String content , Font font , float fixedLeading , int alignment){
        Paragraph p = getParagraph(content);
        p.setFont(font);
        p.setLeading(fixedLeading);
        p.setAlignment(alignment);
        return p;
    }

    // 默认段落样式
    public static Paragraph getDefaultParagraph(String context){
        Paragraph p = getParagraph(context);
        // 默认行间距
        p.setLeading(DEFAULT_LEADING);
        // 默认首行空隙
        p.setFirstLineIndent(DEFAULT_LINE_INDENT);
        return p;
    }

    // 将参数和字符串内容组合成集合
    public static List createParagraphs(String context , Map map){
        int index = 0;
        List list = new ArrayList();
        Paragraph p = getDefaultParagraph(null);
        while((index  = context.indexOf(BEGIN)) > -1){
            String text = context.substring(0,index);
            context = context.substring(index, context.length());
            index = context.indexOf(END);
            String param =  null;
            if(index > 0){
                param = context.substring(BEGIN.length(),index);
            }
            p.add(text);
            if(!NEW_LINE.equals(param)){
                Object value = map.get(param);
                if(value != null){
                    p.add(new Chunk(value.toString(),UNDER_LINE));
                }else{
                    p.add(new Chunk(""));
                }
            }else{
                list.add(p);
                p = getDefaultParagraph(null);
                p.setSpacingBefore(0);
            }
            context = context.substring(index+END.length(),context.length());
        }
        list.add(p);
        list.add(getParagraph(context));
        return list;
    }
}
  • 编写控制器
@GetMapping("/pdf")
    public String exportDistrictsToPdf(ModelMap map) {
        List districts = distService.listAllDistricts();
        map.put("districts", districts);
        return "distPdf";
    }

因为设置了内联打开,所以直接访问url会在浏览器打开,如下

spring整合导出excle和PDF_第2张图片
pdf
  • 在PDF中输出图片
    在刚刚的自定义视图中添加如下代码
document.newPage();
        //添加图片
        String path = request.getServletContext().getRealPath("/images") + "/" + "mm.jpg";
        try (InputStream in = new FileInputStream(path)) {
            byte[] buffer = new byte[in.available()];
            in.read(buffer);
            // URL url = new URL("https://www.baidu.com/img/bd_logo1.png");
            Image image = Image.getInstance(buffer);
            image.scaleToFit(PageSize.A4.getWidth(), PageSize.A4.getHeight());
            document.add(image);
        }

结果如下:(第二页显示图片)

spring整合导出excle和PDF_第3张图片
第二页显示图片

你可能感兴趣的:(spring整合导出excle和PDF)