导出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";
}
-
直接访问地址
内容如下:
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会在浏览器打开,如下
- 在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);
}
结果如下:(第二页显示图片)