导出Excel工具类(一个主表多个明细表)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了导出Excel工具类(一个主表多个明细表)相关的知识,希望对你有一定的参考价值。

①ExcelData.java(Excel数据封装类)

package com.kentra.util;

import java.util.List;
import java.util.Map;
/**
 * 
 * 描述:为导出Excel文件封装数据
 * 封装Excel文件数据注意事项:
 * 1.heads(标题行):是一个字符串, 标题与标题之间以逗号分隔如:hears="学号,姓名,性别"
 * 2.data: 表示:主数据集合,data是个字符串集合,包含了所有主数据,集合中的一个字符串元素就是Excel表格中的一行记录;
 * 列数据项与列数项之间用冒号分隔, 如果某个列数据项值为空, 就用null代替,如: data.add("001:老李:null:15056786789:null");
 * 3.assoceData 关联数据集合,主数据集合的字符串元素的下标在关联数据集合就是对应的关联数据.是个双list集合字符串,包含了所有主数据的关联数据集合,
 * 它的每一个元素就是某一行主数据的关联数据集合,如果主表数据没有关联数据,那么它的关联数据,就用null代替
 * 4.widthAndHeiht map的key 表示列的位置,map的value 表示列的宽度, 如:widthAndHeiht.put(3, 5000); 第4列宽度为5000英寸
 * 5.length 合并单元格的个数
 * @author sunxuefeng 2017年7月28日 下午5:13:35
 * @version 1.0
 */

public class ExcelData {

    private String                excelName;    // Excel文件名称
    private String                sheetName;    // 工作表的名称
    private String                heads;        // 标题行
    private List<String>          data;         // 主数据
    private Map<Integer, Integer> widthAndHeiht;// 单元格的宽高,如:xSheet.setColumnWidth(10,1000);
                                                // 10表示:map的key, //
                                                // 10,1000表示:map的value
    private List<List<String>>    assoceData;   // 关联数据行,一张主表对应一个从表,当有多个明细表的时候,那么就全部拼接到这个从表中即可。
    private int                   length;       // 合并单元格的个数 没有就不用填



    public String getHeads() {
        return heads;
    }



    public void setHeads(String heads) {
        this.heads = heads;
    }



    public int getLength() {
        return length;
    }



    public void setLength(int length) {
        this.length = length;
    }



    public List<List<String>> getAssoceData() {
        return assoceData;
    }



    public void setAssoceData(List<List<String>> assoceData) {
        this.assoceData = assoceData;
    }



    public String getExcelName() {
        return excelName;
    }



    public void setExcelName(String excelName) {
        this.excelName = excelName;
    }



    public String getSheetName() {
        return sheetName;
    }



    public void setSheetName(String sheetName) {
        this.sheetName = sheetName;
    }



    public List<String> getData() {
        return data;
    }



    public void setData(List<String> data) {
        this.data = data;
    }



    public Map<Integer, Integer> getWidthAndHeiht() {
        return widthAndHeiht;
    }



    public void setWidthAndHeiht(Map<Integer, Integer> widthAndHeiht) {
        this.widthAndHeiht = widthAndHeiht;
    }

}

②ExportExcelUtils.java(导出工具类)

package com.kentra.util;

import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 
 * 描述:导出excel文件模板
 * 
 * @author sunxuefeng 2017年7月28日 上午11:20:48
 * @version 1.0
 */
public class ExportExcelUtils {
    private static final Logger LOG = Logger.getLogger(ExportExcelUtils.class);



    /**
     * 
     * 描述:输出Excel文件
     * 
     * @param response
     * @param excelData
     *            为导出Excel文件封装数据
     * @author sunxuefeng 2017年7月31日 上午9:58:10
     * @version 1.0
     * @throws Exception
     */
    public static void exportFile(HttpServletResponse response, ExcelData excelData) {
        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            response.setHeader("Content-disposition",
                    "attachment; filename = " + URLEncoder.encode(excelData.getExcelName() + ".xlsx", "UTF-8"));
            response.setContentType("application/octet-streem");
            List<List<String>> assoceData = excelData.getAssoceData();
            XSSFWorkbook workbook = null;
            if (assoceData != null && assoceData.size() > 0) {
                workbook = setSheetContent(excelData);
            } else {
                workbook = setSheetContentNO(excelData);
            }
            workbook.write(outputStream);
        } catch (Exception e) {
            LOG.error("Excel文件导出失败:" + e.getMessage());
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }



