无需安装任何东西即可读取/写入 Excel 文件

时间:2021-03-03 13:29:01

标签: c# excel ms-jet-ace

我有一个 Excel .xlsx 文件。我想从文件中读取数据并将数据写回文件;没有图形、方程、图像,只有数据。

我尝试使用 System.Data.OleDb 中的类型进行连接:

using System.Data.OleDb;

var fileName = @"C:\ExcelFile.xlsx";
var connectionString =
    "Provider=Microsoft.ACE.OLEDB.12.0;" +
    $"Data Source={fileName};" +
    "Extended Properties=\"Excel 12.0;HDR=NO;TypeGuessRows=0;ImportMixedTypes=Text\"";

using var conn = new OleDbConnection(connectionString);
conn.Open();

但我收到以下错误:

<块引用>

“Microsoft.ACE.OLEDB.12.0”提供程序未在本地计算机上注册。

我知道我可以安装 Microsoft Access Database Engine 2016 Redistributable,但我不想安装其他软件。

我该怎么做?

1 个答案:

答案 0 :(得分:0)

对于初学者来说,您可能已经安装了驱动程序,但仅适用于 32 位程序,而您的程序在 64 位下运行(反之亦然,但这种情况不太常见)。

您可以在 .csproj 文件中强制使用特定环境。要强制使用 32 位,请使用:

<PropertyGroup>
  <PlatformTarget>x86</PlatformTarget>
</PropertyGroup>

并强制使用 64 位:

<PropertyGroup>
  <PlatformTarget>x64</PlatformTarget>
</PropertyGroup>

如果驱动程序已经安装在其他环境中,您的代码应该可以成功连接。

注意。您可以使用如下代码列出当前环境的可用提供程序:

using System.Data;
using System.Data.OleDb;
using System.Linq;
using static System.Console;

var oleEnum = new OleDbEnumerator();
var data =
    oleEnum.GetElements()
        .Rows
        .Cast<DataRow>()
        .Select(row => (
            name: row["SOURCES_NAME"] as string,
            descr: row["SOURCES_DESCRIPTION"] as string
        ))
        .OrderBy(descr => descr);
foreach (var (name, descr) in data) {
    WriteLine($"{name,-30}{descr}");
}

如果您在任一环境中都没有 Microsoft.ACE.OLEDB.12.0 提供程序怎么办?如果您可以将 .xlsx 文件转换为 .xls 文件,则可以使用 Microsoft Jet 4.0 OLE DB Provider,它自 Windows 2000 以来已安装在每个版本的 Windows 中(仅适用于 32 位) .

如上将 PlatformTarget 设置为 x86(32 位)。然后,编辑连接字符串以使用旧的提供程序:

using System.Data.OleDb;

var fileName = @"C:\ExcelFile.xls";
// note the changes to Provider and the first value in Extended Properties
var connectionString =
    "Provider=Microsoft.Jet.OLEDB.4.0;" +
    $"Data Source={fileName};" +
    "Extended Properties=\"Excel 8.0;HDR=NO;TypeGuessRows=0;ImportMixedTypes=Text\"";

using var conn = new OleDbConnection(connectionString);
conn.Open();

一旦您打开了 OleDbConnection,您就可以使用标准的 ADO .NET 命令习语来读取和写入数据以与数据源交互:

using System.Data;
using System.Data.OleDb;

var ds = new DataSet();
using (var conn = new OleDbConnection(connectionString)) {
    conn.Open();

    // assuming the first worksheet is called Sheet1

    using (var cmd = conn.CreateCommand()) {
        cmd.CommandText = "UPDATE [Sheet1$] SET Field1 = \"AB\" WHERE Field2 = 2";
        cmd.ExecuteNonQuery();
    }

    using (var cmd1 = conn.CreateCommand()) {
        cmd1.CommandText = "SELECT * FROM [Sheet1$]";
        var adapter = new OleDbDataAdapter(cmd);
        adapter.Fill(ds);
    }
};

注意。我发现为了更新数据,我需要根据 this answer 从连接字符串中删除 IMEX=1 值。


如果必须使用 .xlsx 文件,并且只需要从 Excel 文件中读取数据,则可以在项目中使用 ExcelDataReader NuGet 包。

然后,您可以编写如下代码:

using System.IO;
using ExcelDataReader;

// The following line is required on .NET Core / .NET 5+
// see https://github.com/ExcelDataReader/ExcelDataReader#important-note-on-net-core
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

DataSet ds = null;
using (var stream = File.Open(@"C:\ExcelFile.xlsx", FileMode.Open, FileAccess.Read)) {
    using var reader = ExcelReaderFactory.CreateReader(stream);
    ds = reader.AsDataSet();
}

您可能会考虑的另一种替代方法是使用 Office Open XML SDK,它支持读取和写入。我认为 this 是一个很好的起点——它展示了如何从给定的单元格读取信息,以及如何将信息写回单元格。

相关问题