You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#读取OpenXML的CellValue返回十六进制值 如何获取Excel实际存储值

问题原因

你当前的代码仅处理了*共享字符串(SharedString)*类型的单元格,对DataType == null的单元格直接读取原始文本,这会导致读取结果不符合预期:
OpenXML中DataType为null时,单元格默认存储的是数值类型原始值,如果单元格实际是日期、百分比、货币等带格式的类型,原始值是OLE自动化日期数值、未格式化的原始数字,并非Excel界面中展示的格式化值,你误以为的十六进制格式实际是未转换的OLE日期值或者科学计数法格式的原始数字字符串。

解决方案

你需要补充处理不同的单元格类型,增加日期、布尔值、数值的转换逻辑,修改后的完整代码如下:

foreach (Row row in sheetData.Elements<Row>())
{
    ArrayList data = new ArrayList();
    if (!firstRow)
    {
        var firstCol = true;
        foreach (Cell cell in row.Elements<Cell>())
        {
            if (!firstCol)
            {
                object cellValue = string.Empty;
                // 处理带明确DataType的单元格
                if (cell.DataType != null)
                {
                    switch (cell.DataType.Value)
                    {
                        // 共享字符串类型
                        case CellValues.SharedString:
                            if (int.TryParse(cell.InnerText, out int id))
                            {
                                cellValue = workbookPart.SharedStringTablePart.SharedStringTable
                                    .Elements<SharedStringItem>().ElementAt(id).InnerText;
                            }
                            break;
                        // 布尔类型
                        case CellValues.Boolean:
                            cellValue = cell.InnerText == "1";
                            break;
                        // 内联字符串
                        case CellValues.InlineString:
                            cellValue = cell.InnerText;
                            break;
                        // 错误值统一返回空
                        case CellValues.Error:
                            cellValue = string.Empty;
                            break;
                    }
                }
                // 处理数值/日期类型(DataType默认为null)
                else if (cell.CellValue != null)
                {
                    string rawValue = cell.CellValue.Text;
                    // 先判断是否为日期格式
                    if (IsCellDateType(cell, workbookPart) && double.TryParse(rawValue, out double oleDate))
                    {
                        cellValue = DateTime.FromOADate(oleDate);
                    }
                    // 再判断是否为普通数值
                    else if (double.TryParse(rawValue, out double number))
                    {
                        cellValue = number;
                    }
                    // 其他情况直接返回原始文本
                    else
                    {
                        cellValue = rawValue;
                    }
                }
                data.Add(cellValue);
            }
            else
            {
                firstCol = false;
            }
        }
        rowList.Add(data);
    }
    else 
    {
        firstRow = false;
    }
}

新增判断单元格是否为日期格式的辅助方法:

private static bool IsCellDateType(Cell cell, WorkbookPart workbookPart)
{
    if (cell.StyleIndex == null) 
        return false;
    CellFormat cellFormat = (CellFormat)workbookPart.WorkbookStylesPart.Stylesheet.CellFormats
        .ElementAt((int)cell.StyleIndex.Value);
    uint formatId = cellFormat.NumberFormatId;
    // Excel标准日期格式的NumberFormatId范围
    return (formatId is >= 14 and <= 22) 
           || (formatId is >= 27 and <= 36) 
           || (formatId is >= 45 and <= 47) 
           || (formatId is >= 50 and <= 58)
           || formatId >= 81;
}

补充说明

如果需要获取和Excel界面展示完全一致的格式化文本,可以根据NumberFormatId对应的格式规则,将原始数值格式化为对应字符串,比如格式ID为10对应mm-dd-yy,格式ID为2对应0.00。


内容的提问来源于stack exchange,提问作者Nayab Raheel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 15:54:04