/**
 * 系统数据导出Excel 生成器
 * @version 1.0
 */
package com.emr.util;

import com.emr.entity.Archive_Detail;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


public class ExportExcelUtil {

	private final int SPLIT_COUNT = 1000000; //Excel每个工作簿的行数

	private static List<String> fieldName = null; //excel标题数据集

	private static List<List<String>> fieldData = null; //excel数据内容

	private String fileName;//excel文件名

	private HSSFWorkbook workBook = null;
	/**
	 * 组织表头,带逗号的字符串转换成list
	 * */
	public List<String> getFieldName(String tableThNames){
		String[] names = tableThNames.split(",");
		List<String> fieldName = new ArrayList<String>();
		if (names != null) {
			for (int i = 0; i < names.length; i++) {
				if (StringUtils.isNoneBlank(names[i])) {
					fieldName.add(names[i]);
				}
			}
		}
		return fieldName;
	}

	/**
	 * 组织数据,1.对象属性带逗号的字符串转换成list  2.数据组织成嵌套list
	 * */
	public List<List<String>> getFieldData(String fieldCns, Collection list){
		List<List<String>> fieldData = new ArrayList<List<String>>();
		String[] fieldList = fieldCns.split(",");
		Object[] objects = list.toArray();
		for (Object object : objects) {
			List<String> data = new ArrayList<String>();
			for (String english : fieldList) {
				String field = fieldToProperty(english);
				String value = getFieldValueByFieldName(field,object);
				data.add(value);
			}
			fieldData.add(data);
		}
		return fieldData;
	}
	/**
	 * 导出excel工具
	 * tableThNames：表头中文，用","隔开,如：“姓名，年龄”
	 * fieldCns：对象属性集合，用","隔开，如“name,age”
	 * list:对象数据集合
	 * fileName:excel文件命名
	 * response:输出
	 * */
	public void expordExcel(String tableThNames,String fieldCns,Collection list,String fileName,HttpServletResponse response) throws Exception {
		this.fieldName = getFieldName(tableThNames);
		this.fieldData = getFieldData(fieldCns,list);
		this.fileName = fileName;
		OutputStream os = response.getOutputStream();
		//导出excel建议加上重置输出流，可以不加该代码，但是如果不加必须要保证输出流中不应该在存在其他数据，否则导出会有问题
		response.reset();
		//处理乱码
		fileName = new String(fileName.getBytes("gbk"), "iso-8859-1");
		response.setContentType("application/vnd.ms-excel");
		response.setHeader("Content-disposition", "attachment;filename=" + fileName);
		response.setBufferSize(1024);
		workBook = createWorkbook();
		workBook.write(os);//将excel中的数据写到输出流中，用于文件的输出
		os.close();
	}
	/**
	 * 创建HSSFWorkbook对象
	 * @return HSSFWorkbook
	 */
	public HSSFWorkbook createWorkbook() {
		workBook = new HSSFWorkbook();//创建一个工作薄对象
		int rows = fieldData.size();//总的记录数
		int sheetNum = 0;           //指定sheet的页数

		if (rows % SPLIT_COUNT == 0) {
			sheetNum = rows / SPLIT_COUNT;
		} else {
			sheetNum = rows / SPLIT_COUNT + 1;
		}

		for (int i = 1; i <= sheetNum; i++) {//循环2个sheet的值
			HSSFSheet sheet = workBook.createSheet("Page " + i);//使用workbook对象创建sheet对象
			HSSFRow headRow = sheet.createRow((short) 0); //创建行，0表示第一行（本例是excel的标题）
			/**************对标题添加样式begin********************/

			HSSFCellStyle cellStyle = workBook.createCellStyle();//创建列的样式对象
			//水平居中
			cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
			//垂直居中
			cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

			HSSFFont font = workBook.createFont();//创建字体对象
			//字体加粗
			font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
			//字体颜色变红
			font.setColor(HSSFColor.RED.index);
			//如果font中存在设置后的字体，并放置到cellStyle对象中，此时该单元格中就具有了样式字体
			cellStyle.setFont(font);

			/**************对标题添加样式end********************/
			for (int j = 0; j < fieldName.size(); j++) {//循环excel的标题
				HSSFCell cell = headRow.createCell( j);//使用行对象创建列对象，0表示第1列
				//设置列的宽度/
				sheet.setColumnWidth(j, 6000);
				//添加样式
				cell.setCellType(HSSFCell.CELL_TYPE_STRING);
				if(fieldName.get(j) != null){
					//将创建好的样式放置到对应的单元格中
					cell.setCellStyle(cellStyle);
					cell.setCellValue((String) fieldName.get(j));//为标题中的单元格设置值
				}else{
					cell.setCellValue("-");
				}
			}
			//分页处理excel的数据，遍历所有的结果
			for (int k = 0; k < (rows < SPLIT_COUNT ? rows : SPLIT_COUNT); k++) {
				if (((i - 1) * SPLIT_COUNT + k) >= rows)//如果数据超出总的记录数的时候，就退出循环
					break;
				HSSFRow row = sheet.createRow((short) (k + 1));//创建1行
				//分页处理，获取每页的结果集，并将数据内容放入excel单元格
				ArrayList<String> rowList = (ArrayList<String>) fieldData.get((i - 1) * SPLIT_COUNT + k);
				for (int n = 0; n < rowList.size(); n++) {//遍历某一行的结果
					HSSFCell cell = row.createCell( n);//使用行创建列对象
					if(rowList.get(n) != null){
						cell.setCellValue((String) rowList.get(n).toString());
					}else{
						cell.setCellValue("");
					}
				}
			}
		}
		return workBook;
	}

	/**
	 * 字段转换成对象属性 例如：user_name to userName
	 * @param field
	 * @return
	 */
	public static String fieldToProperty(String field) {
		if (null == field) {
			return "";
		}
		char[] chars = field.toCharArray();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < chars.length; i++) {
			char c = chars[i];
			if (c == '_') {
				int j = i + 1;
				if (j < chars.length) {
					sb.append(StringUtils.upperCase(CharUtils.toString(chars[j])));
					i++;
				}
			} else {
				sb.append(c);
			}
		}
		return sb.toString();
	}

	/**
	 * 根据属性名获取属性值
	 *
	 * @param fieldName
	 * @param object
	 * @return
	 */
	public static String getFieldValueByFieldName(String fieldName, Object object) {
		try {
			Field field = object.getClass().getDeclaredField(fieldName);
			//设置对象的访问权限，保证对private的属性的访问
			field.setAccessible(true);
			return  field.get(object).toString();
		} catch (Exception e) {
			return null;
		}
	}
}
