Как использовать API OpenXML для чтения таблицы из электронной таблицы Excel?
Я прочитал кучу материала в интернете о том, как получить данные о ячейках с помощью API OpenXML. Но на самом деле там не так уж много того, что особенно прямолинейно. Большинство из них, похоже, посвящено написанию в SpreadsheetML, а не чтению... но даже это не очень помогает. У меня есть электронная таблица, в которой есть таблица. Я знаю, как называется таблица, и могу узнать, на каком листе она находится и какие столбцы в таблице. Но я не могу понять, как вернуть коллекцию строк обратно. содержите данные в таблице.
У меня есть это, чтобы загрузить документ и получить дескриптор книги:
SpreadsheetDocument document = SpreadsheetDocument.Open("file.xlsx", false);
WorkbookPart workbook = document.WorkbookPart;
У меня есть это, чтобы найти таблицу / лист:
Table table = null;
foreach (Sheet sheet in workbook.Workbook.GetFirstChild<Sheets>())
{
WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheet.Id);
foreach (TableDefinitionPart tableDefinitionPart in worksheetPart.TableDefinitionParts)
{
if (tableDefinitionPart.Table.DisplayName == this._tableName)
{
table = tableDefinitionPart.Table;
break;
}
}
}
И я могу перебирать столбцы в таблице, предварительно перейдя по таблице.Столовые ложки.
2 ответа:
, Чтобы прочитать файл Excel 2007/2010 таблицу с помощью инструкции OpenXML API является очень легко. Как-то даже проще, чем использовать OleDB, как мы всегда делали, как быстрое и грязное решение. Кроме того, это не просто простой, но подробный, я думаю, что помещать весь код здесь не полезно, если его нужно комментировать и объяснять, поэтому я напишу только резюме и свяжу хорошую статью. Прочитайте эту статью на MSDN, она объясняет, как читать документы XLSX очень простым способом.
Просто чтобы подведите итог, вы сделаете это:
- откройте
SpreadsheetDocument
с помощьюSpreadsheetDocument.Open
.- получите
Sheet
, который вам нужен, с помощью запроса LINQ изWorkbookPart
документа.- получить (наконец-то!)
WorksheetPart
(нужный вам объект), используя идентификаторSheet
.В коде, удаление комментариев и обработка ошибок:
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, false)) { Sheet sheet = document.WorkbookPart.Workbook .Descendants<Sheet>() .Where(s => s.Name == sheetName) .FirstOrDefault(); WorksheetPart sheetPart = (WorksheetPart)(document.WorkbookPart.GetPartById(theSheet.Id)); }
Теперь (но внутри использования!) то, что вам нужно сделать, это просто прочитать значение ячейки:
Cell cell = sheetPart.Worksheet.Descendants<Cell>(). Where(c => c.CellReference == addressName).FirstOrDefault();
Если вам нужно перечислить строки (а их много), вы должны сначала чтобы получить ссылку на объект
SheetData
:SheetData sheetData = sheetPart.Worksheet.Elements<SheetData>().First();
Теперь вы можете задать для всех строк и ячеек:
foreach (Row row in sheetData.Elements<Row>()) { foreach (Cell cell in row.Elements<Cell>()) { string text = cell.CellValue.Text; // Do something with the cell value } }
Чтобы просто перечислить нормальную электронную таблицу, вы можете использовать
Descendants<Row>()
объектаWorksheetPart
.Если вам нужно больше ресурсов о OpenXML посмотрите наOpenXML Developer , он содержит много хороших учебников.
Вероятно, есть много лучших способов закодировать это, но я собрал это вместе, потому что мне это было нужно, так что, надеюсь, это поможет некоторым другим.
using DocumentFormat.OpenXml.Spreadsheet; using DocumentFormat.OpenXml.Packaging; private static DataTable genericExcelTable(FileInfo fileName) { DataTable dataTable = new DataTable(); try { using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fileName.FullName, false)) { Workbook wkb = doc.WorkbookPart.Workbook; Sheet wks = wkb.Descendants<Sheet>().FirstOrDefault(); SharedStringTable sst = wkb.WorkbookPart.SharedStringTablePart.SharedStringTable; List<SharedStringItem> allSSI = sst.Descendants<SharedStringItem>().ToList<SharedStringItem>(); WorksheetPart wksp = (WorksheetPart)doc.WorkbookPart.GetPartById(wks.Id); foreach (TableDefinitionPart tdp in wksp.TableDefinitionParts) { QueryTablePart qtp = tdp.QueryTableParts.FirstOrDefault<QueryTablePart>(); Table excelTable = tdp.Table; int colcounter = 0; foreach (TableColumn col in excelTable.TableColumns) { DataColumn dcol = dataTable.Columns.Add(col.Name); dcol.SetOrdinal(colcounter); colcounter++; } SheetData data = wksp.Worksheet.Elements<SheetData>().First(); foreach (DocumentFormat.OpenXml.Spreadsheet.Row row in data) { if (isInTable(row.Descendants<Cell>().FirstOrDefault(), excelTable.Reference, true)) { int cellcount = 0; DataRow dataRow = dataTable.NewRow(); foreach (Cell cell in row.Elements<Cell>()) { if (cell.DataType != null && cell.DataType.InnerText == "s") { dataRow[cellcount] = allSSI[int.Parse(cell.CellValue.InnerText)].InnerText; } else { dataRow[cellcount] = cell.CellValue.Text; } cellcount++; } dataTable.Rows.Add(dataRow); } } } } //do whatever you want with the DataTable return dataTable; } catch (Exception ex) { //handle an error return dataTable; } } private static Tuple<int, int> returnCellReference(string cellRef) { int startIndex = cellRef.IndexOfAny("0123456789".ToCharArray()); string column = cellRef.Substring(0, startIndex); int row = Int32.Parse(cellRef.Substring(startIndex)); return new Tuple<int,int>(TextToNumber(column), row); } private static int TextToNumber(string text) { return text .Select(c => c - 'A' + 1) .Aggregate((sum, next) => sum * 26 + next); } private static bool isInTable(Cell testCell, string tableRef, bool headerRow){ Tuple<int, int> cellRef = returnCellReference(testCell.CellReference.ToString()); if (tableRef.Contains(":")) { int header = 0; if (headerRow) { header = 1; } string[] tableExtremes = tableRef.Split(':'); Tuple<int, int> startCell = returnCellReference(tableExtremes[0]); Tuple<int, int> endCell = returnCellReference(tableExtremes[1]); if (cellRef.Item1 >= startCell.Item1 && cellRef.Item1 <= endCell.Item1 && cellRef.Item2 >= startCell.Item2 + header && cellRef.Item2 <= endCell.Item2) { return true; } else { return false; } } else if (cellRef.Equals(returnCellReference(tableRef))) { return true; } else { return false; } }