SpreadsheetLight C# - 按名称将 Excel Table 加载到数据 Table
SpreadsheetLight C# - Load Excel Table by Name into DataTable
我对 SpreadsheetLight 非常满意。但是我忍不住认为我忽略了一些东西。在 Excel 中,您可以 "Format As Table",然后当 table 被选中时,会出现 "Table Tools - Design" 选项卡。您可以更改 Table 非常棒的名称。
然而,我一直在努力寻找一种直接的方法来使用 SpreadsheetLight 加载 excel 文件,然后在工作表上获取 tables。
难道除了反思就没有别的办法了吗?
using SpreadsheetLight;
~~~~~~~
~~~~~~~
~~~~~~~
public DataTable LoadExcelFileTable(string FullFileName)
{
//Load Excel File, get Table Names, compare, Load matching table name into DataTable and return.
string tableName = "Table1";
SLDocument sl = new SLDocument(FullFileName);
sl.SelectWorksheet(SLDocument.DefaultFirstSheetName);
DataTable excelTableDT = GetExcelTablesOfSelectedWorksheet(sl);
//Using table dt can extract data....
return null; //Placeholder for now
}
private DataTable GetExcelTablesOfSelectedWorksheet(SLDocument sl)
{
string sci = "StartColumnIndex";
string sri = "StartRowIndex";
string eci = "EndColumnIndex";
string eri = "EndRowIndex";
DataTable excelTableDT = new DataTable();
excelTableDT.Columns.Add("DisplayName");
excelTableDT.Columns.Add(sci, typeof(int)); // 1 == A, 2 == B
excelTableDT.Columns.Add(sri, typeof(int)); // 1 == 1, 2 == 2
excelTableDT.Columns.Add(eci, typeof(int)); // 1 == A, 2 == B
excelTableDT.Columns.Add(eri, typeof(int)); // 1 == 1, 2 == 2
//Appears it's not made public, we cannot normally access tables and then by name determine start and end cells.
//Reflection to the rescue
FieldInfo slwsFieldInfo = typeof(SLDocument).GetField("slws", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (slwsFieldInfo != null)
{
var b = slwsFieldInfo.GetValue(sl);
if (b != null)
{
var TablesPropInfo = b.GetType().GetProperty("Tables", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (TablesPropInfo != null)
{
var oTables = TablesPropInfo.GetValue(b);
if (oTables != null && oTables is List<SLTable> Tables)
{
if (Tables != null)
{
foreach (SLTable slTable in Tables)
{
//Get the info we need
string DisplayName = slTable.DisplayName;
int StartColumnIndex = Reflection_TryGetIntPropertyValue(slTable, sci);
int StartRowIndex = Reflection_TryGetIntPropertyValue(slTable, sri);
int EndColumnIndex = Reflection_TryGetIntPropertyValue(slTable, eci);
int EndRowIndex = Reflection_TryGetIntPropertyValue(slTable, eri);
//Add to DataTable
excelTableDT.Rows.Add(new object[] { DisplayName, StartColumnIndex, StartRowIndex, EndColumnIndex, EndRowIndex });
}
}
}
}
}
}
return excelTableDT;
}
private int Reflection_TryGetIntPropertyValue(object o, string propertyName)
{
int x = -1;
try
{
var propInfo = o.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (propInfo != null)
{
object val = propInfo.GetValue(o);
if (val != null && val is int yay)
{
x = yay;
}
}
}
catch { }
return x;
}
经过深入研究,我学会了如何使用 Microsoft "DocumentFormat.OpenXml" 获取所有电子表格中的表格,这正是 SpreadsheetLight 在幕后使用的工具。在这一点上,我很乐意通过反射使用这种方法。
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
~~~~~~
~~~~~~
~~~~~~
private DataTable GetExcelTablesFromWorksheets(string FullFileName)
{
DataTable excelTablesDT = new DataTable();
excelTablesDT.Columns.Add("Spreadsheet");
excelTablesDT.Columns.Add("TableName");
excelTablesDT.Columns.Add("CellRange");
excelTablesDT.Columns.Add("HasHeader", typeof(bool));
using (SpreadsheetDocument sd = SpreadsheetDocument.Open(FullFileName, false))
{
if(sd != null && sd.WorkbookPart != null)
{
IEnumerable<Sheet> sheets = sd.WorkbookPart.Workbook.Sheets.Elements<Sheet>();
IEnumerable<WorksheetPart> wsps = sd.WorkbookPart.WorksheetParts;
if (wsps != null)
{
foreach (WorksheetPart wsp in wsps)
{
if (wsp != null)
{
IEnumerable<TableDefinitionPart> tdps = wsp.TableDefinitionParts;
if (tdps != null)
{
foreach (TableDefinitionPart tdp in tdps)
{
if (tdp != null)
{
Table t = tdp.Table;
if (t != null)
{
string Spreadsheet = "";
string SpreadsheetId = sd.WorkbookPart.GetIdOfPart(wsp);
Sheet currentSheet = sheets.FirstOrDefault(s => s.Id.HasValue && s.Id.Value.Equals(SpreadsheetId, StringComparison.OrdinalIgnoreCase));
if(currentSheet != null)
{
Spreadsheet = currentSheet.Name;
}
string TableName = t.DisplayName;
string CellRange = t.Reference.HasValue ? t.Reference.Value : "";
bool hasHeader = !(t.HeaderRowCount != null && t.HeaderRowCount.HasValue && t.HeaderRowCount.Value == 0);
//Add to DataTable
excelTablesDT.Rows.Add(new object[] { Spreadsheet, TableName, CellRange, hasHeader });
}
}
}
}
}
}
}
}
}
return excelTablesDT;
}
我对 SpreadsheetLight 非常满意。但是我忍不住认为我忽略了一些东西。在 Excel 中,您可以 "Format As Table",然后当 table 被选中时,会出现 "Table Tools - Design" 选项卡。您可以更改 Table 非常棒的名称。
然而,我一直在努力寻找一种直接的方法来使用 SpreadsheetLight 加载 excel 文件,然后在工作表上获取 tables。
难道除了反思就没有别的办法了吗?
using SpreadsheetLight;
~~~~~~~
~~~~~~~
~~~~~~~
public DataTable LoadExcelFileTable(string FullFileName)
{
//Load Excel File, get Table Names, compare, Load matching table name into DataTable and return.
string tableName = "Table1";
SLDocument sl = new SLDocument(FullFileName);
sl.SelectWorksheet(SLDocument.DefaultFirstSheetName);
DataTable excelTableDT = GetExcelTablesOfSelectedWorksheet(sl);
//Using table dt can extract data....
return null; //Placeholder for now
}
private DataTable GetExcelTablesOfSelectedWorksheet(SLDocument sl)
{
string sci = "StartColumnIndex";
string sri = "StartRowIndex";
string eci = "EndColumnIndex";
string eri = "EndRowIndex";
DataTable excelTableDT = new DataTable();
excelTableDT.Columns.Add("DisplayName");
excelTableDT.Columns.Add(sci, typeof(int)); // 1 == A, 2 == B
excelTableDT.Columns.Add(sri, typeof(int)); // 1 == 1, 2 == 2
excelTableDT.Columns.Add(eci, typeof(int)); // 1 == A, 2 == B
excelTableDT.Columns.Add(eri, typeof(int)); // 1 == 1, 2 == 2
//Appears it's not made public, we cannot normally access tables and then by name determine start and end cells.
//Reflection to the rescue
FieldInfo slwsFieldInfo = typeof(SLDocument).GetField("slws", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (slwsFieldInfo != null)
{
var b = slwsFieldInfo.GetValue(sl);
if (b != null)
{
var TablesPropInfo = b.GetType().GetProperty("Tables", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (TablesPropInfo != null)
{
var oTables = TablesPropInfo.GetValue(b);
if (oTables != null && oTables is List<SLTable> Tables)
{
if (Tables != null)
{
foreach (SLTable slTable in Tables)
{
//Get the info we need
string DisplayName = slTable.DisplayName;
int StartColumnIndex = Reflection_TryGetIntPropertyValue(slTable, sci);
int StartRowIndex = Reflection_TryGetIntPropertyValue(slTable, sri);
int EndColumnIndex = Reflection_TryGetIntPropertyValue(slTable, eci);
int EndRowIndex = Reflection_TryGetIntPropertyValue(slTable, eri);
//Add to DataTable
excelTableDT.Rows.Add(new object[] { DisplayName, StartColumnIndex, StartRowIndex, EndColumnIndex, EndRowIndex });
}
}
}
}
}
}
return excelTableDT;
}
private int Reflection_TryGetIntPropertyValue(object o, string propertyName)
{
int x = -1;
try
{
var propInfo = o.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (propInfo != null)
{
object val = propInfo.GetValue(o);
if (val != null && val is int yay)
{
x = yay;
}
}
}
catch { }
return x;
}
经过深入研究,我学会了如何使用 Microsoft "DocumentFormat.OpenXml" 获取所有电子表格中的表格,这正是 SpreadsheetLight 在幕后使用的工具。在这一点上,我很乐意通过反射使用这种方法。
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
~~~~~~
~~~~~~
~~~~~~
private DataTable GetExcelTablesFromWorksheets(string FullFileName)
{
DataTable excelTablesDT = new DataTable();
excelTablesDT.Columns.Add("Spreadsheet");
excelTablesDT.Columns.Add("TableName");
excelTablesDT.Columns.Add("CellRange");
excelTablesDT.Columns.Add("HasHeader", typeof(bool));
using (SpreadsheetDocument sd = SpreadsheetDocument.Open(FullFileName, false))
{
if(sd != null && sd.WorkbookPart != null)
{
IEnumerable<Sheet> sheets = sd.WorkbookPart.Workbook.Sheets.Elements<Sheet>();
IEnumerable<WorksheetPart> wsps = sd.WorkbookPart.WorksheetParts;
if (wsps != null)
{
foreach (WorksheetPart wsp in wsps)
{
if (wsp != null)
{
IEnumerable<TableDefinitionPart> tdps = wsp.TableDefinitionParts;
if (tdps != null)
{
foreach (TableDefinitionPart tdp in tdps)
{
if (tdp != null)
{
Table t = tdp.Table;
if (t != null)
{
string Spreadsheet = "";
string SpreadsheetId = sd.WorkbookPart.GetIdOfPart(wsp);
Sheet currentSheet = sheets.FirstOrDefault(s => s.Id.HasValue && s.Id.Value.Equals(SpreadsheetId, StringComparison.OrdinalIgnoreCase));
if(currentSheet != null)
{
Spreadsheet = currentSheet.Name;
}
string TableName = t.DisplayName;
string CellRange = t.Reference.HasValue ? t.Reference.Value : "";
bool hasHeader = !(t.HeaderRowCount != null && t.HeaderRowCount.HasValue && t.HeaderRowCount.Value == 0);
//Add to DataTable
excelTablesDT.Rows.Add(new object[] { Spreadsheet, TableName, CellRange, hasHeader });
}
}
}
}
}
}
}
}
}
return excelTablesDT;
}