2019-01-28--第42天(我教你POI(3))
一天一个小案例,教你学会使用poi,如果你等不及,可以点击下方的链接,
https://www.imooc.com/video/7145 我就是在这里学的
如果你接触过Poi,那你一定会听过 可以通过XML来配置Excel样式。
像设置列、合并单元格、下拉宽、设置列宽等,那具体怎么实现的呢?
那我们继续往下看↓
XML配置--定制生成用户模板信息
<!-- 定义了excel标签, name是导出excel文件的名称 -->
<excel id="student" code="student" name="学生信息导入">
<!-- 定义excel有哪些列,并且列宽是多少 -->
<colgroup>
<col index="A" width="17em"></col>
<col index="B" width="17em"></col>
<col index="C" width="17em"></col>
<col index="D" width="17em"></col>
<col index="E" width="17em"></col>
<col index="F" width="17em"></col>
</colgroup>
<!-- 定义excel的标题,并且合并第一行 A-F列单元格 和标题的内容 -->
<title>
<tr height="16px">
<td rowspan="1" colspan="6" value="学生信息导入" />
</tr>
</title>
<!-- 定义列名 表头 -->
<thead>
<tr height="16px">
<th value="编号"/>
<th value="姓名"/>
<th value="年龄"/>
<th value="性别"/>
<th value="出生日期"/>
<th value="爱好"/>
</tr>
</thead>
<!-- jsl解析xml 数据样式 -->
<tbody>
<tr height="16px" firstrow="2" firstcol="0" repeat="5"><!-- repeat初始化模板的时候,有多少条数据 -->
<td type="string" isnullable="false" maxlength="30"/><!-- 编号 -->
<td type="string" isnullable="false" maxlength="50"/><!-- 姓名 -->
<td type="numeric" format="##0" isnullable="false" /><!-- 年龄 format设置为整数-->
<td type="enum" format="男,女" isnullable="true" /><!-- 性别 -->
<td type="date" isnullable="false" maxlength="30"/><!-- 出生日期 -->
<td type="enum" format="足球,篮球,兵乓球" isnullable="true" /><!-- 爱好 -->
</tr>
</tbody>
</excel>
Main方法向 D盘 输出Excel文件(初始化5行数据)
![](https://img.haomeiwen.com/i15976239/6c9d6c064924d778.png)
package com.moban.excel;
import java.awt.List;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException
import org.apache.commons.codec.binary.StringUtils;
import org.apache.commons.io.FileUtils;
import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFFont;
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.hssf.util.CellRangeAddressList;
import org.apache.poi.ss.util.CellRangeAddress;
import org.dom4j.Element;
import org.jdom.Document;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.mockito.internal.util.StringUtil;
import aj.org.objectweb.asm.Attribute;
public class CreteTemplate {
/**
* 创建模板文件 使用jdom解析xml文件 -- 本类+xml文件
* 功能:
* 合并单元格
* 数字框、字符框、下拉框、日期框 ,默认初始化5行
* @param args
*/
public static void main(String[] args) {
//获取要解析的xml文件路径 user.dir是当前用户的工作目录 +xml文件存放位置
String path=System.getProperty("user.dir")+"/src/main/java/com/gaoji/excel/student.xml";
//读取文件
File file=new File(path);
//解析xml文件
SAXBuilder builder=new SAXBuilder();
try {
//解析xml文件, 返回对象类型为Document
Document parse = builder.build(file);
//创建Excel
HSSFWorkbook wb=new HSSFWorkbook();
//创建sheet
HSSFSheet sheet=wb.createSheet("sheet0");
//获取XML文件根节点 指的是xml文件中<excel><excel/>标签,可以提前获取模板名称name
org.jdom.Element root=parse.getRootElement();
//获取xml中的模板名称
String templateName=root.getAttribute("name").getValue();
//定义变量 行号 列号 默认都是0
int rownum= 0;
int colum = 0;
//根据xml中colgroup标签,来 设置列宽
org.jdom.Element colgroup = root.getChild("colgroup");
//定义一个共通方法,来设置不同列的列宽,传递参数sheet,colgroup
setColumnWidth(sheet,colgroup);
//根据xml中title标签,来 设置标题
//获取title节点
org.jdom.Element title = root.getChild("title");
//获取tr标签
java.util.List<org.jdom.Element> trs = title.getChildren("tr");
for (int i = 0; i < trs.size(); i++) {
org.jdom.Element tr = trs.get(i);
//获取td节点
java.util.List<org.jdom.Element> tds = tr.getChildren("td");
HSSFRow row = sheet.createRow(rownum);
//设置样式
HSSFCellStyle cellStyle = wb.createCellStyle();
//设置居中
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
//td有可能以后会用到多层,所以这里嵌套一层循环
for (int column = 0; column <tds.size(); column ++) {
org.jdom.Element td = tds.get(column);
//创建单元格
HSSFCell cell = row.createCell(column);
//要合并的单元格 行
org.jdom.Attribute rowSpan = td.getAttribute("rowspan");
org.jdom.Attribute colSpan = td.getAttribute("colspan");
org.jdom.Attribute value = td.getAttribute("value");
if (value != null) {
//不为null 设置值,合并单元格
String val = value.getValue();
//将value值设置到单元格中
cell.setCellValue(val);
//行值装换, -1是因为excel默认从0开始
int rspan = rowSpan.getIntValue()-1;
int cspan = colSpan.getIntValue()-1;
//设置字体
HSSFFont font = wb.createFont();
font.setFontName("仿宋_GB2312");
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//字体加粗
font.setFontHeightInPoints((short)12); //设置字体高度
cellStyle.setFont(font); //字体加入样式中
cell.setCellStyle(cellStyle); //单元格设置样式
//合并单元格 居中 开始行 结束行 开始列 结束列
sheet.addMergedRegion(new CellRangeAddress(rspan, rspan, 0,cspan));
}
}
//操作完表头后 行号+1
rownum ++;
}
//设置表头
org.jdom.Element thead = root.getChild("thead");
trs = thead.getChildren("tr");
for (int i = 0; i < trs.size(); i++) {
org.jdom.Element tr =trs.get(i);
HSSFRow row = sheet.createRow(rownum);
java.util.List<org.jdom.Element> ths = tr.getChildren("th");
for (int column = 0; column < ths.size(); column++) {
org.jdom.Element th = ths.get(column);
//元素属性
org.jdom.Attribute valueAttr = th.getAttribute("value");
//创建单元格
HSSFCell cell = row.createCell(column);
if (valueAttr != null) {
String value= valueAttr.getValue();
cell.setCellValue(value);
}
}
rownum++;
}
//设置数据区域样式
org.jdom.Element tbody = root.getChild("tbody");
org.jdom.Element tr = tbody.getChild("tr");
//初始化模板的时候,有多少条数据
int repeat = tr.getAttribute("repeat").getIntValue();
java.util.List<org.jdom.Element> tds = tr.getChildren("td");
for (int i = 0; i < repeat; i++) {
//创建行记录
HSSFRow row = sheet.createRow(rownum);
//设置每一个单元格
for (int column = 0; column < tds.size(); column++) {
org.jdom.Element td =tds.get(column);
HSSFCell cell = row.createCell(column);
//设置单元格样式 参数excel、单元格、 td标签
setType(wb,cell,td);
}
rownum++;
}
//生成Excel导入模板
File tempFile = new File("d:/" + templateName + ".xls");
//如果文件存在 就删除
tempFile.delete();
//写入数据流
tempFile.createNewFile();
FileOutputStream stream = FileUtils.openOutputStream(tempFile);
//写入文件
wb.write(stream);
//关闭流
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置单元格样式
* @param wb
* @param cell
* @param td
*/
private static void setType(HSSFWorkbook wb, HSSFCell cell, org.jdom.Element td) {
//先得到td的属性
org.jdom.Attribute typeAttr = td.getAttribute("type");
String type = typeAttr.getValue();
//格式化
HSSFDataFormat format = wb.createDataFormat();
//单元格样式
HSSFCellStyle cellStyle = wb.createCellStyle();
//判断 td 设置的单元格类型
if ("NUMERIC".equalsIgnoreCase(type)) {
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);//单元格设置为数字类型
//得到xml中format值
org.jdom.Attribute formatAttr = td.getAttribute("format");
String formatValue = formatAttr.getValue();
//假如没有实例化模板的话,需要设置一个默认值, 先进性判断
//如果不为空,格式化的值就是formatValue 负责给他默认值0.00
formatValue = org.apache.commons.lang3.StringUtils.isNotBlank(formatValue)?formatValue:"#,##0.00";
//格式化
cellStyle.setDataFormat(format.getFormat(formatValue));
}else if ("STRING".equalsIgnoreCase(type)) {
//设置默认值
cell.setCellValue("");
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
//设置文本 @表示
cellStyle.setDataFormat(format.getFormat("@"));
}else if ("DATE".equalsIgnoreCase(type)) {
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
cellStyle.setDataFormat(format.getFormat("yyyy-m-d"));
}else if ("ENUM".equalsIgnoreCase(type)) {//枚举类型
//设置下拉框 参数开始行 结束行 开始列 结束列
org.apache.poi.ss.util.CellRangeAddressList regions = new org.apache.poi.ss.util.CellRangeAddressList(cell.getRowIndex(), cell.getRowIndex(), cell.getColumnIndex(), cell.getColumnIndex());
//获取枚举值
org.jdom.Attribute enumAttr = td.getAttribute("format");
String enumValue = enumAttr.getValue();
//加载下拉列表内容 参数值为下拉列表的数组
DVConstraint constraint = DVConstraint.createExplicitListConstraint(enumValue.split(","));
//加入数据有效性对象 参数regions 和 数据
HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);
wb.getSheetAt(0).addValidationData(dataValidation);
}
cell.setCellStyle(cellStyle);
}
/**
* 设置列宽
* 需要得到colgroup标签中,位置、宽度的大小和属性值
* @param sheet
* @param colgroup
*/
private static void setColumnWidth(HSSFSheet sheet, org.jdom.Element colgroup) {
//获取xml文件中<col>标签
java.util.List<org.jdom.Element> cols = colgroup.getChildren("col");
for (int i = 0; i < cols.size(); i++) {
org.jdom.Element col = cols.get(i);
//获取xml中定义列宽的 width属性
org.jdom.Attribute width = col.getAttribute("width");
//截取一下width的计量单位 截取后为em
String unit = width.getValue().replaceAll("[0-9,\\.]", "");
String value=width.getValue().replaceAll(unit, "");
int v=0;
//判断条件 单位为空 或 单位为px
if (org.apache.commons.lang3.StringUtils.isBlank(unit) || "px".endsWith(unit)) {
v = Math.round(Float.parseFloat(value)*37F);
}else if ("em".endsWith(unit)) {
////如果是的话,通过将poi的宽度单位,转换成excel的宽度单位 来设置列表宽度
v = Math.round(Float.parseFloat(value)*267.5F);
}
//宽度End
sheet.setColumnWidth(i, v);
}
} }