导出excel通用模板(程序定义模板导出)

转载原文:https://www.jianshu.com/p/5c7b359a159c

如下代码,本方法主要用于程序定义模板格式,并导出文件。该方法将定义和创建分离,达到了一定解耦合,降低了开发复杂度。但是依然是程序定义模板,对模板的样式需要程序控制,没有达到将数据和样式分离的目的。

 

改良版,关于添加依赖之类的之前一篇文章里面有。
这篇是把之前的方法抽成通用模板。

一、添加一个实体类

package com.lencity.securitymanagementplatform.data.entity;

import java.util.List;

public class XlsData {

    public static final int DATA_TYPE_INTEGER = 0;
    public static final int DATA_TYPE_STRING = 1;
    private List<String> titles;//表头
    private List<Integer> types;//数据类型
    private List<List<Object>> values;存表数据
    
    public List<Integer> getTypes() {
        return types;
    }
    public void setTypes(List<Integer> types) {
        this.types = types;
    }
    public List<String> getTitles() {
        return titles;
    }
    public void setTitles(List<String> titles) {
        this.titles = titles;
    }
    public List<List<Object>> getValues() {
        return values;
    }
    public void setValues(List<List<Object>> values) {
        this.values = values;
    }   
}

二、创建一个service类

package com.lencity.securitymanagementplatform.service;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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.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.ss.usermodel.HorizontalAlignment;
import org.springframework.stereotype.Service;

import com.lencity.securitymanagementplatform.data.entity.XlsData;

@Service
public class XlsService {

        //写一个接口,哪个控制器需要加上导出excel功能就继承这个接口
    public static interface IXlsOutputProcessor {
        public XlsData processXlsData(Map<String, Object> condition);
    }

        //解析数据创建excel
    public HSSFWorkbook createExcelData(IXlsOutputProcessor processor, Map<String, Object> condition) {
        XlsData xlsData = processor.processXlsData(condition);
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("统计表");// 创建一个excel表单
        HSSFRow titleRow = sheet.createRow(0);
        // 设置列宽,setColumnWidth的第二个参数要乘以256,这个参数的单位是1/256个字符宽度
        sheet.setColumnWidth(1, 15 * 256);
        sheet.setColumnWidth(3, 20 * 256);

        HSSFCellStyle style = workbook.createCellStyle();
        style.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));// 设置日期格式
        HSSFFont font = workbook.createFont();// 设置为居中加粗
        font.setBold(true);
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setFont(font);
        List<String> titles = xlsData.getTitles();
        HSSFCell cell;
        /* 构造表头 */
        for (int i = 0; i < titles.size(); i++) {
            cell = titleRow.createCell(i);
            cell.setCellValue(titles.get(i));
            cell.setCellStyle(style);
        }
        int rowNum = 1;
        List<Integer> dataTypes = xlsData.getTypes();
        List<List<Object>> values = xlsData.getValues();
        for (int i = 0; i < values.size(); i++) {
            List<Object> value = values.get(i);
            HSSFRow row = sheet.createRow(rowNum);
            for (int j = 0; j < value.size(); j++) {
                switch (dataTypes.get(j)) {
                case XlsData.DATA_TYPE_INTEGER:
                    row.createCell(j).setCellValue((Integer) value.get(j));
                    break;
                case XlsData.DATA_TYPE_STRING:
                    row.createCell(j).setCellValue((String) value.get(j));
                    break;
                }
            }
            rowNum++;

        }
        return workbook;
    }


    // 浏览器导出excel
    public void buildExcelDocument(String filename, HSSFWorkbook workbook, HttpServletResponse response)
            throws Exception {
        response.reset();
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "utf-8"));
        OutputStream outputStream = response.getOutputStream();
        workbook.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }

    // 下载excel模板功能
    public void downloadTemplate(HttpServletResponse response,HttpServletRequest request) throws Exception {
        String fileName="导出模板.xls";
        response.reset();
        response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
            String filePath=request.getServletContext().getRealPath("/excel/")+fileName;
            FileInputStream input=new FileInputStream(filePath);
            OutputStream out=response.getOutputStream();
            byte[] b=new byte[2048];
            int len;
            while((len=input.read(b))!=-1) {
                out.write(b,0,len);
            }
             response.setHeader("Content-Length", String.valueOf(input.getChannel().size()));
                input.close();
    }
}

