
package com.house365.web.util;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.hssf.usermodel.HSSFCell;
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.HSSFColor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.xssf.usermodel.*;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Excel文件导出工具类
 *
 * @author huaqingchun
 * @version 1.0
 * @date
 */
public class ExcelUtil {

    private static final int PAGESIZE = 1000;
    private static final String DATEFORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * 向浏览器客户端输出Excel文件
     *
     * @param fileName
     * @param sheetName
     * @param titles
     * @param recordList
     * @param response
     */
    public static void exportExcel(String fileName, String sheetName, String[] titles, List<List<Object>> recordList,
                                   HttpServletResponse response) {
        exportExcel(fileName, sheetName, PAGESIZE, titles, recordList, response);
    }

    /**
     * 向浏览器客户端输出Excel文件
     *
     * @param fileName
     * @param sheetName
     * @param pageSize
     * @param titles
     * @param recordList
     * @param response
     */
    public static void exportExcel(String fileName, String sheetName, int pageSize, String[] titles,
                                   List<List<Object>> recordList, HttpServletResponse response) {
        XSSFWorkbook workBook = new XSSFWorkbook();
        XSSFCellStyle headStyle = getHeadStyle(workBook);
        XSSFCellStyle bodyStyle = getBodyStyle(workBook);
        XSSFSheet sheet = null;
        int sheetCount = (int) Math.ceil(Double.valueOf(recordList.size()) / pageSize);
        if (sheetCount == 0) {
            sheet = workBook.createSheet(sheetName);
            XSSFRow headRow = sheet.createRow(0);
            XSSFCell cell = null;
            if (titles != null) {
                for (int j = 0; j < titles.length; j++) {
                    cell = headRow.createCell(j);
                    cell.setCellStyle(headStyle);
                    cell.setCellValue(titles[j]);
                }
            }
        }
        for (int i = 0; i < sheetCount; i++) {
            sheet = workBook.createSheet((i == 0) ? sheetName : (sheetName + "(" + (i + 1) + ")"));
            //设置第一行表头的各个列标题
            XSSFRow headRow = sheet.createRow(0);
            XSSFCell cell = null;
            if (titles != null) {
                for (int j = 0; j < titles.length; j++) {
                    cell = headRow.createCell(j);
                    cell.setCellStyle(headStyle);
                    cell.setCellValue(titles[j]);
                }
            }
            //设置第二行开始的动态列数据
            if (CollectionUtils.isNotEmpty(recordList)) {
                int start = i * pageSize;
                int end = (i + 1) * pageSize;
                end = end > recordList.size() ? recordList.size() : end;
                for (int j = start, row = 1; j < end; j++, row++) {
                    XSSFRow bodyRow = sheet.createRow(row);
                    List<Object> record = recordList.get(j);
                    for (int k = 0; k < record.size(); k++) {
                        Object object = record.get(k);
                        if (object == null) {
                            object = "";
                        }
                        String value = null;
                        if (object instanceof java.util.Date) {
                            value = DateTimeUtils.getDateString((Date) object, DATEFORMAT);
                        } else {
                            value = String.valueOf(object);
                        }
                        cell = bodyRow.createCell(k);
                        cell.setCellStyle(bodyStyle);
                        cell.setCellValue(value);
                    }
                }
            }
        }
        //输出文件并关闭输出流
        OutputStream os = null;
        try {
            if (!fileName.toLowerCase().endsWith(".xlsx") && !fileName.toLowerCase().endsWith(".xls")) {
                fileName += ".xlsx";
            }
            //fileName = new String(fileName.getBytes("UTF-8"), "ISO8859_1");
            fileName = URLEncoder.encode(fileName, "UTF-8");
            if (fileName.length() > 15) {
                String guessCharset = "gb2312";
                fileName = new String(fileName.getBytes(guessCharset), "ISO8859-1");
            }
            // fileName = new String(fileName.getBytes("gb2312"), "ISO8859_1");
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "no-store");
            response.setDateHeader("Expires", 0);
            //response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            response.setContentType("application/octet-stream; charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName);
            //response.setContentType("application/octet-stream; charset=gb2312");
            os = response.getOutputStream();
            workBook.write(os);
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 设置表头的单元格样式
     *
     * @param workBook
     * @return
     */
    private static XSSFCellStyle getHeadStyle(XSSFWorkbook workBook) {
        // 创建单元格样式
        XSSFCellStyle cellStyle = workBook.createCellStyle();
        // 设置单元格的背景颜色为淡蓝色
        cellStyle.setFillForegroundColor(HSSFColor.PALE_BLUE.index);
        cellStyle.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
        // 设置单元格左对齐
        cellStyle.setAlignment(XSSFCellStyle.ALIGN_LEFT);
        // 设置单元格垂直居中对齐
        // cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
        // 创建单元格内容显示不下时自动换行
        // cellStyle.setWrapText(true);
        // 设置单元格字体样式
        // XSSFFont font = wb.createFont();
        // // 设置字体加粗
        // font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
        // font.setFontName("宋体");
        // font.setFontHeight((short) 200);
        // cellStyle.setFont(font);
        // 设置单元格边框为细线条
        cellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN);
        return cellStyle;
    }

