package com.ads.common.base;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.ads.common.data.GetPictureConfigInData;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.util.HtmlUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static cn.hutool.core.date.DatePattern.PURE_DATE_PATTERN;

/**
 * 利用开源组件POI动态导出EXCEL文档
 *
 * @version v1.0
 * @param <T> 应用泛型，代表任意一个符合javabean风格的类
 *            注意这里为了简单起见，boolean型的属性xxx的get器方式为getXxx(),而不是isXxx()
 */
public class ExportExcel<T> implements ExportExcelInterface<T> {



	private static Pattern NUMBER_PATTERN = Pattern.compile("^//d+(//.//d+)?$");

	/**
	 * 这是一个通用的方法，利用了JAVA的反射机制，可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上
	 *
	 *
	 * @param headers 表格属性列名数组
	 * @param dataset 需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。此方法支持的
	 *            javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据)
	 * @param out 与输出设备关联的流对象，可以将EXCEL文档导出到本地文件或者网络中
	 * @param pattern 如果有时间数据，设定输出格式。默认为"yyy-MM-dd"
	 */
	@SuppressWarnings({ "deprecation", "rawtypes", "unchecked", "resource" })
	@Override
	public void exportExcel(String[] headers,Collection<T> dataset, OutputStream out, String pattern) throws Exception {
		// 声明一个工作薄

		XSSFWorkbook workbook = new XSSFWorkbook();
		// 生成一个表格
		XSSFSheet sheet = workbook.createSheet("sheet1");
		// 设置表格默认列宽度为15个字节
		sheet.setDefaultColumnWidth((short) 15);
		// 生成一个样式
		XSSFCellStyle style = workbook.createCellStyle();
		// 设置这些样式
		style.setFillForegroundColor(IndexedColors.GREEN.getIndex());
		style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);
		style.setBorderRight(BorderStyle.THIN);
		style.setBorderTop(BorderStyle.THIN);
		style.setAlignment(HorizontalAlignment.CENTER);
		// 生成一个字体
		XSSFFont font = workbook.createFont();
		font.setColor(HSSFColor.VIOLET.index);
		font.setFontHeightInPoints((short) 12);
		font.setBold(true);
		// 把字体应用到当前的样式
		style.setFont(font);
		// 生成并设置另一个样式
		XSSFCellStyle style2 = workbook.createCellStyle();
		style2.setFillForegroundColor(IndexedColors.GREEN.getIndex());
		style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		style2.setBorderBottom(BorderStyle.THIN);
		style2.setBorderLeft(BorderStyle.THIN);
		style2.setBorderRight(BorderStyle.THIN);
		style2.setBorderTop(BorderStyle.THIN);
		style2.setAlignment(HorizontalAlignment.CENTER);
		style2.setVerticalAlignment(VerticalAlignment.CENTER);
		// 生成另一个字体
		XSSFFont font2 = workbook.createFont();
		font2.setBold(true);
		// 把字体应用到当前的样式
		style2.setFont(font2);

		// 产生表格标题行
		XSSFRow row = sheet.createRow(0);
		for (int i = 0; i < headers.length; i++) {
			XSSFCell cell = row.createCell(i);
			cell.setCellStyle(style);
			XSSFRichTextString text = new XSSFRichTextString(headers[i]);
			cell.setCellValue(text);
		}
		int index = 0;
		//副标题行
		/*if(headers2!=null){
			HSSFRow row2 = sheet.createRow(1);
			for (int i = 0; i < headers.length; i++) {
				HSSFCell cell2 = row2.createCell(i);
				cell2.setCellStyle(style);
				HSSFRichTextString text = new HSSFRichTextString(headers2[i]);
				cell2.setCellValue(text);
			}
			index ++;
		}*/