三、控制器
假设我们要在用户页面加上导出表格的功能,那就在用户的控制器上继承接口

public class UserController implements IXlsOutputProcessor {

继承之后需要在控制器中重写接口方法,

 

 
导出的表格样式.png
关于封装数据,主要就是根据自己实际的项目需求,来构造数据了
// 封装数据
    @Override
    public XlsData processXlsData(Map<String, Object> condition) {
        List<String> titles = new ArrayList<>();//表头
        List<Integer> dataTypes = new ArrayList<>();//表数据类型
        List<List<Object>> values = new ArrayList<>();//表头对应的数据
        titles.add("姓名");
        dataTypes.add(XlsData.DATA_TYPE_STRING);
        titles.add("手机号码");
        dataTypes.add(XlsData.DATA_TYPE_STRING);
        titles.add("职位");
        dataTypes.add(XlsData.DATA_TYPE_STRING);
        titles.add("部门");
        dataTypes.add(XlsData.DATA_TYPE_STRING);
        List<User> users = userService.getUsersByCondition(condition);
        XlsData xlsData = new XlsData();
        xlsData.setTitles(titles);
        xlsData.setTypes(dataTypes);
        for (User user : users) {
            List<Object> tmpList = new ArrayList<>();
            tmpList.add(user.getName());
            tmpList.add(user.getMobile());
            tmpList.add(user.getPosition());
            tmpList.add(departmentService.getDepartmentNameByDepartmentCode(user.getDepartmentCode()));
            values.add(tmpList);
        }
        xlsData.setValues(values);
        return xlsData;
    }

