美文网首页每天写1000字
2019-01-28--第42天(我教你POI(3))

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

作者: 3171631ce5f1 | 来源:发表于2019-01-29 07:57 被阅读26次

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

    相关文章

      网友评论

        本文标题:2019-01-28--第42天(我教你POI(3))

        本文链接:https://www.haomeiwen.com/subject/pazzjqtx.html