    /**
     * 
     * 描述: set Sheet标题行
     * 
     * @param xWorkbook
     * @param xSheet
     * @param headers标题行
     * @author sunxuefeng 2017年7月28日 下午1:13:36
     * @version 1.0
     */
    private static void setSheetHeader(XSSFWorkbook xWorkbook, XSSFSheet xSheet, String headers) {
        // 设置样式
        CellStyle cs = xWorkbook.createCellStyle();
        // 设置水平垂直居中
        cs.setAlignment(CellStyle.ALIGN_CENTER);
        cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        // 设置字体
        Font headerFont = xWorkbook.createFont();
        headerFont.setFontHeightInPoints((short) 12);
        headerFont.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
        headerFont.setFontName("宋体");
        cs.setFont(headerFont);
        cs.setWrapText(false);// 是否自动换行
        XSSFRow xRow0 = xSheet.createRow(0);
        String[] header = headers.split(",");
        for (int i = 0, length = header.length; i < length; i++) {
            XSSFCell xCell = xRow0.createCell(i);
            xCell.setCellStyle(cs);
            xCell.setCellValue(header[i]);
        }
    }



    /***
     * 
     * 描述: 设置Sheet页内容(有关联数据)
     * 
     * @param excelData
     * @return
     * @author sunxuefeng 2017年7月31日 上午9:59:24
     * @version 1.0
     */
    private static XSSFWorkbook setSheetContent(ExcelData excelData) {
        XSSFWorkbook xWorkbook = new XSSFWorkbook();
        XSSFSheet xSheet = xWorkbook.createSheet(excelData.getSheetName());
        Map<Integer, Integer> map = excelData.getWidthAndHeiht();
        CellStyle cs = xWorkbook.createCellStyle(); // 设置样式
        cs.setAlignment(CellStyle.ALIGN_CENTER);
        cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        cs.setWrapText(true); // 是否自动换行。加入\n 就会换行, eg:电子科技大学2 \n 北京大学
        setSheetHeader(xWorkbook, xSheet, excelData.getHeads());
        if (map != null && map.size() > 0) { // 设置单元格的宽高
            for (Integer key : map.keySet()) {
                xSheet.setColumnWidth(key, map.get(key));
            }
        }
        List<String> data = excelData.getData();
        List<List<String>> assoceDatas = excelData.getAssoceData();
        if (data != null && data.size() > 0) {
            int l = 0, ii = 0;
            for (int i = 0; i < data.size(); i++) {
                List<String> assoceData = assoceDatas.get(i);
                int assoceDataSize = 0;
                boolean assoceDataFlag = false;
                if (assoceData != null && assoceData.size() > 0) {
                    assoceDataSize = assoceData.size();
                    assoceDataFlag = true;
                    if (i == 0) {
                        ii = 0;
                        l = assoceDataSize;
                    } else {
                        ii = l;
                        l += assoceDataSize;
                    }
                } else {
                    if (i == 0) {
                        ii = 0;
                        l = 1;
                    } else {
                        ii = l;
                        l += 1;
                    }
                }
                for (int k = ii, m = 0, lengths = l; k < lengths; k++, m++) {// 控制行行:
                    XSSFRow xRow = xSheet.createRow(k + 1);
                    int j = 0;
                    j = setValue(j, 0, data.get(i), xRow, cs);// 设置主数据
                    int length = data.get(i).split(":").length;
                    if (assoceDataFlag) {
                        setValue(j, length, assoceData.get(m), xRow, cs);// 设置关联数据
                    }
                }
                if (assoceDatas.size() >= 1) { // 合并单元格
                    for (int m = 0; m < excelData.getLength(); m++) {
                        if (assoceDataFlag) {
                            int endRows = xSheet.getLastRowNum();
                            int startRow = endRows - assoceDataSize + 1;
                            xSheet.addMergedRegion(new CellRangeAddress(startRow, endRows, m, m));
                        }
                    }
                }
            }
        }
        return xWorkbook;
    }



    /***
     * 
     * 描述: 设置Sheet页内容(无关联数据)
     * 
     * @param excelData
     * @return
     * @author sunxuefeng 2017年7月31日 上午9:59:24
     * @version 1.0
     */
    private static XSSFWorkbook setSheetContentNO(ExcelData excelData) throws Exception {
        XSSFWorkbook xWorkbook = new XSSFWorkbook();
        XSSFSheet xSheet = xWorkbook.createSheet(excelData.getSheetName());
        Map<Integer, Integer> map = excelData.getWidthAndHeiht();
        CellStyle cs = xWorkbook.createCellStyle(); // 设置样式
        cs.setAlignment(CellStyle.ALIGN_CENTER);
        cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
//        cs.setWrapText(false); // 是否自动换行
        cs.setWrapText(true); // 是否自动换行
        setSheetHeader(xWorkbook, xSheet, excelData.getHeads());
        if (map != null && map.size() > 0) { // 设置单元格的宽
            for (Integer key : map.keySet()) {
                xSheet.setColumnWidth(key, map.get(key));
            }
        }
        List<String> data = excelData.getData();
        if (data != null && data.size() > 0) {
            for (int i = 0; i < data.size(); i++) {
                XSSFRow xRow = xSheet.createRow(i + 1);
                int j = 0;
                j = setValue(j, 0, data.get(i), xRow, cs);// 设置主数据
            }
        }
        return xWorkbook;
    }



