SpreadsheetLight C# - 按名称将Excel表加载到DataTable

时间:2018-06-05 22:02:16

标签: c# excel spreadsheet spreadsheetlight

我对SpreadsheetLight非常满意。但是我不禁想到我忽略了一些东西。在Excel中,您可以“格式化为表格”,然后在选择表格时,将出现“表格工具 - 设计”选项卡。您可以更改表名,这很棒。

但是我一直在努力寻找一种直接的方式来使用SpreadsheetLight来加载excel文件,然后在工作表上获取表格。

除了诉诸反思之外没有别的办法吗?

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;
}

1 个答案:

答案 0 :(得分:0)

经过一些深入的研究,我学会了如何使用Microsoft&#34; DocumentFormat.OpenXml&#34;在所有电子表格上获取表格。这就是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;
}