参考
C#实现Excel文件的读取与保存,主要用作游戏开发时对于一些数据的修改及添加。游戏打包后不使用。
Excel.dll 以及 ICSharpCode.SharpZipLib
Epplus.dll
System.Data.dll
自定义Attribute,为类的字段添加标签。保存Excel文件时,通过反射获取字段的CustomAttributes,这样就可以为Excel文件的字段添加中文的解释。
自定义Attribute的代码如下:
///
/// 自定义Attribute
///
public class DescriptionAttribute : Attribute
{
private string description;
public DescriptionAttribute(string str_description)
{
description = str_description;
}
public string Description
{
get { return description; }
set { description = value; }
}
}
测试使用 DescriptionAttribute的代码如下:
///
/// 测试使用 DescriptionAttribute
///
public class AttributeTest
{
[Description("编号")]
public int id;
[Description("名称")]
public string name;
[Description("修改日期")]
public string updateTime;
}
///
/// 可用于保存到Excel文件的抽象类
///
[System.Serializable]
public abstract class ExcelData
{
/// 唯一标识符
protected string _guid;
public abstract string guid
{
get;
}
}
///
/// 测试数据类
///
public class TestData : ExcelData
{
[Description("编号")]
public int id;
[Description("名称")]
public string name;
[Description("修改日期")]
public string updateTime;
public override string guid
{
get
{
return string.Format("{0}_{1}", id, name);
}
}
}
///
/// 将数据写入excel
///
///
/// 所需保存的数据
/// Excel文件名
/// Excel文件中的sheetName
public static void SaveToExcel(this List current, string excel_name = "", string sheet_name = "") where T : ExcelData, new()
{
/// excel_name为空时采用T类型名作为excel文件名,sheet_name同理
excel_name = string.IsNullOrEmpty(excel_name) ? typeof(T).ToString() : excel_name;
sheet_name = string.IsNullOrEmpty(sheet_name) ? typeof(T).ToString() : sheet_name;
/// 获取文件信息 PathConst.ExcelFilePath(excel_name) 为文件地址
var fileInfo = new FileInfo(PathConst.ExcelFilePath(excel_name));
using (var package = new ExcelPackage(fileInfo))
{
if (package.Workbook.Worksheets[sheet_name] != null)
{
package.Workbook.Worksheets.Delete(sheet_name);
}
var workSheet = package.Workbook.Worksheets.Add(sheet_name);
var fields = typeof(T).GetFields();
/// 字段名
for (int titleId = 0; titleId < fields.Length; titleId++)
{
var attribs = fields[titleId].GetCustomAttributes(typeof(DescriptionAttribute), false);
workSheet.Cells[1, titleId + 1].Value = attribs.Length > 0 ? ((DescriptionAttribute)attribs[0]).Description : fields[titleId].Name;
}
/// 内容
for (int i = 0; i < current.Count; i++)
{
for (int j = 0; j < fields.Length; j++)
{
workSheet.Cells[i + 2, j + 1].Value = fields[j].GetValue(current[i]);
}
}
package.Save();
Debuger.Log(string.Format("{0}_{1}:写入成功!", excel_name, sheet_name));
}
}
List source = new List();
for (int i = 0; i < 10; i++)
{
source.Add(new TestData(i, "name_" + i.ToString(), DateTime.Now.ToString()));
}
/// 保存到Excel文件中
source.SaveToExcel();
///
/// Excel种读取数据
///
///
///
///
///
///
public static List ReadFromExcel(this List current, string excel_name = "", string sheet_name = "") where T : ExcelData, new()
{
excel_name = string.IsNullOrEmpty(excel_name) ? typeof(T).ToString() : excel_name;
sheet_name = string.IsNullOrEmpty(sheet_name) ? typeof(T).ToString() : sheet_name;
if (!File.Exists(PathConst.ExcelFilePath(excel_name)))
{
current.SaveToExcel();
return current;
}
using (var fs = File.Open(PathConst.ExcelFilePath(excel_name), FileMode.Open, FileAccess.Read))
{
using (var excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs))
{
var table = excelReader.AsDataSet().Tables[sheet_name];
var fields = typeof(T).GetFields();
int rowCount = table.Rows.Count;
int columnCount = table.Columns.Count;
/// 第一行为变量名称
var variableNameList = new List<string>();
for (int i = 0; i < columnCount; i++)
variableNameList.Add(table.Rows[0][i].ToString());
for (int i = 1; i < rowCount; i++)
{
var item = new T();
var row = table.Rows[i];
for (int j = 0; j < fields.Length; j++)
{
var field = fields[j];
var index = variableNameList.IndexOf(field.Name);
if (index < 0)
Debuger.LogError(string.Format("Excel表格{0}中,无法找到{1}字段", typeof(T).ToString(), field.Name));
else
field.SetValue(item, Convert.ChangeType(row[j], field.FieldType));
}
current.Add(item);
}
}
Debuger.Log(string.Format("{0}_{1}:读出成功!", excel_name, sheet_name));
}
return current;
}
上述 ConvertObject(object,type) 方法是将excel中读取的数据转换为制定类型的数据,需要进一步扩展。