//==============================================================
//  版权所有：深圳杰文科技
//  文件名：ExcelHelper.cs
//  版本：V1.0  
//  创建者：Jay  ( QQ： 85363208 )
//  创建时间：2017-11-28 16:18
//  创建描述：
//  修改者：
//  修改时间：
//  修改说明： 
//==============================================================

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Infrastructure.Utilities
{
	public class ExcelHelper
	{
		#region - Read -

		private static string connectionString = string.Empty;
		private static ExcelExtention excelExtention = ExcelExtention.xls;

		public static DataSet ReadSet(string path)
		{
			excelExtention = GetExcelExtention(path);
			return ReadSet(path, GetWorkSheets(GetConnectionString(path)));
		}

		public static DataTable ReadTable()
		{
			OpenFileDialog dialog = new OpenFileDialog();
			dialog.Filter = "Excel文档|*.xls;*.xlsx|所有文档|*.*";
			if (dialog.ShowDialog() != DialogResult.OK)
			{
				return null;
			}
			return ReadTable(dialog.FileName);
		}

		public static DataTable ReadTable(string path)
		{
			return ReadTable(path, null);
		}

		public static DataTable ReadTable(string path, string sheetName)
		{
			excelExtention = GetExcelExtention(path);
			string[] tables = GetWorkSheets(GetConnectionString(path));

			if (string.IsNullOrEmpty(sheetName))
			{
				sheetName = tables[0];
			}
			else
			{
				if (!sheetName.EndsWith("$"))
				{
					sheetName = sheetName + "$";
				}

				if (!tables.Contains(sheetName))
				{
					throw new Exception("没有找到指定的Sheet：" + sheetName);
				}
			}

			DataSet ds = ReadSet(path, new string[] { sheetName });
			return ds.Tables[0];
		}

		private static ExcelExtention GetExcelExtention(string path)
		{
			string extention = path.Split('.')[path.Split('.').Length - 1];
			if (extention.Trim() == ExcelExtention.xlsx.ToString())
				return ExcelExtention.xlsx;
			else
				return ExcelExtention.xls;

		}

		private static string GetConnectionString(string path)
		{
			if (excelExtention == ExcelExtention.xls)
				connectionString = string.Format("Provider=Microsoft.Jet.OleDb.4.0;data source={0};Extended Properties=Excel 8.0;", path);
			else if (excelExtention == ExcelExtention.xlsx)
				connectionString = string.Format("Provider=Microsoft.ACE.OleDb.12.0; data source={0}; Extended Properties=Excel 8.0;", path);
			return connectionString;
		}

		private static DataSet ReadSet(string path, string[] workSheets)
		{
			var ds = new DataSet();
			foreach (string workSheet in workSheets)
			{
				try
				{
					using (OleDbDataAdapter adapter = new OleDbDataAdapter(string.Format("SELECT * FROM [{0}]", workSheet), GetConnectionString(path)))
					{
						adapter.Fill(ds, workSheet);
						adapter.Dispose();
					}
				}
				catch (Exception ex)
				{
					throw new Exception(ex.Message, ex.InnerException);
				}
			}
			return ds;
		}

		private static string[] GetWorkSheets(string connectionString)
		{
			DataTable dataTable;
			try
			{
				using (OleDbConnection connection = new OleDbConnection(connectionString))
				{
					connection.Open();
					dataTable = connection.GetSchema("Tables");
				}
			}
			catch (Exception ex)
			{
				throw new Exception(ex.Message, ex.InnerException);
			}
			int lenght = dataTable.Rows.Count;
			string[] worksheets = new string[lenght];
			for (int i = 0; i < lenght; i++)
			{
				worksheets[i] = dataTable.Rows[i]["TABLE_NAME"].ToString();
			}
			return worksheets;
		}

		private enum ExcelExtention
		{
			xls = 1,
			xlsx = 2
		}

		#endregion

		#region - Write -
		public static void WriteTable(DataTable dt, string path)
		{
			FileStream fileStream = new FileStream(string.Format(@"{0}\{1}.xls", path, dt.TableName), FileMode.Create);
			ExcelWriter writer = new ExcelWriter(fileStream);
			writer.BeginWrite();
			int rowIndex = 0;
			foreach (DataColumn column in dt.Columns)
			{
				writer.WriteCell(rowIndex, column.Ordinal, column.ColumnName);
			}
			foreach (DataRow row in dt.Rows)
			{
				rowIndex++;
				foreach (DataColumn column in dt.Columns)
				{
					writer.WriteCell(rowIndex, column.Ordinal, row[column.ColumnName].ToString());
				}

			}
			writer.EndWrite();
			fileStream.Close();

		}

		public static void WriteSet(DataSet ds, string path)
		{
			foreach (DataTable dt in ds.Tables)
			{
				WriteTable(dt, path);
			}
		}

		private class ExcelWriter
		{
			private Stream stream;
			private BinaryWriter writer;

			private ushort[] clBegin = { 0x0809, 8, 0, 0x10, 0, 0 };
			private ushort[] clEnd = { 0x0A, 00 };


			private void WriteUshortArray(ushort[] value)
			{
				for (int i = 0; i < value.Length; i++)
				{
					writer.Write(value[i]);
				}
			}

			public ExcelWriter(Stream stream)
			{
				this.stream = stream;
				writer = new BinaryWriter(stream);
			}

			public void WriteCell(int row, int col, string value)
			{
				ushort[] clData = { 0x0204, 0, 0, 0, 0, 0 };
				int iLen = value.Length;
				byte[] plainText = Encoding.ASCII.GetBytes(value);
				clData[1] = (ushort)(8 + iLen);
				clData[2] = (ushort)row;
				clData[3] = (ushort)col;
				clData[5] = (ushort)iLen;
				WriteUshortArray(clData);
				writer.Write(plainText);
			}

			public void WriteCell(int row, int col, int value)
			{
				ushort[] clData = { 0x027E, 10, 0, 0, 0 };
				clData[2] = (ushort)row;
				clData[3] = (ushort)col;
				WriteUshortArray(clData);
				int iValue = (value << 2) | 2;
				writer.Write(iValue);
			}

			public void WriteCell(int row, int col, double value)
			{
				ushort[] clData = { 0x0203, 14, 0, 0, 0 };
				clData[2] = (ushort)row;
				clData[3] = (ushort)col;
				WriteUshortArray(clData);
				writer.Write(value);
			}

			public void WriteCell(int row, int col)
			{
				ushort[] clData = { 0x0201, 6, 0, 0, 0x17 };
				clData[2] = (ushort)row;
				clData[3] = (ushort)col;
				WriteUshortArray(clData);
			}

			public void BeginWrite()
			{
				WriteUshortArray(clBegin);
			}

			public void EndWrite()
			{
				WriteUshortArray(clEnd);
				writer.Flush();
			}
		}

		#endregion

		/// <summary>
		/// 从Excel文件中导入数据为实体类。
		/// </summary>
		/// <returns></returns>
		public static List<T> Read<T>(string fileName, string sheet) where T : class, new()
		{
			DataTable table = ReadTable(fileName, sheet);
			List<T> list = table.ToList<T>();
			return list;
		}

		/// <summary>
		/// 从Excel文件中导入数据为实体类。
		/// </summary>
		/// <returns></returns>
		public static IList<T> Read<T>() where T : class, new()
		{
			OpenFileDialog dialog = new OpenFileDialog();
			dialog.Filter = "Excel文档|*.xls;*.xlsx|所有文档|*.*";
			if (dialog.ShowDialog() != DialogResult.OK)
			{
				return null;
			}

			DataTable table = ReadTable(dialog.FileName);
			List<T> list = table.ToList<T>();
			return list;
		}

		public static DataTable ReadCsv(string filePath)
		{
			DataTable dt = new DataTable();
			StreamReader reader = new StreamReader(filePath, System.Text.Encoding.Default, false);
			int m = 0;
			reader.Peek();
			while (reader.Peek() > 0)
			{
				string line = reader.ReadLine();
				if (string.IsNullOrWhiteSpace(line)) //跳过空行（包括全是空格的行）。
				{
					continue;
				}

				string[] split = line.Split(',');

				m = m + 1;
				if (m == 1) //默认第一行是列名。
				{
					for (int i = 0; i < split.Length; i++)
					{
						dt.Columns.Add(split[i]);
					}
				}
				else
				{
					System.Data.DataRow dr = dt.NewRow();
					for (int i = 0; i < split.Length; i++)
					{
						dr[i] = split[i];
					}
					dt.Rows.Add(dr);
				}
			}
			return dt;
		}

		public static void Test()
		{
			DataTable table = ReadCsv(@"d:\temp\OD1804000337_2018-7-14-7-4-30.csv");
			Console.WriteLine(table.TableName);
		}
	}
}