    // 导出excel,前台js,点击   导出excel   关联的路径就是这个
    @PostMapping(value = "/downLoadXls")
    @ResponseBody
    public String downLoadXls(Map<String, Object> condition, HttpServletResponse response) throws Exception {
        String fileName = "导出excel.xls";
        HSSFWorkbook workbook = xlsService.createExcelData(this, condition);
        xlsService.buildExcelDocument(fileName, workbook, response);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", 1);
        return jsonObject.toString();
    }
    // 下载模板,前台js,点击  下载模板   关联的路径就是这个
    @PostMapping(value = "/downloadTemplate")
    @ResponseBody
    public String downloadTemplate(HttpServletResponse response,HttpServletRequest request) throws Exception {
        String fileName = "导出excel.xls";
        xlsService.downloadTemplate(response, request);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", 1);
        return jsonObject.toString();
    }
 
前台界面.png

 

 
模板的存放位置

 

前台按钮代码

<button type="button" class="btn btn-primary waves-effect" onclick="downloadTemplate()" id="downloadTemplate">
<i class="material-icons">vertical_align_bottom</i> 
<span>下载模板</span>
</button>

<button type="button" class="btn btn-primary waves-effect"onclick="exportExcel()">
<i class="material-icons">vertical_align_bottom</i> 
<span>导出表格</span>
</button>

js

form表单里面是页面的表单筛选条件,如果要导数据库所有的数据,可把form表单去掉。如果导出的数据是有筛选条件的,需要改一下form表单
function exportExcel() {
   var name = $("#name").val();
   var departmentCode = $("#departmentCode").find("option:selected").val();
    var form = $("<form>");   
    $('body').append(form);  
        form.attr('style','display:none');   
        form.attr('target','');
        form.attr('method','post');
        form.attr('action',contextPath+'/user/downLoadXls');//下载文件的请求路径

        //对应查询条件的开始时间
        var input1 = $('<input>'); 
        input1.attr('type','hidden'); 
        input1.attr('name',"name"); 
        input1.attr('value',name);
        form.append(input1);  

        //对应查询条件的结束时间
        var input2 = $('<input>'); 
        input2.attr('type','hidden'); 
        input2.attr('name','departmentCode'); 
        input2.attr('value',departmentCode);
        form.append(input2);
        form.submit();    
}

下载模板的js

function downloadTemplate() {
    var form = $("<form>");
    $('body').append(form);
    form.attr('style', 'display:none');
    form.attr('target', '');
    form.attr('method', 'post');
    form.attr('action', contextPath + '/user/downloadTemplate');// 下载文件的请求路径
    form.submit();
}

 

二、java通过poi模板导出excel(程序根据模板样式导出

此方法与上文不同的是,用户自定义模板样式,程序根据参数名称和sheet名称来查找填写相应内容。

附上poi的maven配置:

 

Java代码  收藏代码
<dependency>  
     <groupId>org.apache.poi</groupId>  
     <artifactId>poi-ooxml</artifactId>  
     <version>3.16</version>  
 </dependency>  

 

 我使用了最新的版本。

 

 

package com.unionpay.cqupay.utils;

import com.unionpay.cqupay.common.CetcBigDataException;
import com.unionpay.cqupay.entity.SheetData;
import com.unionpay.cqupay.pojo.UmUserGatherPojo;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * @author adam
 * @version 1.0
 * @date 2019-9-23
 */
public class ExcelUtil {
    private final static Logger logger = LoggerFactory.getLogger(ExcelUtil.class);

    /**
     * Sheet复制
     * @param fromSheet
     * @param toSheet
     * @param copyValueFlag
     */
    public static void copySheet(Workbook wb, Sheet fromSheet, Sheet toSheet,
                                 boolean copyValueFlag) {
        //合并区域处理

        mergerRegion(fromSheet, toSheet);
        int index = 0;
        for (Iterator<Row> rowIt = fromSheet.rowIterator(); rowIt.hasNext();) {
            Row tmpRow =  rowIt.next();
            Row newRow = toSheet.createRow(tmpRow.getRowNum());

            CellStyle style = tmpRow.getRowStyle();
            if(style != null)
                newRow.setRowStyle(tmpRow.getRowStyle());

            newRow.setHeight(tmpRow.getHeight());

            //针对第一行设置行宽
            if(index == 0) {
                int first = tmpRow.getFirstCellNum();
                int last = tmpRow.getLastCellNum();
                for(int i = first ; i < last ; i++) {
                    int w = fromSheet.getColumnWidth(i);
                    toSheet.setColumnWidth(i, w + 1);
                }
                toSheet.setDefaultColumnWidth(fromSheet.getDefaultColumnWidth());
            }

            //行复制
            copyRow(wb,tmpRow,newRow,copyValueFlag);

            index++ ;
        }
    }
    /**
     * 行复制功能
     * @param fromRow
     * @param toRow
     */
    static void copyRow(Workbook wb,Row fromRow,Row toRow,boolean copyValueFlag){
        for (Iterator<Cell> cellIt = fromRow.cellIterator(); cellIt.hasNext();) {
            Cell tmpCell = cellIt.next();
            Cell newCell = toRow.createCell(tmpCell.getColumnIndex());
            copyCell(wb,tmpCell, newCell, copyValueFlag);
        }
    }
    /**
     * 复制原有sheet的合并单元格到新创建的sheet
     *
     * @param fromSheet 新创建sheet
     * @param toSheet      原有的sheet
     */
    static void mergerRegion(Sheet fromSheet, Sheet toSheet) {
        int sheetMergerCount = fromSheet.getNumMergedRegions();
        for (int i = 0; i < sheetMergerCount; i++) {

            CellRangeAddress cra = fromSheet.getMergedRegion(i);

            toSheet.addMergedRegion(cra);
        }
    }
    /**
     * 复制单元格
     *
     * @param srcCell
     * @param distCell
     * @param copyValueFlag
     *            true则连同cell的内容一起复制
     */
    public static void copyCell(Workbook wb,Cell srcCell, Cell distCell,
                                boolean copyValueFlag) {



        CellStyle newstyle=wb.createCellStyle();
        //copyCellStyle(srcCell.getCellStyle(), newstyle);
        //distCell.setEncoding(srcCell.);
        newstyle.cloneStyleFrom(srcCell.getCellStyle());
        //样式
        distCell.setCellStyle(newstyle);
        //评论
        if (srcCell.getCellComment() != null) {
            distCell.setCellComment(srcCell.getCellComment());
        }
        // 不同数据类型处理
        CellType srcCellType = srcCell.getCellTypeEnum();
        distCell.setCellType(srcCellType);


        if (copyValueFlag) {
            if (srcCellType == CellType.NUMERIC) {
                if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(srcCell)) {
                    distCell.setCellValue(srcCell.getDateCellValue());
                } else {
                    distCell.setCellValue(srcCell.getNumericCellValue());
                }
            } else if (srcCellType == CellType.STRING ) {
                distCell.setCellValue(srcCell.getRichStringCellValue());
            } else if (srcCellType == CellType.BLANK ) {
                // nothing21
            } else if (srcCellType == CellType.BOOLEAN  ) {
                distCell.setCellValue(srcCell.getBooleanCellValue());
            } else if (srcCellType == CellType.ERROR ) {
                distCell.setCellErrorValue(srcCell.getErrorCellValue());

            } else if (srcCellType == CellType.FORMULA  ) {
                distCell.setCellFormula(srcCell.getCellFormula());
            } else { // nothing29
            }
        }
    }


    /**
     * 写入excel数据
     * @param model 采用的模板 位置在 src/model/下 模板第一个sheet页必须是模板sheet
     * @param sheetDatas 模板数据
     */

    public static void writeData(String model , OutputStream out, SheetData... sheetDatas ) {

        Workbook wb = null;
        try {
            InputStream input = new FileInputStream(model);
         // InputStream input = ExcelUtils2.class.getResourceAsStream(model);
            if(input == null) {
                throw new RuntimeException("模板文件不存在"+model);
            }

            if(model.endsWith(".xlsx"))
                wb = new XSSFWorkbook(input);
            else if(model.endsWith(".xls"))
                wb = new HSSFWorkbook(input);
            else
                throw new RuntimeException("模板文件不合法,不是excel类型"+model );
        } catch (IOException e) {
            //e.printStackTrace();

            throw new RuntimeException("加载模板文件失败"+model);
        }

        Sheet source =  wb.getSheetAt(0);

        //就一个的话 直接用模板
        int size = sheetDatas.length ;
        /*for(int i = 0 ; i < size  ; i++) {

            if(i == 0) {
                if (sheetDatas[0]!=null){
                    wb.setSheetName(0, sheetDatas[0].getName());
                }

            } else {
                if (sheetDatas[i]!=null) {
                    Sheet toSheet = wb.createSheet(sheetDatas[i].getName());
                    //复制格式
                    copySheet(wb, source, toSheet, true);
                }

            }


        }*/
        int numberOfSheets=wb.getNumberOfSheets();
        out:for(int i = 0 ; i < size  ; i++) {
            String sheetDatasName=sheetDatas[i].getName();
            if (StringUtils.isNotBlank(sheetDatasName)){
                for(int j=0;j<numberOfSheets;j++){
                    if (sheetDatasName.equals(wb.getSheetAt(j).getSheetName())){
                        //写数据
                        writeData(sheetDatas[i],wb.getSheetAt(j) );
                        continue out;
                    }
                }
            }

        }
        try {
            wb.write(out);
            out.flush();
            wb.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    /**
     * 向sheet页中写入数据
     * @param sheetData 数据Map
     * @param sheet sheet
     */
    public static void writeData(SheetData sheetData , Sheet sheet) {

        //从sheet中找到匹配符 #{}表示单个 , ${}表示集合,从该单元格开始向下追加

        for(Iterator<Row> rowIt = sheet.rowIterator(); rowIt.hasNext();) {
            Row row = rowIt.next();
            //取cell
            for(int j = row.getFirstCellNum() ; j < row.getLastCellNum() ; j++) {

                Cell cell = row.getCell(j);

                //判断cell的内容是否包含 $ 或者#
                if(cell != null && cell.getCellTypeEnum() == CellType.STRING && cell.getStringCellValue() != null
                        && (cell.getStringCellValue().contains("$") || cell.getStringCellValue().contains("#") )) {
                    //剥离# $
                    String[] winds = CommonUtils.getWildcard(cell.getStringCellValue().trim());

                    for(String wind : winds) {

                        writeData(sheetData, wind , cell , sheet);
                    }


                }

            }

        }
    }

    /**
     * 填充数据
     * @param sheetData
     * @param keyWind #{name}只替换当前 or ${names} 从当前行开始向下替换
     */
    static void writeData(SheetData sheetData , String keyWind , Cell cell , Sheet sheet) {
        String key = keyWind.substring(2 , keyWind.length() - 1);

        if(keyWind.startsWith("#")) {

            //简单替换

            Object value = sheetData.get(key);
            //为空则替换为空字符串
            if(value == null)
                value = "" ;

            String cellValue = cell.getStringCellValue();
            cellValue = cellValue.replace(keyWind, value.toString());

            cell.setCellValue(cellValue);

        } else  if(keyWind.startsWith("$")) {

            //从list中每个实体开始解,行数从当前开始
            int rowindex = cell.getRowIndex();
            int columnindex = cell.getColumnIndex();

            List<? extends Object> listdata = sheetData.getDatas();

            //不为空的时候开始填充
            if(listdata != null && !listdata.isEmpty()){
                for(Object o : listdata) {
                    Object cellValue = CommonUtils.getValue(o, key);

                    Row row = sheet.getRow(rowindex);
                    if(row == null) {
                        row = sheet.createRow(rowindex);
                    }


                    //取出cell
                    Cell c = row.getCell(columnindex);
                    if(c == null)
                        c = row.createCell(columnindex);
                    if(cell.getCellStyle() != null){
                        c.setCellStyle(cell.getCellStyle());

                    }

                    if(cell.getCellTypeEnum() != null) {
                        c.setCellType(cell.getCellTypeEnum());

                    }

                    if(cellValue != null) {
                        if(cellValue instanceof Number || CommonUtils.isNumber(cellValue) )
                            c.setCellValue( Double.valueOf(cellValue.toString()));
                        else if(cellValue instanceof Boolean)
                            c.setCellValue((Boolean)cellValue);
                        else if(cellValue instanceof Date)
                            c.setCellValue(DateUtil.getDayFormatStr((Date)cellValue,sheetData.getTimeFormat()));
                        else
                            c.setCellValue(cellValue.toString());
                    } else {

                        //数据为空 如果当前单元格已经有数据则重置为空
                        if(c.getStringCellValue() != null) {
                            c.setCellValue("");
                        }

                    }



                    rowindex++ ;
                }
            } else {
                //list数据为空则将$全部替换空字符串
                String cellValue = "" ;

                cell.setCellValue(cellValue);

            }



        }

    }


    public static File createFile(String templateName,String fileName,  SheetData... sheetData) throws CetcBigDataException {
        String model = System.getProperty("user.dir")+File.separator+"res"+File.separator+"model"+File.separator+templateName ;

        //创建个临时文件
        File file=new File("temp"+File.separator+"statistics");
        if(!file.exists()){//如果文件夹不存在
            file.mkdirs();//创建文件夹
        }
        file=new File("temp"+File.separator+"statistics"+File.separator+fileName);

        try {
            TemplateExcelUtil.writeData(model, new FileOutputStream(file), sheetData);
        }catch (Exception e){
            throw new CetcBigDataException("导出表格失败,失败原因:"+e.getMessage());

        }
        return file;

    }


    public static void main(String[] args) {

        //获取模板
        //   logger.info("项目路径{}",System.getProperty("user.dir"));

        //    String model = System.getProperty("user.dir")+File.separator+"res\\model\\template_user.xlsx" ;
        String model = "D:\\cetc\\nas\\cetcData\\excelmodel\\template_user.xlsx" ;
        File f = new File("e:/test.xlsx");


        SheetData sd = new SheetData("用户统计");
        sd.put("name", "张三");
        sd.put("age", 13);

        //每个sheet页加入100条测试数据
        //注意这里可以加入pojo也可以直接使用map,理论上map在这里效率更高一些
        UmUserGatherPojo vo=new  UmUserGatherPojo();
        vo.setMonth("201909");
        vo.setUserRegisterNum(100);
        vo.setUserActiveNum(65);
        sd.addData(vo);
        UmUserGatherPojo vo2=new  UmUserGatherPojo();
        vo2.setMonth("201908");
        vo2.setUserRegisterNum(90);
        vo2.setUserActiveNum(null);
        sd.addData(vo2);




        try {
            
      ExcelUtils.writeData(model, new FileOutputStream(f) ,sd);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }
}

 

package com.unionpay.cqupay.entity;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author adam
 * @version 1.0
 * @date 2019-9-23
 */
public class SheetData {

    /**
     * sheet页中存储 #{key} 的数据
     */
    private Map<String, Object> map = new HashMap<String, Object>();

    /**
     * 列表数据存储 sheet页中替换${key} 并以列为单位向下赋值
     */
    private List<Object>  datas = new LinkedList<Object>();

    private String name ;
    private String timeFormat;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public String getTimeFormat() {
        return timeFormat;
    }

    public void setTimeFormat(String timeFormat) {
        this.timeFormat = timeFormat;
    }

    public SheetData(String name) {
        super();
        this.name = name;
    }

    public SheetData(String name,String timeFormat) {
        super();
        this.name = name;
        this.timeFormat=timeFormat;
    }
    public void put(String key , Object value) {
        map.put(key, value);
    }

    public void remove(String key) {
        map.remove(key);
    }

    public Object get(String key) {
        return map.get(key);
    }

    /**
     * 清理map存储和数据存储
     */
    public void clear() {
        map.clear();
        datas.clear();
    }

    public void addData(Object t){
        datas.add(t);
    }

    public void addDatas(List<? extends Object> list) {
        datas.addAll(list);
    }


    public List<Object>  getDatas() {
        return datas;
    }

}

 

其中用到了CommonUtils公共类中封装的几个静态方法:

Java代码  
/** 
   * 从实体中解析出字段数据 
   * @param data 可能为pojo或者map 从field中解析 
   * @param field 字段名称 
   * @return 
   */  
     
  @SuppressWarnings("rawtypes")  
public static Object getValue(Object data , String field) {  
        
      if(data instanceof Map) {  
            
          Map map = (Map) data;  
          return map.get(field);  
      }  
      try {  
            
          String method = "get" + field.substring(0 , 1).toUpperCase() + field.substring(1);  
            
          Method m = data.getClass().getMethod(method, null);  
            
          if(m != null) {  
              return m.invoke(data, null);  
          }  
            
      } catch (Exception e) {  
          // TODO Auto-generated catch block  
         // e.printStackTrace();  
          logger.error("data invoke error , data:" + data + " , key:" + field);  
          return null;  
      }   
        
        
      return null ;  
        
  }  
    
  /** 
   * 判断是否为数字 
   * @param v 
   * @return 
   */  
  public static boolean isNumber(Object v) {  
        
      if(v == null) return false;   
        
      if(v instanceof Number) {  
          return true ;  
      } else if(v.toString().matches("^\\d+$")) {  
          return true ;  
      } else if(v.toString().matches("^-?\\d+\\.?\\d+$")) {  
          return true ;  
      } else {  
          try{  
              Double.parseDouble(v.toString());  
              return true ;  
          }catch(Exception e) {  
              return false;  
          }  
           
            
      }  
        
  }  
  
/** 
   * 返回 #{} 或者 ${} 中包含的值 
   * @param str 
   * @param type 
   * @return eg:#{name} ${ages}  
   */  
  public static String[] getWildcard(String str ) {  
        
     List<String> list = new ArrayList<String>();  
       
     int start = 0;  
     while(start < str.length() && start >= 0) {  
           
         start = str.indexOf("{", start);  
           
         int end = str.indexOf("}", start);  
         if(start > 0) {  
             String wc = str.substring(start - 1 , end + 1);  
               
             list.add(wc);  
         }  
          
         if(start < 0) break ;  
           
         start = end + 1;  
           
     }  
       
     return list.toArray(new String[0]);  
        
  }  

 

下面开始写测试,编辑一个excel模板:



 

 

编写一个测试数据实体(实际使用Map效率会更好一些):

Java代码  
 
public class TestData {  
    private int id ;  
    private int p_id ;  
    private String name ;  
    public int getId() {  
        return id;  
    }  
    public void setId(int id) {  
        this.id = id;  
    }  
    public int getP_id() {  
        return p_id;  
    }  
    public void setP_id(int p_id) {  
        this.p_id = p_id;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public TestData(int id, int p_id, String name) {  
        super();  
        this.id = id;  
        this.p_id = p_id;  
        this.name = name;  
    }  
      
      
}  

 

 

编写测试类,注意模型test.xlsx 已经放入src/model/ 目录下:

Java代码  
public class TestExcel2 {  
      
      
  
    public static void main(String[] args) {  
          
        //获取模板   
        String model = "test.xlsx" ;   
        File f = new File("e:/test.xlsx");  
  
        SheetData[] sds = new SheetData[5];  
          
        //创建5个数据sheet  
        for( int i = 0 ; i < 5 ; i++) {  
            SheetData sd = new SheetData("测试" + i);  
            sd.put("name", "张三" + i);  
            sd.put("age", 13);  
              
            //每个sheet页加入100条测试数据  
            //注意这里可以加入pojo也可以直接使用map,理论上map在这里效率更高一些  
            for(int j = 0 ; j < 100 ; j++) {  
                TestData td = new TestData(j, j * -1, "t" + j);  
                sd.addData(td);;  
            }  
               
            sds[i] = sd ;  
        }  
           
               
        try {  
            ExcelUtils.writeData(model, new FileOutputStream(f) ,sds);  
        } catch (FileNotFoundException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
           
          
  
    }  
  

 

 
 

输出文件如下:



 



 

 

  模板中单元格的样式会延续复制,包含颜色,宽度等等。有兴趣大家可以一起扩展一下。

 

作者封装了ExcelUtil.createFile()方法。在项目中可以灵活调用。如下代码:

    public boolean exportUersStatistics( String email,Integer userId) throws CetcBigDataException {


        List<UmUserGatherPojo> list=this.findPojo(userId) ;
        SheetData sd = new SheetData("用户统计表" );

        for (UmUserGatherPojo vo : list) {
            sd.addData(vo);
        }

        File file=TemplateExcelUtil.createFile("template_user.xlsx",userId+"user.xlsx",sd);

        boolean sendResult = mailUtil.sendMail(email, file.getPath(), "用户统计表(月报)", "每月统计注册用户和活跃用户");
        if (sendResult) {
            return  true;
        } else {
            throw new  CetcBigDataException("发送邮件失败");
        }



    }

 

 

 

参考 https://www.iteye.com/blog/jjxliu306-2383610

 

posted on 2019-09-23 14:34  yuluoxingkong  阅读(3430)  评论(0编辑  收藏  举报