每天写1000字

2019-01-28--第42天(我教你POI(3))

2019-01-29  本文已影响26人  3171631ce5f1

一天一个小案例,教你学会使用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行数据)

image.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);
    }
    
} }
上一篇下一篇

猜你喜欢

热点阅读