16

我需要使用 Open XML SDK 2.0 从 Excel 2007 工作簿中的单个工作表中读取数据。我花了很多时间寻找这样做的基本指南,但我只找到了有关创建电子表格的帮助。

如何使用此 SDK 迭代工作表中的行,然后迭代每行中的单元格?

4

2 回答 2

31

另一个答案似乎更像是一个元答案。我一直在努力解决这个问题,因为使用 LINQ 确实可以处理单独的文档部分。以下代码包含一个包装函数,用于从 Cell 获取值,解析任何可能的字符串查找。

public void ExcelDocTest()
{
    Debug.WriteLine("Running through sheet.");
    int rowsComplete = 0;

    using (SpreadsheetDocument spreadsheetDocument =
                    SpreadsheetDocument.Open(@"path\to\Spreadsheet.xlsx", false))
    {
        WorkbookPart workBookPart = spreadsheetDocument.WorkbookPart;

        foreach (Sheet s in workBookPart.Workbook.Descendants<Sheet>())
        {
            WorksheetPart wsPart = workBookPart.GetPartById(s.Id) as WorksheetPart;
            Debug.WriteLine("Worksheet {1}:{2} - id({0}) {3}", s.Id, s.SheetId, s.Name,
                wsPart == null ? "NOT FOUND!" : "found.");

            if (wsPart == null)
            {
                continue;
            }

            Row[] rows = wsPart.Worksheet.Descendants<Row>().ToArray();

            //assumes the first row contains column names 
            foreach (Row row in wsPart.Worksheet.Descendants<Row>())
            {
                rowsComplete++;

                bool emptyRow = true;
                List<object> rowData = new List<object>();
                string value;

                foreach (Cell c in row.Elements<Cell>())
                {
                    value = GetCellValue(c);
                    emptyRow = emptyRow && string.IsNullOrWhiteSpace(value);
                    rowData.Add(value);
                }

                Debug.WriteLine("Row {0}: {1}", row,
                    emptyRow ? "EMPTY!" : string.Join(", ", rowData));
            }
        }

    }
    Debug.WriteLine("Done, processed {0} rows.", rowsComplete);
}

public static string GetCellValue(Cell cell)
{
    if (cell == null)
        return null;
    if (cell.DataType == null)
        return cell.InnerText;

    string value = cell.InnerText;
    switch (cell.DataType.Value)
    {
        case CellValues.SharedString:
            // For shared strings, look up the value in the shared strings table.
            // Get worksheet from cell
            OpenXmlElement parent = cell.Parent;
            while (parent.Parent != null && parent.Parent != parent
                    && string.Compare(parent.LocalName, "worksheet", true) != 0)
            {
                parent = parent.Parent;
            }
            if (string.Compare(parent.LocalName, "worksheet", true) != 0)
            {
                throw new Exception("Unable to find parent worksheet.");
            }

            Worksheet ws = parent as Worksheet;
            SpreadsheetDocument ssDoc = ws.WorksheetPart.OpenXmlPackage as SpreadsheetDocument;
            SharedStringTablePart sstPart = ssDoc.WorkbookPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();

            // lookup value in shared string table
            if (sstPart != null && sstPart.SharedStringTable != null)
            {
                value = sstPart.SharedStringTable.ElementAt(int.Parse(value)).InnerText;
            }
            break;

        //this case within a case is copied from msdn. 
        case CellValues.Boolean:
            switch (value)
            {
                case "0":
                    value = "FALSE";
                    break;
                default:
                    value = "TRUE";
                    break;
            }
            break;
    }
    return value;
}

编辑:感谢@Nitin-Jadhav对 GetCellValue() 的更正。

于 2012-11-02T20:46:11.630 回答
13

我这样做的方法是使用 Linq。从使用 SDK 到仅使用纯 Open XML(无 SDK),有很多关于这个主题的示例。看一眼:

于 2010-04-13T15:50:14.500 回答