个人公众号:Java技术大杂烩,每天10点精美文章准时奉上
使用java简单的从数据库中查询数据,然后写入到excel中,数据的类型为 List<Map<String, Object>>格式的数据。
首先下载POI的jar包,网址:https://poi.apache.org/download.html#POI-3.16-beta2
然后导入jar包到工程下
:
此外还需要 commons-collections4-4.1.jar 和 xmlbeans-2.6.0.jar 两个额外的jar包,因为我使用的是 3.15 版本的,所以 commons-collections4-4.1.jar 需要使用 4.1 版本的,原来使用的是 4.0 ,报错了。
这两个包可以在这里下载:
https://mvnrepository.com/artifact/org.apache.xmlbeans/xmlbeans/2.6.0
https://mvnrepository.com/artifact/org.apache.commons/commons-collections4/4.1
导入的类:
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFComment;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
因为需要解析成为 .xlsx 格式的 Excel 文件,所以需要的是 XSSFWorkbook.
准备数据:
public static List<Map<String, Object>> getData() {
List<Map<String, Object>> data = new ArrayList<>();
// 使用 LinkedHashMap 保证有序,即标题和数据对应上
Map<String, Object> map1 = new LinkedHashMap<>();
map1.put("id", 1);
map1.put("name", "张三");
map1.put("age", 23);
map1.put("sex", "男");
Map<String, Object> map2 = new LinkedHashMap<>();
map2.put("id", 2);
map2.put("name", "李四");
map2.put("age", 20);
map2.put("sex", "女");
Map<String, Object> map3 = new LinkedHashMap<>();
map3.put("id", 3);
map3.put("name", "王五");
map3.put("age", 19);
map3.put("sex", "男");
Map<String, Object> map4 = new LinkedHashMap<>();
map4.put("id", 4);
map4.put("name", "赵六");
map4.put("age", 18);
map4.put("sex", "女");
Map<String, Object> map5 = new LinkedHashMap<>();
map5.put("id", 5);
map5.put("name", "小七");
map5.put("age", 22);
map5.put("sex", "男");
data.add(map1);
data.add(map2);
data.add(map3);
data.add(map4);
data.add(map5);
return data;
}
PS : 懒得去连接数据库查询了,就自己随便搞了一个。
下面就是把数据写到 Excel 文件中,只能创建一个 sheet。
/**
* 导出Excel
* @param sheetName 表格 sheet 的名称
* @param headers 标题名称
* @param dataList 需要显示的数据集合
* @param exportExcelName 导出excel文件的名字
*/
public static void exportExcel(String sheetName, List<Map<String, Object>> dataList,
String[] headers,String exportExcelName) {
// 声明一个工作薄
XSSFWorkbook workbook = new XSSFWorkbook();
// 生成一个表格
XSSFSheet sheet = workbook.createSheet(sheetName);
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth(15);
// 生成表格中非标题栏的样式
XSSFCellStyle style = workbook.createCellStyle();
// 设置这些样式
style.setFillForegroundColor(HSSFColor.WHITE.index);//背景色
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setAlignment(HorizontalAlignment.CENTER);
// 生成表格中非标题栏的字体
XSSFFont font = workbook.createFont();
font.setColor(HSSFColor.BLACK.index);
font.setFontHeightInPoints((short) 12);
font.setBold(true);
// 把字体应用到当前的样式
style.setFont(font);
// 设置表格标题栏的样式
XSSFCellStyle titleStyle = workbook.createCellStyle();
titleStyle.setFillForegroundColor(HSSFColor.BLUE_GREY.index);
titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
titleStyle.setBorderBottom(BorderStyle.THIN);
titleStyle.setBorderLeft(BorderStyle.THIN);
titleStyle.setBorderRight(BorderStyle.THIN);
titleStyle.setBorderTop(BorderStyle.THIN);
titleStyle.setAlignment(HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 设置标题栏字体
XSSFFont titleFont = workbook.createFont();
titleFont.setColor(HSSFColor.WHITE.index);
titleFont.setFontHeightInPoints((short) 12);
titleFont.setBold(true);
// 把字体应用到当前的样式
titleStyle.setFont(titleFont);
// 产生表格标题行
XSSFRow row = sheet.createRow(0);
for (short i = 0; i < headers.length; i++) {
XSSFCell cell = row.createCell(i);
cell.setCellStyle(titleStyle);
XSSFRichTextString text = new XSSFRichTextString(headers[i]);
cell.setCellValue(text);
}
// 遍历集合数据,产生数据行
Iterator<Map<String, Object>> it = dataList.iterator();
int index = 0;
while (it.hasNext()) {
index++;
row = sheet.createRow(index);
Map<String, Object> data = it.next();
int i = 0;
for(String key : data.keySet()){
XSSFCell cell = row.createCell(i);
cell.setCellStyle(style);
XSSFRichTextString text = new XSSFRichTextString(data.get(key)+"");
cell.setCellValue(text);
i++;
}
}
try {
OutputStream out = null;
String tmpPath = "G:\\excel\\" + exportExcelName + ".xlsx";
out = new FileOutputStream(tmpPath);
workbook.write(out);
} catch (IOException e) {
e.printStackTrace();
}finally{
if(workbook != null){
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
测试:
public static void main(String[] args) {
List<Map<String, Object>> data = MyExecl.getData();
String sheetName = "学生表";
String[] headers = {"ID","名称","年龄","性别"};
String exportExcelName = "student";
MyExecl.exportExcel(sheetName, data, headers, exportExcelName);
}
结果:
重构上面的代码,封装一下
/**
* 创建每个 sheet 页的数据
*/
private void createSheetData(HSSFWorkbook aWorkbook, String[] aTitles, String aSheetName,
List<String[]> aRowData) {
HSSFSheet tmpSheet = aWorkbook.createSheet(aSheetName);
// 设置sheet的标题
HSSFRow tmpTitileRow = tmpSheet.createRow(0);
for (int i = 0; i < aTitles.length; i++) {
tmpTitileRow.createCell(i).setCellValue(aTitles[i]);
}
// 遍历填充每行的数据
HSSFRow tmpRow = null;
int tmpRowNumber = 1;
for (String[] rowData : aRowData) {
tmpRow = tmpSheet.createRow(tmpRowNumber);
for (int i = 0; i < rowData.length; i++) {
tmpRow.createCell(i).setCellValue(rowData[i]);
}
tmpRowNumber++;
}
}
/**
* 设置响应头
*/
private void setResponseHeader(HttpServletResponse aResponse, String aFileName){
try {
try {
aFileName = new String(aFileName.getBytes(), "ISO8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
aResponse.setContentType("application/octet-stream;charset=ISO8859-1");
aResponse.setHeader("Content-Disposition", "attachment;filename=" + aFileName);
aResponse.addHeader("Pargam", "no-cache");
aResponse.addHeader("Cache-Control", "no-cache");
} catch (Exception e) {
e.printStackTrace();
}
}
测试:
/**
* 通过页面导出
* @param aResponse
* @throws IOException
*/
public void export(HttpServletResponse aResponse) throws IOException {
HSSFWorkbook tmpWorkbook = new HSSFWorkbook();
String[] tmpUserTitles = {"姓名", "性别", "年龄", "工作"};
List<String[]> tmpUsers = getUsers();
createSheetData(tmpWorkbook, tmpUserTitles, "用户信息", tmpUsers);
setResponseHeader(aResponse, "用户信息表.xls");
OutputStream tmpOutputStream = aResponse.getOutputStream();
tmpWorkbook.write(tmpOutputStream);
tmpOutputStream.flush();
tmpOutputStream.close();
}
/**
* 导出,不通过页面导出
*/
public void export() throws IOException {
HSSFWorkbook tmpWorkbook = new HSSFWorkbook();
String[] tmpUserTitles = {"姓名", "性别", "年龄", "工作"};
List<String[]> tmpUsers = getUsers();
createSheetData(tmpWorkbook, tmpUserTitles, "用户信息", tmpUsers);
String[] tmpAddressTitles = {"城市", "区域"};
List<String[]> getAddress = getAddress();
createSheetData(tmpWorkbook, tmpAddressTitles, "地址信息", getAddress);
OutputStream tmpOutputStream = new FileOutputStream("E:\\" + System.currentTimeMillis() + ".xls");
tmpWorkbook.write(tmpOutputStream);
tmpOutputStream.flush();
tmpOutputStream.close();
}
/**
* 测试数据
*/
private List<String[]> getAddress(){
List<String[]> address = new ArrayList<>();
for(int i = 1; i <= 5; i++){
String[] addr = new String[2];
addr[0] = "四川";
addr[1] = "高新 - " + i;
address.add(addr);
}
return address;
}
/**
* 测试数据
*/
private List<String[]> getUsers(){
List<String[]> users = new ArrayList<>();
for(int i = 0; i < 10; i++){
String[] user = new String[4];
user[0] = "zhangsan - " + i;
user[1] = "男";
user[2] = "2" + i;
user[3] = "Java - " + i;
users.add(user);
}
return users;
}
给单元格添加批注
@SuppressWarnings("resource")
private void download(HttpServletResponse resp) throws IOException
{
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("用户表");
XSSFRow row = sheet.createRow(0);
XSSFDrawing p=sheet.createDrawingPatriarch();
XSSFCell cel0 = row.createCell(13);
XSSFComment comment=p.createCellComment(new XSSFClientAnchor(0,0,0,0,(short)0,0,(short)2,4));
comment.setString(new XSSFRichTextString("选填项\r\n最多512个字符"));
cel0.setCellValue("名称");
cel0.setCellComment(comment);
XSSFCell cel1 = row.createCell(14);
XSSFComment comment1=p.createCellComment(new XSSFClientAnchor(0,0,0,0,(short)1,0,(short)3,4));
comment1.setString(new XSSFRichTextString("选填项\r\n最多512个字符"));
cel1.setCellValue("年龄");
cel1.setCellComment(comment1);
// 批注相关
XSSFCell tmpCell = null;
XSSFComment tmpComment = null;
XSSFRichTextString tmpVal = new XSSFRichTextString("选填项\r\n最多512个字符");
int dx1 = 80;
int dx2 = 140;
short col1 = 15; // 批注开始的列,即15列
short col2 = 17; // 批注结束的列,即17列
// 动态创建列和列上的批注
for(int i = 1; i <= 5; i++)
{
tmpCell = row.createCell(row.getLastCellNum());
tmpComment = p.createCellComment(new XSSFClientAnchor(dx1,0,dx2,0, col1,0, col2,4));
tmpCell.setCellValue("扩展裂-" + i);
tmpComment.setString(tmpVal);
col1++;
col2++;
}
setResponseHeader(resp, "用户表.xlsx");
OutputStream tmpOutputStream = resp.getOutputStream();
workbook.write(tmpOutputStream);
tmpOutputStream.flush();
tmpOutputStream.close();
}
注意: 创建批注的类 XSSFClientAnchor 的构造参数有四个 :
public XSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2){....}
它们的作用如下:
dx1,dy1 :起始单元格中的 x, y 坐标.
dx2,dy2 :结束单元格中的 x , y 坐标
col1,row1 :指定起始的单元格,下标从0开始
col2,,row2 :指定结束的单元格 ,下标从0开始
来源:oschina
链接:https://my.oschina.net/u/2436902/blog/871875