package com.fuzamei.util;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 
 * @ClassName: ImportExecl
 * @opyright:Copyright (c) Ponshine 2015
 * @Description: TODO(excel读取)
 * @author wangchunjie
 * @date 2015年7月2日 上午9:49:24
 * @version V1.0
 */
public class ReadExcel {
	/** 总行数 */
	private int totalRows = 0;
	/** 总列数 */
	private int totalCells = 0;
	/** 错误信息 */
	private String errorInfo;

	/** 构造方法 */

	public ReadExcel() {
	}

	/**
	 * 
	 * @Title: getTotalRows
	 * @Description: TODO(得到总行数)
	 * @param @return 设定文件
	 * @author wangchunjie
	 * @return int 返回类型
	 * @throws
	 */
	public int getTotalRows() {
		return totalRows;

	}

	/**
	 * 
	 * @Title: getTotalCells
	 * @Description: TODO(得到总列数)
	 * @param @return 设定文件
	 * @author wangchunjie
	 * @return int 返回类型
	 * @throws
	 */
	public int getTotalCells() {
		return totalCells;
	}

	/**
	 * 
	 * @Title: getErrorInfo
	 * @Description: TODO(得到错误信息)
	 * @param @return 设定文件
	 * @author wangchunjie
	 * @return String 返回类型
	 * @throws
	 */
	public String getErrorInfo() {

		return errorInfo;

	}

	/**
	 * 
	 * @Title: validateExcel
	 * @Description: TODO(验证excel文件)
	 * @param @param filePath 文件完整路径
	 * @param @return 设定文件
	 * @author wangchunjie
	 * @return boolean 返回类型
	 * @throws
	 */
	public boolean validateExcel(String filePath) {
		/** 检查文件名是否为空或者是否是Excel格式的文件 */
		if (filePath == null
				|| !(WDWUtil.isExcel2003(filePath) || WDWUtil
						.isExcel2007(filePath))) {
			errorInfo = "文件名不是excel格式";
			return false;
		}
		/** 检查文件是否存在 */
		File file = new File(filePath);
		if (file == null || !file.exists()) {
			errorInfo = "文件不存在";
			return false;
		}
		return true;
	}

	
	
