Как получить имена вкладок из листа excel с помощью OpenXML
у меня есть документ электронной таблицы, в котором есть 182 столбца. Мне нужно поместить данные электронной таблицы в таблицу данных, вкладку за вкладкой, но мне нужно узнать, как я добавляю данные с каждой вкладки, каково имя вкладки, и добавить имя вкладки в столбец в таблице данных.
вот как я настраиваю таблицу данных.
затем я зацикливаюсь в рабочей книге и детализируюсь до sheetData объект и пройдите через каждую строку и столбец, получая данные ячейки. 
DataTable dt = new DataTable();
for (int i = 0; i <= col.GetUpperBound(0); i++)
{
    try
    {
        dt.Columns.Add(new DataColumn(col[i].ToString(), typeof(string)));
    }
    catch (Exception e)
    {
        MessageBox.Show("Uploader  Error" + e.ToString());
        return null;
    }
}
dt.Columns.Add(new DataColumn("SheetName", typeof(string)));
однако в конце строкового массива, который я использую для таблицы данных, мне нужно добавить имя вкладки. Как я могу узнать имя вкладки, когда я зацикливаюсь на листе в Open XML?
вот мой код до сих пор:
using (SpreadsheetDocument spreadSheetDocument = 
           SpreadsheetDocument.Open(Destination, false))
{
    WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
    Workbook workbook = spreadSheetDocument.WorkbookPart.Workbook;
    Sheets sheets = 
        spreadSheetDocument
            .WorkbookPart
            .Workbook
            .GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
    OpenXmlElementList list = sheets.ChildElements;
    foreach (WorksheetPart worksheetpart in workbook.WorkbookPart.WorksheetParts)
    {
        Worksheet worksheet = worksheetpart.Worksheet;
        foreach (SheetData sheetData in worksheet.Elements<SheetData>())
        {
            foreach (Row row in sheetData.Elements())
            {
                string[] thisarr = new string[183];
                int index = 0;
                foreach (Cell cell in row.Elements())
                {
                    thisarr[(index)] = GetCellValue(spreadSheetDocument, cell);
                    index++;
                }
                thisarr[182] = ""; //need to add tabname here
                if (thisarr[0].ToString() != "")
                {
                    dt.Rows.Add(thisarr);
                }
            }
        }
    }
}
return dt;
просто примечание: Я ранее получил имена вкладок из свойства InnerXML "list" в
OpenXmlElementList list = sheets.ChildElements;
однако я заметил, как я зацикливаюсь в электронной таблице, он не получает имена вкладок в правильном порядке.
4 ответов
имена листов хранятся в WorkbookPart на Sheets элемент, который имеет дочерние элементы элемента Sheet который соответствует каждому листу в файле Excel. Все, что вам нужно сделать, это захватить правильный индекс из этого Sheets элемент и Sheet вы находитесь в цикле. Я добавил фрагмент кода, чтобы сделать то, что вы хотите.
int sheetIndex = 0;
foreach (WorksheetPart worksheetpart in workbook.WorkbookPart.WorksheetParts)
{                     
    Worksheet worksheet = worksheetpart.Worksheet;
    // Grab the sheet name each time through your loop
    string sheetName = workbookPart.Workbook.Descendants<Sheet>().ElementAt(sheetIndex).Name;
    foreach (SheetData sheetData in worksheet.Elements<SheetData>())
    {
       ...
    }
    sheetIndex++;
}
вот удобный вспомогательный метод, чтобы получить лист, соответствующий WorksheetPart:
public static Sheet GetSheetFromWorkSheet
    (WorkbookPart workbookPart, WorksheetPart worksheetPart)
{
    string relationshipId = workbookPart.GetIdOfPart(worksheetPart);
    IEnumerable<Sheet> sheets = workbookPart.Workbook.Sheets.Elements<Sheet>();
    return sheets.FirstOrDefault(s => s.Id.HasValue && s.Id.Value == relationshipId);
}
затем вы можете получить имя из листа Name-property:
Sheet sheet = GetSheetFromWorkSheet(myWorkbookPart, myWorksheetPart);
string sheetName = sheet.Name;
...это будет" имя вкладки", на которое ссылается OP.
для записи противоположный метод будет выглядеть так:
public static Worksheet GetWorkSheetFromSheet(WorkbookPart workbookPart, Sheet sheet)
{
    var worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id);
    return worksheetPart.Worksheet;
}
...и с этим мы также можем добавить следующий метод:
public static IEnumerable<KeyValuePair<string, Worksheet>> GetNamedWorksheets
    (WorkbookPart workbookPart)
{
    return workbookPart.Workbook.Sheets.Elements<Sheet>()
        .Select(sheet => new KeyValuePair<string, Worksheet>
            (sheet.Name, GetWorkSheetFromSheet(workbookPart, sheet)));
}
теперь вы можете легко перечислить все листы, включая их имя.
бросьте все это в словарь для поиска на основе имен, если вы предпочитаете это:
IDictionary<string, WorkSheet> wsDict = GetNamedWorksheets(myWorkbookPart)
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
...или если вы просто хотите один конкретный лист на имя:
public static Sheet GetSheetFromName(WorkbookPart workbookPart, string sheetName)
{
    return workbookPart.Workbook.Sheets.Elements<Sheet>()
        .FirstOrDefault(s => s.Name.HasValue && s.Name.Value == sheetName);
}
(тогда называть GetWorkSheetFromSheet чтобы получить соответствующий рабочий лист.)
    Using spreadsheetDocument As SpreadsheetDocument = spreadsheetDocument.Open("D:\Libro1.xlsx", True)
        Dim workbookPart As WorkbookPart = spreadsheetDocument.WorkbookPart
        workbookPart.Workbook.Descendants(Of Sheet)()
        Dim worksheetPart As WorksheetPart = workbookPart.WorksheetParts.Last
        Dim text As String
        For Each Sheet As Sheet In spreadsheetDocument.WorkbookPart.Workbook.Sheets
            Dim sName As String = Sheet.Name
            Dim sID As String = Sheet.Id
            Dim part As WorksheetPart = workbookPart.GetPartById(sID)
            Dim actualSheet As Worksheet = part.Worksheet
            Dim sheetData As SheetData = part.Worksheet.Elements(Of SheetData)().First
            For Each r As Row In sheetData.Elements(Of Row)()
                For Each c As Cell In r.Elements(Of Cell)()
                    text = c.CellValue.Text
                    Console.Write(text & " ")
                Next
            Next
        Next
    End Using
    Console.Read()
