【问题标题】:Open XML - read certain excel cells打开 XML - 读取某些 excel 单元格
【发布时间】:2019-03-08 10:30:00
【问题描述】:

我需要使用 OpenXML 循环 .xlsx 行。当单元格值与我的字符串匹配时,我需要从下一列同一行的单元格中读取值。这是我目前所拥有的:

using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fs, false))
    {
        WorkbookPart workbookPart = doc.WorkbookPart;
        SharedStringTablePart sstpart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
        SharedStringTable sst = sstpart.SharedStringTable;
        WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
        Worksheet sheet = worksheetPart.Worksheet;
        var rows = sheet.Descendants<Row>();

        foreach (Row row in rows)
        {
            foreach (Cell c in row.Elements<Cell>())
            {
                if ((c.DataType != null) && (c.DataType == CellValues.SharedString))
                {
                    int ssid = int.Parse(c.CellValue.Text);
                    string str = sst.ChildElements[ssid].InnerText;

                    if (str == "Date of birth:")
                    {
                        Cell next_cell = row.Descendants<Cell>().ElementAt(ssid + 1);
                        MessageBox.Show(next_cell.CellValue.Text);
                    }
                }
            }
        }
    }
}

这并没有显示来自正确单元格的值,所以请有人指出我在 OpenXML 中执行此操作的正确方法。

编辑:很高兴知道如何在循环外定义一个单元格。

【问题讨论】:

    标签: c# openxml


    【解决方案1】:

    找到正确的 Row 后,您将使用共享字符串表 (ssid) 的索引,而不是 Row 的索引。

    有多种方法可以修复它,但基本上您需要转到下一个 Row 的值,而不是恰好与下一个共享字符串索引匹配的 Row

    最接近您当前代码的方法是在循环时保持单元格的索引并使用它来索引Row

    using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fs, false))
        {
            WorkbookPart workbookPart = doc.WorkbookPart;
            SharedStringTablePart sstpart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
            SharedStringTable sst = sstpart.SharedStringTable;
            WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
            Worksheet sheet = worksheetPart.Worksheet;
            var rows = sheet.Descendants<Row>();
    
            foreach (Row row in rows)
            {
                int cellIndex = 0;
    
                foreach (Cell c in row.Elements<Cell>())
                {
                    if ((c.DataType != null) && (c.DataType == CellValues.SharedString))
                    {
                        int ssid = int.Parse(c.CellValue.Text);
                        string str = sst.ChildElements[ssid].InnerText;
    
                        if (str == "Date of birth:")
                        {
                            Cell next_cell = row.Descendants<Cell>().ElementAt(cellIndex + 1);
                            MessageBox.Show(next_cell.CellValue.Text);
                        }
                    }
    
                    cellIndex++;
                }
            }
        }
    }
    

    根据您的需要,还有其他方法,例如更改为for 循环或直接获取枚举器,如this answer 中所述。

    【讨论】:

    • 感谢您的回复,这可能对我有所帮助。除此之外,您是否知道我如何在循环外定义一个单元格?这对我的帮助更大。我找到了这个 [链接] (stackoverflow.com/questions/11722808/…),但没有什么对我有用? ....我为此编辑了问题。
    • @Lucy82 - 我不确定你所说的“在循环外定义一个单元格”是什么意思,你能详细说明一下吗?
    • 当然。我的问题是我需要在某些列下保存 Excel 文件的值。所以首先我需要搜索带有列标题的单元格以获取列索引,以便从 For Each 中获取所需的值。问题是因为在 For Each 语句代码中只读取 SharedString 值并忽略数字和日期时间类型,所以它跳过行 if ((c.DataType != null) && (c.DataType == CellValues.SharedString))....然后很难将所需的数据与列链接。我希望你现在能更好地理解。
    • @Lucy82 - 听起来您需要在第一行找到您感兴趣的每个单元格的索引(类似于我上面的代码中的cellIndex),然后在后续行中您可以迭代单元格,直到您到达您感兴趣的索引并从该单元格中获取值。只要你在if ((c.DataType... 代码之外增加你的计数器就可以了吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多