我使用以下代码打开 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/