.net 使用OpenXML读取应用了文本格式的单元格值

ecfdbz9o  于 2022-11-19  发布在  .NET
关注(0)|答案(1)|浏览(154)

我正在尝试读取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

5lhxktic

5lhxktic1#

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

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方法的灵感来源于Microsoft的this page文档

相关问题