    /**
     * 
     * 描述:为单元格设置值
     * 
     * @author sunxuefeng 2017年8月1日 上午9:45:36
     * @version 1.0
     */
    private static int setValue(int j, int i, String data, XSSFRow xRow, CellStyle cs) {
        String[] strings = data.split(":");
        for (; j < strings.length + i; j++) {
            String dString = strings[j - i];
            if (dString != null && !dString.equals("") && !dString.equals("null")) {
                XSSFCell xCell = xRow.createCell(j);
                xCell.setCellStyle(cs);
                xCell.setCellValue(dString);
            }
        }
        return j;
    }
}

③导出示例(当有多个明细表时,都拼接到从表后面)

/**
	 *测试导出员工
	 * 
	 */
	@RequestMapping(value="/ExportExcel")
	public void ExportExcel(HttpServletResponse response)throws Exception{
		ExcelData excelData = new ExcelData();
		excelData.setExcelName("员工信息表");
		excelData.setSheetName("员工信息表");
		excelData.setHeads("序号,姓名,性别,年龄,学校,毕业年份,学分,家庭成员,年龄");
		//列宽
		Map<Integer, Integer> widthAndHeiht = new HashMap<>();
		widthAndHeiht.put(0, 2000);
		widthAndHeiht.put(1, 3000);
		widthAndHeiht.put(2, 3000);
		widthAndHeiht.put(4, 8000);
		excelData.setWidthAndHeiht(widthAndHeiht);
		//主表
		String data1 = "1,李建波,null,26";
		String data2 = "2,李雨锋,男,20";
		String data3 = "3,魏文莹,null,null";
		List<String> data = new ArrayList<>();
		data.add(data1);
		data.add(data2);
		data.add(data3);
		excelData.setData(data);
		//合并单元格	
		excelData.setLength(2);
		//关联明细表
		List<List<String>>    assoceData = new ArrayList<>();
		//教育明细
		String jioayu1 = "四川大学,2017,5,父亲,60";
		String jioayu2 = "电子科技大学,2015,4,母亲,55";
		String jioayu33 = "null,null,null,妻子,25";
		List<String> jiaoyulist1 = new ArrayList<>();
		jiaoyulist1.add(jioayu1);
		jiaoyulist1.add(jioayu2);
		jiaoyulist1.add(jioayu33);
		String jioayu3 = "四川大学2,2017,null";
		String jioayu4 = "电子科技大学2 \n 北京大学,2015,4";
		List<String> jiaoyulist2 = new ArrayList<>();
		jiaoyulist2.add(jioayu3);
		jiaoyulist2.add(jioayu4);
		//
		assoceData.add(jiaoyulist1);
		assoceData.add(null);
		assoceData.add(jiaoyulist2);
		excelData.setAssoceData(assoceData);
		//导出
		ExportExcelUtils.exportFile(response, excelData);
		
	}

注意事项:

导出Excel的时候,我们可能需要某一个单元格中的内容自动换行,那么我们可以在需要换行的地方拼接一个 “\n” 那么导出数据就会换行。

该工具类主要是为了导出员工信息表。一个主表多个明细表。比如一个员工有多条工作经历,有多个家庭成员,有多个证件等。

(二)、如何手动实现页面可选择特定字段导出。

我们的思路是页面勾选哪几个字段,我们就拼接哪几个字段然后导出。表头名字来自于选择的复选框的text();内容则通过每个字段对应的value值作为下标去从一条记录(数组)中去获取对应下标的值,然后进行拼接字符串。

技术分享

<div style="padding-top:10px">
		<div>
		<!-- 修改,将span加在了后面-->
		<input type="checkbox" value="1" name="staffinfo_checkbox"/><span>部门</span>
		<input type="checkbox" value="2" name="staffinfo_checkbox"/><span>姓名</span>
		<input type="checkbox" value="3" name="staffinfo_checkbox"/><span>性别</span>
		<input type="checkbox" value="4" name="staffinfo_checkbox"/><span>手机号</span>
		<input type="checkbox" value="5" name="staffinfo_checkbox"/><span>民族</span>
		<input type="checkbox" value="6" name="staffinfo_checkbox"/><span>籍贯</span>				
		<input type="checkbox" value="7" name="staffinfo_checkbox"/><span>出生地</span>
		<input type="checkbox" value="8" name="staffinfo_checkbox"/><span>出生日期</span>
		<input type="checkbox" value="9" name="staffinfo_checkbox"/><span>年龄</span>
</div>


本文出自 “JianBo” 博客,转载请与作者联系!

以上是关于导出Excel工具类(一个主表多个明细表)的主要内容,如果未能解决你的问题,请参考以下文章

怎样让excel从金蝶中抓取数据

Java 通过Xml导出Excel文件,Java Excel 导出工具类,Java导出Excel工具类

EXCEL表格中如何将最新录入的一行数据导入另一个模板EXCEL中

使用While循环导出Excel

hutool工具导出excel代码示例

hutool工具导出excel代码示例