	/**
	 * 
	 * @Title: read
	 * @Description: TODO(根据文件名读取excel文件)
	 * @param @param filePath 文件完整路径
	 * @param @return 设定文件
	 * @author wangchunjie
	 * @return List<List<String>> 返回类型
	 * @throws
	 */
	public List<List<String>> read(String filePath) {
		List<List<String>> dataLst = new ArrayList<List<String>>();
		InputStream is = null;
		try {
			/** 验证文件是否合法 */
			if (!validateExcel(filePath)) {
				System.out.println(errorInfo);
				return null;
			}
			/** 判断文件的类型，是2003还是2007 */

			boolean isExcel2003 = true;
			if (WDWUtil.isExcel2007(filePath)) {
				isExcel2003 = false;
			}
			/** 调用本类提供的根据流读取的方法 */
			File file = new File(filePath);
			is = new FileInputStream(file);
			dataLst = read(is, isExcel2003);
			is.close();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					is = null;
					e.printStackTrace();
				}
			}
		}
		/** 返回最后读取的结果 */
		return dataLst;
	}

	/**
	 * 
	 * @Title: read
	 * @Description: TODO(根据流读取Excel文件)
	 * @param @param inputStream
	 * @param @param isExcel2003
	 * @param @return 设定文件
	 * @author wangchunjie
	 * @return List<List<String>> 返回类型
	 * @throws
	 */
	public List<List<String>> read(InputStream inputStream, boolean isExcel2003) {
		List<List<String>> dataLst = null;
		try {
			/** 根据版本选择创建Workbook的方式 */
			Workbook wb = null;
			if (isExcel2003) {
				wb = new HSSFWorkbook(inputStream);
			} else {
				wb = new XSSFWorkbook(inputStream);
			}
			dataLst = read(wb);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return dataLst;
	}

	/**
	 * 
	 * @Title: read
	 * @Description: TODO(读取数据)
	 * @param @param wb
	 * @param @return 设定文件
	 * @author wangchunjie
	 * @return List<List<String>> 返回类型
	 * @throws
	 */
	private List<List<String>> read(Workbook wb) {
		List<List<String>> dataLst = new ArrayList<List<String>>();
		/** 得到第一个shell */
		Sheet sheet = wb.getSheetAt(0);
		
		/** 得到Excel的行数 */
		this.totalRows = sheet.getPhysicalNumberOfRows();
		/** 得到Excel的列数 */
		if (this.totalRows >= 1 && sheet.getRow(0) != null) {
			this.totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
		}
		/** 循环Excel的行 */
		for (int r = 0; r < this.totalRows; r++) {
			Row row = sheet.getRow(r);
			if (row == null) {
				continue;
			}
			List<String> rowLst = new ArrayList<String>();
			/** 循环Excel的列 */
			for (int c = 0; c < this.getTotalCells(); c++) {
				Cell cell = row.getCell(c);
				/**
				 * 2017-11-08
				 * maamin
				 * 解决excel单元格内的数字不能原样读出的问题，如数字加了.0,长数字读出来是科学计数法
				 */
				cell.setCellType(HSSFCell.CELL_TYPE_STRING);
				//////////////////////////////////////////////结束
				String cellValue = "";
				if (null != cell) {
					// 以下是判断数据的类型
					switch (cell.getCellType()) {
					case HSSFCell.CELL_TYPE_NUMERIC: // 数字
						String temp = String.valueOf(cell.getNumericCellValue());
						cellValue = temp.trim();
						break;
					case HSSFCell.CELL_TYPE_STRING: // 字符串
						cellValue = cell.getStringCellValue();
						break;
					case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
						cellValue = cell.getBooleanCellValue() + "";
						break;
					case HSSFCell.CELL_TYPE_FORMULA: // 公式
						cellValue = cell.getCellFormula() + "";
						break;
					case HSSFCell.CELL_TYPE_BLANK: // 空值
						cellValue = "";
						break;
					case HSSFCell.CELL_TYPE_ERROR: // 故障
						cellValue = "非法字符";
						break;
					default:
						cellValue = "未知类型";
						break;
					}
				}
				rowLst.add(cellValue);
			}
			/** 保存第r行的第c列 */
			dataLst.add(rowLst);
		}
		return dataLst;
	}
	/*
	 * 写入excel操作
	 * 2016年9月6日
	 * 作者：Amin Ma
	 * param：list
	 * param:map<String,String>	,所有列的标题
	 */
	public static HSSFWorkbook CreateExportExcel(List<Map<String,Object>> list,Map<Integer,String> map) {		//创建excel文件对象,传进来的为一个list参数
		HSSFWorkbook wb = new HSSFWorkbook();
		//创建一个张表
		Sheet sheet = wb.createSheet();
		//创建第一行
		Row row = sheet.createRow(0);
	    //创建第二行
		Row row1 = sheet.createRow(1);
		// 文件头字体
		Font font0 = createFonts(wb, Font.BOLDWEIGHT_BOLD, "宋体",false,
				(short) 200);
		Font font1 = createFonts(wb, Font.BOLDWEIGHT_NORMAL, "宋体", false,
				(short) 200);
		for(int i =0; i <map.size(); i ++){	//创建所有的列标题
			createCell(wb, row, i, map.get(i), font0);
		}
		int l = 1;
		for(int i = 0;i < list.size(); i ++){
			if(list.get(i).size() != 0){
				Row rowData = sheet.createRow(l++); 
				int index = 0;
				//键值是未知的，要得到里面所有的键,所有要先遍历所有键
				Map<String,Object> mapdata = list.get(i);
				Set<String> keys = mapdata.keySet();
				for(String key : keys){
					String DataValue = "";
					if(mapdata.get(key) != null){
						DataValue = mapdata.get(key).toString();
					}
					createCell(wb, rowData, index, DataValue, font1);
					index ++;
				}
			}
		}
		//将所有列宽度都设置成自动的,用下面的for有时候会报错
//		for(int i = 0; i < map.size();i ++){	
//			sheet.autoSizeColumn(i);
//		}
		return wb;
	}	

	/*
	 * 写入excel操作（根据要求分sheet页显示）
	 * 2017年2月6日
	 * 作者：龚利炳
	 * param：list
	 * param:map<String,String>	,所有列的标题
	 */
	public static HSSFWorkbook CreateExportExcelBySheet(HSSFWorkbook wb,List<Map<String,Object>> list,Map<Integer,String> map) {			
		//创建一个张表
		Sheet sheet = wb.createSheet();
		//创建第一行
		Row row = sheet.createRow(0);
	    //创建第二行
		Row row1 = sheet.createRow(1);
		// 文件头字体
		Font font0 = createFonts(wb, Font.BOLDWEIGHT_BOLD, "宋体",false,
				(short) 200);
		Font font1 = createFonts(wb, Font.BOLDWEIGHT_NORMAL, "宋体", false,
				(short) 200);
		for(int i =0; i <map.size(); i ++){	//创建所有的列标题
			createCell(wb, row, i, map.get(i), font0);
		}
		int l = 1;
		for(int i = 0;i < list.size(); i ++){
			if(list.get(i).size() != 0){
				Row rowData = sheet.createRow(l++); 
				int index = 0;
				//键值是未知的，要得到里面所有的键,所有要先遍历所有键
				Map<String,Object> mapdata = list.get(i);
				Set<String> keys = mapdata.keySet();
				for(String key : keys){
					String DataValue = "";
					if(mapdata.get(key) != null){
						DataValue = mapdata.get(key).toString();
					}
					createCell(wb, rowData, index, DataValue, font1);
					index ++;
				}
			}
		}
		//将所有列宽度都设置成自动的
		for(int i = 0; i < map.size();i ++){
			sheet.autoSizeColumn(i);
		}
		return wb;
	}	
/**
	 * 创建单元格并设置样式,值
	 * 
	 * @param wb
	 * @param row
	 * @param column
	 * @param
	 * @param
	 * @param value
	 */
	public static void createCell(Workbook wb, Row row, int column,
		String value, Font font) {
		Cell cell = row.createCell(column);
		cell.setCellValue(value);
		CellStyle cellStyle = wb.createCellStyle();
		cellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);
		cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_BOTTOM);
		cellStyle.setFont(font);
		cell.setCellStyle(cellStyle);
	}

	/**
	 * 设置字体
	 * 
	 * @param wb
	 * @return
	 */
	public static Font createFonts(Workbook wb, short bold, String fontName,
			boolean isItalic, short hight) {
		Font font = wb.createFont();
		font.setFontName(fontName);
		font.setBoldweight(bold);
		font.setItalic(isItalic);
		font.setFontHeight(hight);
		return font;
	}

	/**
	 * 判断是否为数字
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNumeric(String str) {
		if (str == null || "".equals(str.trim()) || str.length() > 10)
			return false;
		Pattern pattern = Pattern.compile("^0|[1-9]\\d*(\\.\\d+)?$");
		return pattern.matcher(str).matches();
	}

	public static void main(String[] args) throws Exception {
		ReadExcel poi = new ReadExcel();
//		String filepath = System.getProperty("user.dir")+File.separator+"report_file"+File.separator;
//		String filepath = "E:/MyEclipse 10/dnbm/deploy/WebRoot/upload/ScriptGeneration_script_file/zyfpb1_20160817164139.xlsx";
//		List<List<String>> list = poi.read(");
//		System.out.println("list:"+list.get(0));
		//定以列map
		Map<Integer,String> columnMap = new LinkedHashMap<Integer,String>();
		columnMap.put(0, "1列头");	//代表第一列
		columnMap.put(1,"2列头");
		columnMap.put(2,"3列头");
		columnMap.put(3,"4列头");
		//数据
		List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
		Map<String,Object> map = new LinkedHashMap<String,Object>();
		map.put("aa","fdfd");
		map.put("bb","kjfkd");
		map.put("cc","fdfdffff");
		map.put("dd","kjfkd3333");
		list.add(map);
		//写入某个路径
		HSSFWorkbook wb = ReadExcel.CreateExportExcel(list,columnMap);
		FileOutputStream fileOut  = new FileOutputStream("d:\\excel\\aa.xls");
		wb.write(fileOut);
	}
	
	/**
	 * 创建一张表
	 * xuguoqiang
	 * @param list
	 * @param map
	 * @return
	 */
		public static HSSFWorkbook CreateIpExcel(List<Map<String,Object>> list,Map<Integer,String> map) {
			HSSFWorkbook wb = new HSSFWorkbook();
			//创建一个张表
			Sheet sheet = wb.createSheet();
			//创建第一行
			Row row = sheet.createRow(0);
		    //创建第二行
			Row row1 = sheet.createRow(1);
			//创建第三行
			Row row2 = sheet.createRow(1);
			// 文件头字体
			Font font0 = createFonts(wb, Font.BOLDWEIGHT_BOLD, "宋体",false,
					(short) 200);
			Font font1 = createFonts(wb, Font.BOLDWEIGHT_NORMAL, "宋体", false,
					(short) 200);
		
			
			for(int i =0; i <map.size(); i ++){	//创建所有的列标题
				createCell(wb, row, i, map.get(i), font0);
			}
			int l = 1;
			for(int i = 0;i < list.size(); i ++){
				if(list.get(i).size() != 0){
					Row rowData = sheet.createRow(l++); 
					int index = 0;
					//键值是未知的，要得到里面所有的键,所有要先遍历所有键
					Map<String,Object> mapdata = list.get(i);
					Set<String> keys = mapdata.keySet();
					for(String key : keys){
						String DataValue = "";
						if(mapdata.get(key) != null){
							DataValue = mapdata.get(key).toString();
						}
						createCell(wb, rowData, index, DataValue, font1);
						index ++;
					}
				}
			}

			return wb;
		}
}

/**
 * 
 * @ClassName: WDWUtil
 * @Description: TODO(工具类)
 * @author wangchunjie
 * @version V1.0
 */
class WDWUtil {
	/**
	 * 
	 * @Title: isExcel2003
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @param @param filePath 文件完整路径
	 * @param @return 设定文件
	 * @author wangchunjie
	 * @return boolean 返回类型
	 * @throws
	 */
	public static boolean isExcel2003(String filePath) {

		return filePath.matches("^.+\\.(?i)(xls)$");

	}

	/**
	 * 
	 * @Title: isExcel2007
	 * @Description: TODO(是否是2007的excel，返回true是2007)
	 * @param @param filePath 文件完整路径
	 * @param @return 设定文件
	 * @author wangchunjie
	 * @return boolean 返回类型
	 * @throws
	 */
	public static boolean isExcel2007(String filePath) {

		return filePath.matches("^.+\\.(?i)(xlsx)$");

	}
	
	
}


