Excel编程工具转换CShap
这两天闲着比较蛋疼,工作也暂时告一段落了。研究了个小工具,Excel转C#本地持久化数据。
先说下实现的思路:
首先我们肯定得需要一个Excel文件(可多个)。文件格式如下图一,这里保存三个数据第一行只是标识,没什么用。
从第二行开始,我会先把Sheet的名字缓存到一个字典里面,方便后面的根据sheet名来找指定的工作表。
类名一列,也把它缓存起来,所以第一个我需要用到的字典是 Dictionary<string, Tuple<bool, string>>
为什么这边多了一个bool?因为索引key可能是不要自己设定的,因为有些特殊需求可能会存在相同的key,所以当有可能存在相同的key的时候就不需要指定key的索引。会自动从0-数据长度。第一个string,保存的是sheet名,第二string保存的是key。不填索引key,默认是 “”;
当然我们还得需要一个className的集合,你也既可以在上面的字典加入保存,我这边就单独用了一个list还缓存。
代码一
图一
代码一
public class InitSheetClass
{
private List<Tuple> m_data_List = new List<Tuple>();
private List<string> m_classNames = new List<string>();
private OperaterData operaterData;
private Dictionary<string, Tuple<bool, string>> m_sheet_dic = new Dictionary<string, Tuple<bool, string>>();
public List<string> ClassName { get => m_classNames; }
public List<Tuple> Data_List { get => m_data_List; }
public Dictionary<string, Tuple<bool, string>> Sheet_dic { get => m_sheet_dic; set => m_sheet_dic = value; }
public OperaterData OperaterData { get => operaterData; set => operaterData = value; }
public void InitOneClass(OperaterData operaterData)
{
this.OperaterData = operaterData;
InitDataInfo();
}
private void InitDataInfo()
{
if (this.OperaterData == null || this.OperaterData.workBook == null)
{
throw new Exception("this.operaterData is Null.");
}
ISheet sheet = OperaterData.workBook.GetSheetAt(0);//获取第一张表格,从第二行 开始读取
IRow row;//操作的行数据
for (int i = 1; i <= sheet.LastRowNum; i++)
{
row = sheet.GetRow(i);
if (row == null) continue;
string sheetName = "";
for (int c = 0; c < row.LastCellNum; c++)
{
ICell cell = row.GetCell(c);
string strValue = cell.ToString();
if (c == 1)
{
m_classNames.Add(strValue + "Vo");//类
}
if (c == 0)
{
sheetName = strValue;
Sheet_dic.Add(strValue, null);
}
if (c == row.LastCellNum - 1)
{
bool isSetAutoKey = (row.LastCellNum < 3);
string idKey = "";
if (!isSetAutoKey)
{
idKey = strValue;
}
Sheet_dic[sheetName] = new Tuple<bool, string>(isSetAutoKey, idKey);
}
}
}
}
}
public class OperaterData
{
public IWorkbook workBook;
public void Init(FileStream fileStream, bool isXSS = false)
{
if (isXSS) workBook = new XSSFWorkbook(fileStream);
else
workBook = new HSSFWorkbook(fileStream);
fileStream.Close();
}
}
上面的代码一,我单独封装了一个类来操作,避免看得复杂。第二段的代码是我缓存的工作表。
然后我们开始循环的是遍历所有工作表。文件(循环)->表格1->(循环根据sheet表格开始)
public void ReadExcel()
{
string path = Directory.GetCurrentDirectory() + "/excel/";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
return;
}
DirectoryInfo fileAllInfo = new DirectoryInfo(path);
FileInfo[] fileInfoArray = fileAllInfo.GetFiles();
if (fileInfoArray.Length == 0)
{
if (strGele != null) strGele("没有可以解析的文件...");
return;
}
if (fileInfoArray.Length != 0)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (FileInfo file in fileInfoArray)//每个个表
{
if (strGele != null) strGele("正在操作表:" + file.Name);
ReadOneFile(file.DirectoryName + "\\" + file.Name);
}
}
WriteCShapFile();//写出C#文件
if (updateProgressDelegate != null) { updateProgressDelegate(); }
if (strGele != null) strGele("done.....");
循环的去操作表,然后每次读表的操作抽出这个方法,不然很拥挤 ReadOneFile 需要参数,路径加文件名。
public void ReadOneFile(string filePath)
{
InitSheetClass initSheetClass = new InitSheetClass();
OperaterData operaterData = new OperaterData();
if (filePath.IndexOf(".xlsx") >= 0)
{
operaterData.Init(new FileStream(filePath, FileMode.Open, FileAccess.Read), true);
initSheetClass.InitOneClass(operaterData);
if (initSheetClass.Sheet_dic.Count == initSheetClass.ClassName.Count)//sheet 和 class是必须相等的
{
XlsxReadResult(initSheetClass);
}
else
{
throw new Exception("Sheet 和 类的数量不匹配!");
}
}
else if (filePath.IndexOf(".xls") >= 0)
{
}
if (operaterData.workBook != null)
{
operaterData.workBook.Close();
}
}
XlsxReadResult这边是开始工作表的操作,需要参数,一个已经缓存好的Sheet,包括operaterdata 的 Iwork
其他内表的数据格式如下图:
未完待续…….