c# - 仅当 Excel 文件实际在 Ms Excel 中打开时才能读取 Excel 文件

标签 c# excel

我使用以下代码打开 Excel 文件 (XLS) 并使用第一个工作表填充 DataTable:

var connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0; data source={0}; Extended Properties=Excel 8.0;", filename);

OleDbConnection connExcel = new OleDbConnection(connectionString);
connExcel.Open();
DataTable dtExcelSchema;
dtExcelSchema = connExcel.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string SheetName = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
connExcel.Close();

var adapter = new OleDbDataAdapter("SELECT * FROM [" + SheetName + "]", connectionString);
var ds = new DataSet();
int count = 0;

adapter.Fill(ds, SheetName);

DataTable dt = ds.Tables[0];

仅当文件已在 Ms Excel 中打开时才有效。为什么会这样?

如果文件未打开,我会收到一条错误消息(在线connExcel.Open):外部表不是预期的格式。

最佳答案

我面临着同样的问题,根据这个网站,许多开发人员都在为同样的问题而苦苦挣扎:

-When I try read Excel with OLE DB all values are empty

-Can't connect to excel file unless file is already open

实际上我正在使用经典的连接字符串(请注意,我正在尝试读取 97/2003 文件):

Provider=Microsoft.Jet.OLEDB.4.0; Data Source = " + GetFilename(filename) + "; Extended Properties ='Excel 8.0;HDR=NO;IMEX=1'

但只有在以下情况下才能正确读取文件:

  • 在 Excel 中打开,甚至在 Word 中打开! (文件当然看起来已损坏且无法读取,但 OleDb 过程可以读取文件的每一行),我没有尝试使用其他 Office 应用程序

  • 文件不是只读模式

我也尝试过手动锁定文件或用其他非办公应用程序打开它,但结果不一样。如果我遵循前面的两条规则(在 Word 或 Excel 中以非只读模式打开的文件),我可以看到所有单元格,否则似乎第一列被完全忽略(因此 F2 变为 F1, F3 变成了 F2,...最后一个 F6 应该变成 F5,否则会抛出索引外错误)。

为了在不使用第三方库的情况下保持与 OleDb 的兼容性,我发现了一个使用 Microsoft.Office.Interop.Excel 程序集的非常愚蠢的解决方法。

Excel.Application _app = new Excel.Application();
var workbooks = _app.Workbooks;
workbooks.Open(_filename);

// OleDb Connection
using (OleDbConnection conn = new OleDbConnection(connectionOleDb))
            {
                try
                {
                    conn.Open();
                    OleDbCommand cmd = new OleDbCommand();
                    cmd.Connection = conn;

                    cmd.CommandText = String.Format("SELECT * FROM [{0}$]", tableName);
OleDbDataReader myReader = cmd.ExecuteReader();

                    int i = 0;
                    while (myReader.Read())
                    {
                        //Here I read through all Excel rows
                    }


                }
                catch (Exception E)
                {
                    MessageBox.Show("Error!\n" + E.Message);
                }
                finally
                {
                    conn.Close();

                    workbooks.Close();
                    if (workbooks != null)
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
                    _app.Quit();
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(_app);
                }
            }

本质上,前 3 行运行一个 Excel 实例,该实例的持续时间恰好是 OleDb 执行其任务所需的时间。 最后 4 行,在finally block 内,让Excel实例在任务结束后立即正确关闭,并避免幽灵Excel进程。

我再说一遍,这是一个非常愚蠢的解决方法,还需要将 1.5 MB 的 dll (Microsoft.Office.Interop.Excel.dll) 添加到项目中。 无论如何,OleDb 无法自行管理丢失的数据似乎是不可能的......

关于c# - 仅当 Excel 文件实际在 Ms Excel 中打开时才能读取 Excel 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34883829/

相关文章:

c# - c# 中的并行和工作划分?

c# - 如何避免 web.config 中的 session 超时

mysql - SQL查询将Excel表中的列添加到mysql表中?

python - 展平双嵌套 JSON

java - 如何在通过java创建的Excel工作表中设置整数值?

java - 读取不带标题的 POI Excel 文件

c# - 找不到类型或命名空间名称 'ICloudRecoEventHandler'

c# - WCF 错误 "The socket connection has been disposed"

c# - .Net Excel 添加帮助

c# - 如何从 *.dll 中检索所有公共(public)方法