【问题标题】:Reading cell value with applied Text formatting with OpenXML使用 OpenXML 应用文本格式读取单元格值
【发布时间】:2022-11-13 04:53:08
【问题描述】:

我正在尝试阅读 Excel 工作表,其中包含具有文本格式的单元格。

某些列具有值11.11.2 等。

在 Excel 中,所有这些值在具有文本格式的单元格中看起来都不错 - 11.11.2

但是当我用 OpenXML 读取这些单元格时,我得到了值11.10000000000000011.2——其中一些有小数部分。

好的,我在 *.xlsx 文件中检查了 xl\worksheets\sheet1.xml,我看到,它确实包含值 1.1000000000000001

<row r="3" spans="1:20" ht="15" x14ac:dyDescent="0.25">
            <c r="A3" s="2">
                <v>1.1000000000000001</v>
            </c>

我的代码是:

 List<List<string>> rows = new List<List<string>>();

            List<string> cols;

            spreadsheetDocument = SpreadsheetDocument.Open(excelFilePath, false);

            WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
            WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
            SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();

            SharedStringTablePart sstpart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
            SharedStringTable sst = sstpart.SharedStringTable;

            foreach (Row r in sheetData.Elements<Row>())
            {
                cols = new List<string>();
                foreach (Cell c in r.Elements<Cell>())
                {
                    if (c.DataType != null && c.DataType == CellValues.SharedString)
                    {
                        int ssid = int.Parse(c.CellValue.Text);
                        string str = sst.ChildElements[ssid].InnerText;
                        cols.Add(str);
                    }
                    else
                    {
                        cols.Add(c.CellValue?.InnerText);
                    }
                }
                rows.Add(cols);
            }

            spreadsheetDocument.Close();

我该如何从这些单元格中获得正确的值?例如,1.1,但不是1.1000000000000001

【问题讨论】:

  • 与其尝试阅读原始 XML,为什么不使用像 EPPlus、ClosedXML、NPOI 这样的库?所有这些代码都可以简化为workSheet.Cells[1,1].Text
  • 主要目标 - 使用支持微软的库,而不是第三方库。
  • 在这种情况下,您根本无法使用 .NET。所有版本,包括 .NET Framework 和 .NET Core 都依赖于 NuGet 包,甚至是 JSON.NET 等第三方库。如果不使用“第三方”库,您将无法做任何事情
  • 事实上,微软本身强烈建议使用第三方开源库而不是弃用的类like SmtpClient

标签: c# .net openxml openxml-sdk


【解决方案1】:

首先创建此方法以获取单元格的值。

public static string GetCellValue(WorkbookPart workbookPart, Cell cell)
{
    string value = null;
    if (cell.InnerText.Length > 0)
    {
        value = cell.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 (cell.DataType != null)
        {
            switch (cell.DataType.Value)
            {
                case CellValues.SharedString:

                    // For shared strings, look up the value in the
                    // shared strings table.
                    var stringTable =
                        workbookPart.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:
                    value = value switch
                    {
                        "0" => "FALSE",
                        _ => "TRUE",
                    };
                    break;
            }
        }
    }
    return value;
}

然后将此代码用于您的内部 for 循环:

foreach (Cell c in r.Elements<Cell>())
{
    string str = GetCellValue(workbookPart, c);
    cols.add(str);
}

GetCellValue 方法的灵感来自于this page 上的 Microsoft 文档

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    相关资源
    最近更新 更多