读取和写入excel表格所需的DLL:
public static DataSet ReadExcel(string path)
{
FileStream stream = File.Open(path,FileMode.Open,FileAccess.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet();
excelReader.Close();
int columns = result.Tables[0].Columns.Count;
int rows = result.Tables[0].Rows.Count;
for(int i = 0;i < rows;i++)
{
for(int j = 0;j < columns;j++)
{
string nvalue = result.Tables[0].Rows[i][j].ToString();
}
}
return result;
}
这个方法从给定的excel中拿到所有的行和列的数据。
因为读取和写入不应该关心具体的数据类型,只是按表格的行和列遍历的操作,所以在读取和写入的入口位置采用泛型。
public static List<T> Load<T>(string path)
{
List<T> data = new List<T>();
DataSet resultds = ReadExcel(path);
int column = resultds.Tables[0].Columns.Count;
int row = resultds.Tables[0].Rows.Count;
for(int i = 1;i < row;i++)
{
T t = System.Activator.CreateInstance<T>();
int j = 0;
foreach(var property in t.GetType().GetProperties())
{
property.SetValue(t, resultds.Tables[0].Rows[i][j].ToString(),null);
j++;
}
data.Add(t);
}
return data;
}
这个是对外的接口,传入要读取的excel路径(包括文件名.xlsx)。
遍历行时从1开始,排除了表头,创建该泛型实例,利用反射,获取该泛型类型中的所有属性,挨个赋予刚才读到的值,最后返回这个数据队列。
public static void WriteIn<T>(string path,List<T> paramList)
{
FileInfo newFile = new FileInfo(path);
if(newFile.Exists)
{
newFile.Delete();
newFile = new FileInfo(path);
}
using (ExcelPackage package = new ExcelPackage(newFile))
{
ExcelWorksheet workSheet = package.Workbook.Worksheets.Add("Sheet1");
int i = 1;
foreach(var t in typeof(T).GetProperties())
{
workSheet.Cells[1, i++].Value = t.Name;
}
for(int j = 0;j < paramList.Count;j++)
{
System.Reflection.PropertyInfo[] propertyInfos =
paramList[j].GetType().GetProperties();
for (int k = 0;k < propertyInfos.Length;k++)
{
System.Reflection.PropertyInfo propertyInfo = propertyInfos[k];
workSheet.Cells[j + 2, k + 1].Value =
propertyInfo.GetValue(paramList[j]);
}
}
package.Save();
}
}
这是写入excel的对外接口。
第一个遍历先利用反射,按照泛型类型的所有属性名,写入表头(必须把所有数据写一遍,不写的就会丢失)。然后用一个双循环, 把传进来的数据队列按行列逐个写入excel。最后保存。
最后看一下调用的地方:
public class ManagerTableData
{
private string id;
private string na;
private string index;
public string ID
{
get
{
return id;
}
set
{
id = value;
}
}
public string Name
{
get
{
return na;
}
set
{
na = value;
}
}
public string Index
{
get
{
return index;
}
set
{
index = value;
}
}
}
List<ManagerTableData> data = DoExcel.Load<ManagerTableData>(Application.streamingAssetsPath + "/Manager.xlsx");
ManagerTableData是一个自定义数据类型,用来封装从该表格中读取到的数据。
创建一个该类型的队列(一般是字典),调用Load接口,传入表格的路径,即可得到从表中读取到的封装后的该类型数据队列。
再看一下写入的接口调用:
string fileName = "Manager";
string path = string.Format("{0}/{1}.xlsx", Application.streamingAssetsPath, fileName);
ManagerTableData tData = new ManagerTableData();
tData.ID = "1";
tData.Name = "Camera";
tData.Index = "1";
List<ManagerTableData> l = new List<ManagerTableData>();
l.Add(tData);
tData = new ManagerTableData();
tData.ID = "3";
tData.Name = "People";
tData.Index = "3";
l.Add(tData);
WriteExcel.WriteIn<ManagerTableData>(path,l);
写入时,先把需要写入的数据封装成该类型的数据队列,然后传给该接口即可。
泛型最大的好处就是灵活,读取和写入的功能不关心外界传入的类型,只需要关心数据的存取即可。在入口处,传入什么类型,最后拿到的还是对应类型的数据,爽歪歪。