解析Excel电子表格的单元格值

时间:2021-07-31 12:08:26

标签: c# excel openxml spreadsheet openxml-sdk

我解析位于 A2 地址中的单元格。这将返回 3 值而不是预期的 类别 1

test.xlsx

enter image description here

using System;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using X = DocumentFormat.OpenXml.Spreadsheet;

namespace DotNetSandbox.SO
{
    public class IncorrectCellValue
    {
        public static void ParseCellValue()
        {
            using SpreadsheetDocument doc = SpreadsheetDocument.Open(@"c:\temp\test.xlsx", false);
            X.Sheet sheet = doc.WorkbookPart.Workbook.Descendants<X.Sheet>().First();
            WorksheetPart wsPart = (WorksheetPart)doc.WorkbookPart.GetPartById(sheet.Id);
            X.Cell cell = wsPart.Worksheet.Descendants<X.Cell>().First(c => c.CellReference == "A2");

            string cellValue = cell.CellValue.Text;

            Console.WriteLine(cellValue);
            Console.ReadKey();
        }
    }
}

输出:

<块引用>

3


  • 目标:.NET 5
  • DocumentFormat.OpenXml 版本:2.13.0

我做错了什么或者是图书馆的错误?

1 个答案:

答案 0 :(得分:1)

使用这个方法

 public static string GetCellValue(string fileName,
        string addressName, string sheetName = "")
    {
        string value = null;

        // Open the spreadsheet document for read-only access.
        using (SpreadsheetDocument document =
            SpreadsheetDocument.Open(fileName, false))
        {
            // Retrieve a reference to the workbook part.
            WorkbookPart wbPart = document.WorkbookPart;

            // Find the sheet with the supplied name, and then use that 
            // Sheet object to retrieve a reference to the first worksheet.
            var theSheets = wbPart.Workbook.Descendants<Sheet>();
            Sheet theSheet = string.IsNullOrEmpty(sheetName) ? theSheets.FirstOrDefault() : theSheets.FirstOrDefault(x => x.Name == sheetName);

            // Throw an exception if there is no sheet.
            if (theSheet == null)
            {
                throw new ArgumentException("sheetName");
            }

            // Retrieve a reference to the worksheet part.
            WorksheetPart wsPart =
                (WorksheetPart)(wbPart.GetPartById(theSheet.Id));

            // Use its Worksheet property to get a reference to the cell 
            // whose address matches the address you supplied.
            Cell theCell = wsPart.Worksheet.Descendants<Cell>().
              Where(c => c.CellReference == addressName).FirstOrDefault();

            // If the cell does not exist, return an empty string.
            if (theCell.InnerText.Length > 0)
            {
                value = theCell.InnerText;

                // If the cell represents an integer number, you are done. 
                // For dates, this code returns the serialized value that 
                // represents the date. The code handles strings and 
                // Booleans individually. For shared strings, the code 
                // looks up the corresponding value in the shared string 
                // table. For Booleans, the code converts the value into 
                // the words TRUE or FALSE.
                if (theCell.DataType != null)
                {
                    switch (theCell.DataType.Value)
                    {
                        case CellValues.SharedString:

                            // For shared strings, look up the value in the
                            // shared strings table.
                            var stringTable =
                                wbPart.GetPartsOfType<SharedStringTablePart>()
                                .FirstOrDefault();

                            // If the shared string table is missing, something 
                            // is wrong. Return the index that is in
                            // the cell. Otherwise, look up the correct text in 
                            // the table.
                            if (stringTable != null)
                            {
                                value =
                                    stringTable.SharedStringTable
                                    .ElementAt(int.Parse(value)).InnerText;
                            }
                            break;

                        case CellValues.Boolean:
                            switch (value)
                            {
                                case "0":
                                    value = "FALSE";
                                    break;
                                default:
                                    value = "TRUE";
                                    break;
                            }
                            break;
                    }
                }
            }
        }
        return value;
    }

你卡在这里了:

<块引用>

如果单元格代表一个整数,你就完成了。 对于日期,此代码返回序列化值 代表日期。该代码处理字符串和 单独的布尔值。对于共享字符串,代码 在共享字符串中查找对应的值 桌子。对于布尔值,代码将值转换为 TRUE 或 FALSE 这个词。

通过运行此代码,我能够获得第 1 类:

 var cellValue = GetCellValue(@"c:\test.xlsx", "A2");

Microsoft Doc

请注意,如果您不将工作表名称传递给方法,我将原始方法更改为获取第一张工作表。

什么是共享字符串: 为了优化电子表格中字符串的使用,SpreadsheetML 将字符串的单个实例存储在称为共享字符串表的表中。然后,单元格按索引引用字符串,而不是将值内联存储在单元格值中。 Excel 在保存文件时总是创建一个共享字符串表。