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

C#读取Excel时遇COM对象转String类型错误求助

C# Interop Excel读取单元格字符串值报错解决方案

问题背景

编写C#读取Excel的测试代码时,已解决Microsoft.Office.Interop.Excel.dll未找到的问题(将DLL复制到运行目录),但当前获取单元格值时出现无法将System.__ComObject类型的COM对象强制转换为System.String类型的错误。已添加Close()和Quit()避免Excel进程残留,尝试过String.Format和强制转换为Excel.Range,仍无法正常获取单元格字符串值。

原代码如下:

namespace ExcelReadTestProject {
    using System;
    using System.IO;
    using Excel = Microsoft.Office.Interop.Excel;

    class ExcelReadTest {
        static void Main(string[] args) {
            if ( args.Length==0 ) {
                Console.WriteLine("ExcelReadTest [fullpath_to_excel_file]\n\nExcelReadTest \"C:\Users\User\Documents\ExcelReadTest.xlsx\"");
            } else if ( !System.IO.File.Exists(args[0]) ) {  // file specified not found
                Console.WriteLine("File \"{0}\" not found");
            } else if ( args[0].IndexOf('\\')<0 ) {  // full path not specified
                Console.WriteLine("Need to specify full path to file \"{0}\"");
            } else {
                Excel.Application app = new Excel.Application();
                app.Visible = false;  // run hidden or minimized
                Excel.Workbook wkbook = app.Workbooks.Open(args[0]);
                Excel.Worksheet wksheet = (Excel.Worksheet)wkbook.Sheets[1];
                Excel.Range cells = wksheet.UsedRange;
                int row = 1;
                QRecords recs = new QRecords();
                while ( cells.Cells[row,1]!=null ) {
                    Console.WriteLine("{0},{1},{2}",String.Format("{0}",(Excel.Range)cells.Cells[row,1].Value),String.Format("{0}",(Excel.Range)cells.Cells[row,2].Value),String.Format("{0}",(Excel.Range)cells.Cells[row,3].Value));
                    row++;
                }
                wkbook.Close(0);  // need to close workbook
                app.Quit();  // need to quit EXCEL process
            }
        }
    }
}

问题分析

  1. 错误的取值方式:cells.Cells[row,1].Value返回的是COM对象的包装实例,直接强制转换为Excel.Range或用String.Format无法正确解析为字符串,必须先提取值再转换。
  2. 无效的循环终止条件:cells.Cells[row,1]!=null永远为true,因为COM对象即使对应单元格为空,也不会返回null,会导致无限循环。
  3. 资源释放不彻底:仅调用Close()和Quit()可能无法完全释放COM对象,仍会残留Excel进程。

解决方案

关键修改点

  • 安全取值:使用Convert.ToString()处理单元格Value,结合?? string.Empty处理空值,避免空引用和类型转换错误。
  • 修正循环逻辑:通过判断单元格内容是否为空或限制循环行数来终止循环。
  • 完善资源释放:用try-catch-finally包裹操作,确保即使出错也能关闭Excel,并调用Marshal.ReleaseComObject彻底释放COM资源。

修改后的完整代码

namespace ExcelReadTestProject {
    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    using Excel = Microsoft.Office.Interop.Excel;

    class ExcelReadTest {
        static void Main(string[] args) {
            if ( args.Length == 0 ) {
                Console.WriteLine("ExcelReadTest [fullpath_to_excel_file]\n\nExcelReadTest \"C:\\Users\\User\\Documents\\ExcelReadTest.xlsx\"");
                return;
            }

            if ( !File.Exists(args[0]) ) {
                Console.WriteLine($"File \"{args[0]}\" not found");
                return;
            }

            if ( args[0].IndexOf('\\') < 0 ) {
                Console.WriteLine($"Need to specify full path to file \"{args[0]}\"");
                return;
            }

            Excel.Application app = null;
            Excel.Workbook wkbook = null;
            Excel.Worksheet wksheet = null;
            Excel.Range cells = null;

            try {
                app = new Excel.Application();
                app.Visible = false;
                wkbook = app.Workbooks.Open(args[0]);
                wksheet = (Excel.Worksheet)wkbook.Sheets[1];
                cells = wksheet.UsedRange;
                int row = 1;

                // 循环读取直到第一列单元格为空,或超出已使用范围行数
                while (row <= cells.Rows.Count) {
                    // 安全获取单元格值并转为字符串
                    string cellVal1 = Convert.ToString(cells.Cells[row, 1].Value ?? string.Empty);
                    string cellVal2 = Convert.ToString(cells.Cells[row, 2].Value ?? string.Empty);
                    string cellVal3 = Convert.ToString(cells.Cells[row, 3].Value ?? string.Empty);

                    // 如果第一列为空,停止循环(可根据实际需求调整判断条件)
                    if (string.IsNullOrWhiteSpace(cellVal1)) break;

                    Console.WriteLine($"{cellVal1},{cellVal2},{cellVal3}");
                    row++;
                }
            } catch (Exception ex) {
                Console.WriteLine($"读取错误: {ex.Message}");
            } finally {
                // 关闭工作簿,参数false表示不保存
                if (wkbook != null) wkbook.Close(false);
                // 退出Excel应用
                if (app != null) {
                    app.Quit();
                    // 释放COM对象,避免进程残留
                    Marshal.ReleaseComObject(app);
                }
            }
        }
    }
}

补充说明

  • 如果需要获取单元格显示的格式化文本(而非原始值),可以将cells.Cells[row, 1].Value替换为cells.Cells[row, 1].Text。
  • 确保项目已正确引用Microsoft.Office.Interop.Excel组件,而非仅复制DLL到运行目录(推荐通过NuGet安装Microsoft.Office.Interop.Excel包)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 07:27:46