		// 遍历集合数据，产生数据行
		Iterator<T> it = dataset.iterator();
		XSSFFont font3 = workbook.createFont();
		font3.setColor(HSSFColor.BLUE.index);
		while (it.hasNext()) {
			index++;
			row = sheet.createRow(index);
			T t = (T) it.next();
			// 利用反射，根据javabean属性的先后顺序，动态调用getXxx()方法得到属性值
			Field[] fields = t.getClass().getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				XSSFCell cell = row.createCell(i);
				cell.setCellStyle(style2);
				Field field = fields[i];
				String fieldName = field.getName();
				String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
				Class tCls = t.getClass();
				Method getMethod = tCls.getMethod(getMethodName, new Class[] {});
				Object value = getMethod.invoke(t, new Object[] {});
				// 判断值的类型后进行强制类型转换
				String textValue = null;
				if (value instanceof Date) {
					Date date = (Date) value;
					textValue = DateUtil.format(date, DatePattern.NORM_DATE_PATTERN);
				} else {
					// 其它数据类型都当作字符串简单处理
					if (value == null) {
						textValue = "";
					} else {
						textValue = HtmlUtils.htmlUnescape(value.toString());
					}

				}
				// 如果不是图片数据，就利用正则表达式判断textValue是否全部由数字组成
				if (textValue != null) {
					Matcher matcher = NUMBER_PATTERN.matcher(textValue);
					if (matcher.matches()) {
						// 是数字当作double处理
						cell.setCellValue(Double.parseDouble(textValue));
					} else {
						XSSFRichTextString richString = new XSSFRichTextString(textValue);
						richString.applyFont(font3);
						cell.setCellValue(richString);
					}
				}
			}

		}
		workbook.write(out);
	}

	@Override
	public void exportExcel2(String title, String[] headers1, String[] headers2, Collection<T> dataset, OutputStream out, String pattern) throws Exception {
		// 声明一个工作薄
		HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
		// 生成一个表格
		HSSFSheet sheet = hssfWorkbook.createSheet(title);
		//指定合并开始行、合并结束行 合并开始列、合并结束列
		CellRangeAddress cellRangeAddress = new CellRangeAddress(0,2,0,10);
		//添加要合并地址到表格
		sheet.addMergedRegion(cellRangeAddress);
		//创建行，指定起始行号，从0开始
		HSSFRow row = sheet.createRow(0);
		//创建单元格，指定起始列号，从0开始
		HSSFCell cell = row.createCell(0);
		//设置单元格内容
		cell.setCellValue(title);
		//创建样式对象
		HSSFCellStyle style = hssfWorkbook.createCellStyle();
		style.setAlignment(HorizontalAlignment.CENTER);
		style.setVerticalAlignment(VerticalAlignment.CENTER);
		style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		// 生成一个字体
		HSSFFont font = hssfWorkbook.createFont();
		font.setFontHeightInPoints((short) 20);
		// 把字体应用到当前的样式
		style.setFont(font);
		//为指定单元格设定样式
		cell.setCellStyle(style);
		//创建样式对象
		HSSFCellStyle style2 = hssfWorkbook.createCellStyle();
		style2.setAlignment(HorizontalAlignment.CENTER);
		style2.setVerticalAlignment(VerticalAlignment.CENTER);
		style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		style2.setBorderBottom(BorderStyle.THIN);
		style2.setBorderTop(BorderStyle.THIN);
		style2.setBorderLeft(BorderStyle.THIN);
		style2.setBorderRight(BorderStyle.THIN);
		//创建样式对象
		HSSFCellStyle style3 = hssfWorkbook.createCellStyle();
		style3.setAlignment(HorizontalAlignment.CENTER);
		style3.setVerticalAlignment(VerticalAlignment.CENTER);
		style3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		style3.setBorderBottom(BorderStyle.THIN);
		style3.setBorderTop(BorderStyle.THIN);
		style3.setBorderLeft(BorderStyle.THIN);
		style3.setBorderRight(BorderStyle.THIN);
		// 生成一个字体
		HSSFFont font2 = hssfWorkbook.createFont();
		font2.setFontHeightInPoints((short) 12);
		// 把字体应用到当前的样式
		style2.setFont(font2);
		// 产生表格第一个标题行
		HSSFRow row3 = sheet.createRow(6);
		for (int i = 0; i < headers1.length; i++) {
			sheet.setColumnWidth(i+2, sheet.getColumnWidth(i+2)*15/7);
			HSSFCell titleCell = row3.createCell(i+2);
			titleCell.setCellStyle(style2);
			HSSFRichTextString text = new HSSFRichTextString(headers1[i]);
			titleCell.setCellValue(text);
		}
		// 产生表格第二个标题行
		HSSFRow row5 = sheet.createRow(11);
		for (int i = 0; i < headers2.length; i++) {
			HSSFCell titleCell = row5.createCell(i+2);
			titleCell.setCellStyle(style2);
			HSSFRichTextString text = new HSSFRichTextString(headers2[i]);
			titleCell.setCellValue(text);
		}
		// 遍历集合数据，产生第一个标题行对应的数据行
		Iterator<T> it = dataset.iterator();
		while (it.hasNext()) {
			T t = (T) it.next();
			HSSFRow row4 = sheet.createRow(7);
			HSSFRow row6 = sheet.createRow(12);
			// 利用反射，根据javabean属性的先后顺序，动态调用getXxx()方法得到属性值
			Field[] fields = t.getClass().getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				if (i <= 6){
					HSSFCell valueCell = row4.createCell(i+2);
					valueCell.setCellStyle(style3);
					Field field = fields[i];
					String fieldName = field.getName();
					String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
					Class tCls = t.getClass();
					Method getMethod = tCls.getMethod(getMethodName, new Class[] {});
					Object value = getMethod.invoke(t, new Object[] {});
					// 判断值的类型后进行强制类型转换
					String textValue = null;
					if (value instanceof Date) {
						Date date = (Date) value;
						textValue = DateUtil.format(date, DatePattern.NORM_DATE_PATTERN);
					} else {
						// 其它数据类型都当作字符串简单处理
						if (value == null) {
							textValue = "";
						} else {
							textValue = HtmlUtils.htmlUnescape(value.toString());
						}
					}
					// 如果不是图片数据，就利用正则表达式判断textValue是否全部由数字组成
					if (textValue != null) {
						Matcher matcher = NUMBER_PATTERN.matcher(textValue);
						if (matcher.matches()) {
							// 是数字当作double处理
							valueCell.setCellValue(Double.parseDouble(textValue));
						} else {
							HSSFRichTextString richString = new HSSFRichTextString(textValue);
							richString.applyFont(font2);
							valueCell.setCellValue(richString);
						}
					}
				} else {
					HSSFCell valueCell = row6.createCell(i-5);
					valueCell.setCellStyle(style3);
					Field field = fields[i];
					String fieldName = field.getName();
					String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
					Class tCls = t.getClass();
					Method getMethod = tCls.getMethod(getMethodName, new Class[] {});
					Object value = getMethod.invoke(t, new Object[] {});
					// 判断值的类型后进行强制类型转换
					String textValue = null;
					if (value instanceof Date) {
						Date date = (Date) value;
						textValue = DateUtil.format(date, DatePattern.NORM_DATE_PATTERN);
					} else {
						// 其它数据类型都当作字符串简单处理
						if (value == null) {
							textValue = "";
						} else {
							textValue = HtmlUtils.htmlUnescape(value.toString());
						}
					}
					// 如果不是图片数据，就利用正则表达式判断textValue是否全部由数字组成
					if (textValue != null) {
						Matcher matcher = NUMBER_PATTERN.matcher(textValue);
						if (matcher.matches()) {
							// 是数字当作double处理
							valueCell.setCellValue(Double.parseDouble(textValue));
						} else {
							HSSFRichTextString richString = new HSSFRichTextString(textValue);
							richString.applyFont(font2);
							valueCell.setCellValue(richString);
						}
					}
				}
			}
		}

		//药师签名
		HSSFRow row6 = sheet.createRow(14);
		HSSFCell signCell = row6.createCell(2);
		signCell.setCellValue("药师签名：");
		signCell.setCellStyle(style2);

		//打印日期
		HSSFRow row7 = sheet.createRow(15);
		HSSFCell dateCell = row7.createCell(2);
		dateCell.setCellValue("打印日期：");
		dateCell.setCellStyle(style2);
		HSSFCell valueCell = row7.createCell(3);
		valueCell.setCellValue(DateUtil.format(new Date(),PURE_DATE_PATTERN));
		valueCell.setCellStyle(style2);

		hssfWorkbook.write(out);
	}

	/**
	 * 这是一个通用的方法，利用了JAVA的反射机制，可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上
	 *
	 *
	 * @param headers 表格属性列名数组
	 * @param dataset 需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。此方法支持的
	 *            javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据)
	 * @param out 与输出设备关联的流对象，可以将EXCEL文档导出到本地文件或者网络中
	 * @param pattern 如果有时间数据，设定输出格式。默认为"yyy-MM-dd"
	 */
	@SuppressWarnings({ "deprecation", "rawtypes", "unchecked", "resource" })
	@Override
	public void exportExcelInitStyle(String[] headers,Collection<T> dataset, OutputStream out, String pattern) throws Exception {
		// 声明一个工作薄
		XSSFWorkbook workbook = new XSSFWorkbook();
		// 生成一个表格
		XSSFSheet sheet = workbook.createSheet("sheet1");
		// 设置表格默认列宽度为15个字节
		sheet.setDefaultColumnWidth((short) 15);
		// 生成一个样式
		XSSFCellStyle style = workbook.createCellStyle();
		// 设置这些样式
		style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
		style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);
		style.setBorderRight(BorderStyle.THIN);
		style.setBorderTop(BorderStyle.THIN);
		style.setAlignment(HorizontalAlignment.CENTER);
		// 生成一个字体
		XSSFFont font = workbook.createFont();
		font.setColor(HSSFColor.VIOLET.index);
		font.setFontHeightInPoints((short) 12);
		font.setBold(true);
		// 把字体应用到当前的样式
		style.setFont(font);
		// 生成并设置另一个样式
		XSSFCellStyle style2 = workbook.createCellStyle();
		style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
		style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		style2.setBorderBottom(BorderStyle.THIN);
		style2.setBorderLeft(BorderStyle.THIN);
		style2.setBorderRight(BorderStyle.THIN);
		style2.setBorderTop(BorderStyle.THIN);
		style2.setAlignment(HorizontalAlignment.CENTER);
		style2.setVerticalAlignment(VerticalAlignment.CENTER);
		// 生成另一个字体
		XSSFFont font2 = workbook.createFont();
		font2.setBold(true);
		// 把字体应用到当前的样式
		style2.setFont(font2);
		CellRangeAddress callRangeAddress = new CellRangeAddress(0,0,0,36);//起始行,结束行,起始列,结束列

		CellRangeAddress callRangeAddress1 = new CellRangeAddress(1,3,0,0);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress2 = new CellRangeAddress(1,3,1,1);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress3 = new CellRangeAddress(1,3,2,2);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress4 = new CellRangeAddress(1,3,3,3);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress5 = new CellRangeAddress(1,3,4,4);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress6 = new CellRangeAddress(1,3,5,5);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress7 = new CellRangeAddress(1,3,6,6);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress8 = new CellRangeAddress(1,3,7,7);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress9 = new CellRangeAddress(1,3,8,8);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress10 = new CellRangeAddress(1,3,9,9);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress11 = new CellRangeAddress(1,3,10,10);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress12 = new CellRangeAddress(1,3,11,11);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress13 = new CellRangeAddress(1,3,12,12);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress14 = new CellRangeAddress(1,3,13,13);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress15 = new CellRangeAddress(1,3,14,14);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress16 = new CellRangeAddress(1,3,15,15);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress17 = new CellRangeAddress(1,3,16,16);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress18 = new CellRangeAddress(1,1,17,21);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress19 = new CellRangeAddress(2,2,17,18);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress20 = new CellRangeAddress(2,2,19,20);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress21 = new CellRangeAddress(1,3,22,22);//起始行,结束行,起始列,结束列

		CellRangeAddress callRangeAddress22 = new CellRangeAddress(1,3,23,23);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress23 = new CellRangeAddress(1,3,24,24);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress24 = new CellRangeAddress(1,3,25,25);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress25 = new CellRangeAddress(1,3,26,26);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress26 = new CellRangeAddress(1,3,27,27);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress27 = new CellRangeAddress(1,2,28,29);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress28 = new CellRangeAddress(1,2,30,31);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress29 = new CellRangeAddress(1,3,32,32);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress30 = new CellRangeAddress(1,3,33,33);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress31 = new CellRangeAddress(1,3,34,34);//起始行,结束行,起始列,结束列
		CellRangeAddress callRangeAddress32 = new CellRangeAddress(1,3,35,35);//起始行,结束行,起始列,结束列
		//CellRangeAddress callRangeAddress33 = new CellRangeAddress(1,3,36,36);//起始行,结束行,起始列,结束列
		//CellRangeAddress callRangeAddress34 = new CellRangeAddress(1,3,37,37);//起始行,结束行,起始列,结束列

		XSSFRow rowHead = sheet.createRow(0);
		XSSFCell cellHead = rowHead.createCell(0);
		//加载单元格样式
		//标题样式
		cellHead.setCellStyle(style);
		cellHead.setCellValue("促销商品海报");

		// 产生表格标题行
		XSSFRow row = sheet.createRow(1);
		for (int i = 0; i < headers.length; i++) {
			XSSFCell cell = row.createCell(i);
			cell.setCellStyle(style);
			XSSFRichTextString text = new XSSFRichTextString(headers[i]);
			cell.setCellValue(text);
		}
		XSSFRow rowTwo = sheet.createRow(2);
		String[] titleTwo = {"版一ABC","版二DE","版三F"};
		for(int i=0;i<titleTwo.length*2;i = i+2)
		{
			XSSFCell cell2 = rowTwo.createCell(i+17);
			//加载单元格样式
			cell2.setCellStyle(style);
			cell2.setCellValue(titleTwo[i/2]);
		}
		XSSFRow rowThree = sheet.createRow(3);
		String[] titleThree = {"室内","室外","室内","室外","伍缘"};
		for(int i=0;i<titleThree.length;i++)
		{
			XSSFCell cell2 = rowThree.createCell(i+17);
			//加载单元格样式
			cell2.setCellStyle(style);
			cell2.setCellValue(titleThree[i]);
		}
		String[] titlePS = {"直送","配送","直送","配送"};
		for(int i=0;i<titlePS.length;i++)
		{
			XSSFCell cell2 = rowThree.createCell(i+28);
			//加载单元格样式
			cell2.setCellStyle(style);
			cell2.setCellValue(titlePS[i]);
		}
		sheet.addMergedRegion(callRangeAddress);
		sheet.addMergedRegion(callRangeAddress1);
		sheet.addMergedRegion(callRangeAddress2);
		sheet.addMergedRegion(callRangeAddress3);
		sheet.addMergedRegion(callRangeAddress4);
		sheet.addMergedRegion(callRangeAddress5);
		sheet.addMergedRegion(callRangeAddress6);
		sheet.addMergedRegion(callRangeAddress7);
		sheet.addMergedRegion(callRangeAddress8);
		sheet.addMergedRegion(callRangeAddress9);
		sheet.addMergedRegion(callRangeAddress10);
		sheet.addMergedRegion(callRangeAddress11);
		sheet.addMergedRegion(callRangeAddress12);
		sheet.addMergedRegion(callRangeAddress13);
		sheet.addMergedRegion(callRangeAddress14);
		sheet.addMergedRegion(callRangeAddress15);
		sheet.addMergedRegion(callRangeAddress16);
		sheet.addMergedRegion(callRangeAddress17);
		sheet.addMergedRegion(callRangeAddress18);
		sheet.addMergedRegion(callRangeAddress19);
		sheet.addMergedRegion(callRangeAddress20);
		sheet.addMergedRegion(callRangeAddress21);
		sheet.addMergedRegion(callRangeAddress22);
		sheet.addMergedRegion(callRangeAddress23);
		sheet.addMergedRegion(callRangeAddress24);
		sheet.addMergedRegion(callRangeAddress25);
		sheet.addMergedRegion(callRangeAddress26);
		sheet.addMergedRegion(callRangeAddress27);
		sheet.addMergedRegion(callRangeAddress28);
		sheet.addMergedRegion(callRangeAddress29);
		sheet.addMergedRegion(callRangeAddress30);
		sheet.addMergedRegion(callRangeAddress31);
		sheet.addMergedRegion(callRangeAddress32);
		//sheet.addMergedRegion(callRangeAddress33);
		//sheet.addMergedRegion(callRangeAddress34);

		int index = 3;
		//副标题行
		/*if(headers2!=null){
			HSSFRow row2 = sheet.createRow(1);
			for (int i = 0; i < headers.length; i++) {
				HSSFCell cell2 = row2.createCell(i);
				cell2.setCellStyle(style);
				HSSFRichTextString text = new HSSFRichTextString(headers2[i]);
				cell2.setCellValue(text);
			}
			index ++;
		}*/

		// 遍历集合数据，产生数据行
		Iterator<T> it = dataset.iterator();
		XSSFFont font3 = workbook.createFont();
		font3.setColor(HSSFColor.BLUE.index);
		while (it.hasNext()) {
			index++;
			row = sheet.createRow(index);
			T t = (T) it.next();
			// 利用反射，根据javabean属性的先后顺序，动态调用getXxx()方法得到属性值
			Field[] fields = t.getClass().getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				XSSFCell cell = row.createCell(i);
				cell.setCellStyle(style2);
				Field field = fields[i];
				String fieldName = field.getName();
				String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
				Class tCls = t.getClass();
				Method getMethod = tCls.getMethod(getMethodName, new Class[] {});
				Object value = getMethod.invoke(t, new Object[] {});
				// 判断值的类型后进行强制类型转换
				String textValue = null;
				if (value instanceof Date) {
					Date date = (Date) value;
					textValue = DateUtil.format(date, DatePattern.NORM_DATE_PATTERN);
				} else {
					// 其它数据类型都当作字符串简单处理
					if (value == null) {
						textValue = "";
					} else {
						textValue = HtmlUtils.htmlUnescape(value.toString());
					}

				}
				// 如果不是图片数据，就利用正则表达式判断textValue是否全部由数字组成
				if (textValue != null) {
					Matcher matcher = NUMBER_PATTERN.matcher(textValue);
					if (matcher.matches()) {
						// 是数字当作double处理
						cell.setCellValue(Double.parseDouble(textValue));
					} else {
						XSSFRichTextString richString = new XSSFRichTextString(textValue);
						richString.applyFont(font3);
						cell.setCellValue(richString);
					}
				}
			}

		}
		workbook.write(out);
	}

	/**
	 * 导出excel模板
	 */
	public static void exportModelFile(HttpServletResponse res, String fileName, String modelPath){
		res.setHeader("content-type", "text/plain");
		res.setHeader("content-type", "application/x-msdownload;");
		res.setContentType("text/plain; charset=utf-8");
		res.setHeader("Content-Disposition", "attachment; filename=" + fileName);
		byte[] buff = new byte[1024];
		BufferedInputStream bis = null;
		OutputStream os = null;

		try {
			os = res.getOutputStream();
			bis = new BufferedInputStream(new FileInputStream(new File(modelPath)));
			int i = bis.read(buff);

			while (i != -1) {
				os.write(buff, 0, buff.length);
				os.flush();
				i = bis.read(buff);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 导出excel模板
	 */
	public static void exportExcelFile(HttpServletResponse response, String fileName, String filePath){
		byte[] buff = new byte[1024];
		BufferedInputStream bis = null;
		OutputStream os = null;

		try {
			response.setContentType("application/vnd.ms-excel; charset=UTF-8");
			fileName = new String(fileName.getBytes("GB2312"), StandardCharsets.ISO_8859_1);
			response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
			response.setCharacterEncoding("UTF-8");
			ClassPathResource resource = new ClassPathResource(filePath);
			os = response.getOutputStream();
			bis = new BufferedInputStream(resource.getInputStream());
			int i = bis.read(buff);

			while (i != -1) {
				os.write(buff, 0, buff.length);
				os.flush();
				i = bis.read(buff);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 导出文件
	 */
	public static void exportFile(HttpServletResponse response, HttpServletRequest request, String fileName, String filePath){
		byte[] buff = new byte[1024];
		BufferedInputStream bis = null;
		OutputStream os = null;

		try {
			response.setContentType("application/pdf; charset=UTF-8");
			fileName = new String(fileName.getBytes("GB2312"), StandardCharsets.ISO_8859_1);
			response.setHeader("Content-Disposition", "attachment; filename=" +  URLEncoder.encode(fileName, "UTF-8"));
			response.setCharacterEncoding("UTF-8");
			/*String path = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";
			filePath = path +"file/upload/" + filePath;*/
			URL url = new URL(filePath);
			HttpURLConnection conn = (HttpURLConnection)url.openConnection();
			InputStream inputStream = conn.getInputStream();
			os = response.getOutputStream();
			bis = new BufferedInputStream(inputStream);
			int i = bis.read(buff);

			while (i != -1) {
				os.write(buff, 0, buff.length);
				os.flush();
				i = bis.read(buff);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

}