    /**
     * 设置表体的单元格样式
     *
     * @param workBook
     * @return
     */
    private static XSSFCellStyle getBodyStyle(XSSFWorkbook workBook) {
        // 创建单元格样式
        XSSFCellStyle cellStyle = workBook.createCellStyle();
        // 设置单元格左对齐
        cellStyle.setAlignment(XSSFCellStyle.ALIGN_LEFT);
        // // 设置单元格垂直居中对齐
        // cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
        // // 创建单元格内容显示不下时自动换行
        // cellStyle.setWrapText(true);
        // // 设置单元格字体样式
        // XSSFFont font = wb.createFont();
        // // 设置字体加粗
        // font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
        // font.setFontName("宋体");
        // font.setFontHeight((short) 200);
        // cellStyle.setFont(font);
        // 设置单元格边框为细线条
        cellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN);
        return cellStyle;
    }

    /**
     * 读取excel内容
     *
     * @param filePath 文件路径
     * @return List<List<Object>>
     * @throws IOException
     * @author zhaodeshan
     * @version [v1.0.0, 2015年2月25日]
     * @since [产品/模块版本](可选)
     */
    public static List<List<Object>> importExcel(String filePath) throws IOException {
        InputStream in = new FileInputStream(filePath);
        return importExcel(in);
    }

    /**
     * 导入Excel文件
     *
     * @param is 文件输入流
     * @return List<List<Object>>
     * @throws IOException,IllegalArgumentException
     * @author zhaodeshan
     * @version [版本号, 2015年3月9日]
     * @since [产品/模块版本](可选)
     */
    public static List<List<Object>> importExcel(InputStream is) throws IOException {
        if (!is.markSupported()) {
            is = new PushbackInputStream(is, 8);

            if (POIFSFileSystem.hasPOIFSHeader(is)) {
                return importExcelHSSF(is);
            } else if (POIXMLDocument.hasOOXMLHeader(is)) {
                return importExcelXSSF(is);
            }
        }

        throw new IllegalArgumentException("excel版本无法解析");
    }

    public static List<List<Object>> importExcelSecond(InputStream is) throws IOException {
        is = new PushbackInputStream(is, 8);

        if (POIFSFileSystem.hasPOIFSHeader(is)) {
            return importExcelHSSF(is);
        } else {
            return importExcelXSSF(is);
        }

    }

    /**
     * 读取excel内容
     *
     * @param is 文件流
     * @return List<List<Object>>
     * @author zhaodeshan
     * @version [v1.0.0, 2015年2月25日]
     * @since [产品/模块版本](可选)
     */
    public static List<List<Object>> importExcelXSSF(InputStream is) {
        DecimalFormat df = new DecimalFormat("0");
        List<List<Object>> recordList = new ArrayList<List<Object>>();
        try {
            XSSFWorkbook wbs = new XSSFWorkbook(is);
            XSSFSheet sheet = wbs.getSheetAt(0);
            int rowNum = sheet.getLastRowNum() + 1;
            for (int j = 0; j < rowNum; j++) {
                XSSFRow row = sheet.getRow(j);
                if (null != row) {
                    List<Object> rowList = new ArrayList<Object>();
                    for (int k = 0; k < row.getLastCellNum(); k++) {
                        XSSFCell cell = row.getCell(k);
                        if (null != cell) {
                            switch (cell.getCellType()) {
                                case XSSFCell.CELL_TYPE_NUMERIC: // 数字
                                    rowList.add(df.format(cell.getNumericCellValue()));
                                    break;
                                case XSSFCell.CELL_TYPE_STRING: // 字符串
                                    rowList.add(cell.getStringCellValue());
                                    break;
                                case XSSFCell.CELL_TYPE_BOOLEAN: // Boolean
                                    rowList.add(cell.getBooleanCellValue());
                                    break;
                                case XSSFCell.CELL_TYPE_FORMULA: // 公式
                                    rowList.add(cell.getCellFormula());
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    recordList.add(rowList);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return recordList;
    }

    /**
     * 读取excel内容
     *
     * @param is 文件流
     * @return List<List<Object>>
     * @author zhaodeshan
     * @version [v1.0.0, 2015年2月25日]
     * @since [产品/模块版本](可选)
     */
    public static List<List<Object>> importExcelHSSF(InputStream is) {
        DecimalFormat df = new DecimalFormat("0");
        List<List<Object>> recordList = new ArrayList<List<Object>>();
        try {
            HSSFWorkbook wbs = new HSSFWorkbook(is);
            HSSFSheet sheet = wbs.getSheetAt(0);
            int rowNum = sheet.getLastRowNum() + 1;
            for (int j = 0; j < rowNum; j++) {
                HSSFRow row = sheet.getRow(j);
                if (null != row) {
                    List<Object> rowList = new ArrayList<Object>();
                    for (int k = 0; k < row.getLastCellNum(); k++) {
                        HSSFCell cell = row.getCell(k);
                        if (null != cell) {
                            switch (cell.getCellType()) {
                                case HSSFCell.CELL_TYPE_NUMERIC: // 数字
                                    rowList.add(df.format(cell.getNumericCellValue()));
                                    break;
                                case HSSFCell.CELL_TYPE_STRING: // 字符串
                                    rowList.add(cell.getStringCellValue());
                                    break;
                                case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
                                    rowList.add(cell.getBooleanCellValue());
                                    break;
                                case HSSFCell.CELL_TYPE_FORMULA: // 公式
                                    rowList.add(cell.getCellFormula());
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    recordList.add(rowList);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return recordList;
    }

    public static void main(String[] args) throws IOException {
        System.out.println(importExcel("E:/test/newHouse.xlsx"));
        System.out.println(importExcel("E:/test/newHouse.xls"));
        System.out.println(importExcel("E:/test/test.xlsx"));
        System.out.println(importExcel("E:/test/test.xls"));
    }
}
