Чтение/запись файла Excel без установки чего-либо

У меня есть файл 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, но я хочу сделать это без установки дополнительного ПО.

Как это сделать?


person user4773407    schedule 03.03.2021    source источник
comment
Отвечает ли это на ваш вопрос? 'Microsoft.ACE.OLEDB .12.0' провайдер не зарегистрирован на локальном компьютере   -  person Zev Spitz    schedule 03.03.2021
comment
нет, мне не нужны какие-либо плагины или дополнительные установленные файлы, мне нужно знать, как настроить соединение с помощью собственного кода   -  person user4773407    schedule 03.03.2021
comment
Вы хотите перепроектировать весь драйвер? Это около 50 МБ кода ... Самое близкое, что вы могли бы сделать, это проверить, установлен ли у вас драйвер, и вы используете неправильную разрядность; или, может быть, вы могли бы использовать более старую версию установленного драйвера.   -  person Zev Spitz    schedule 03.03.2021
comment
нет, конечно, я не мог перепроектировать весь драйвер, я думаю, что драйвер обрабатывает слишком много случаев или опций, я думал, что соединение ACE можно настроить с помощью нескольких строк кода.   -  person user4773407    schedule 03.03.2021
comment
Его можно настроить с помощью нескольких строк кода (пример), но вам нужен соответствующий драйвер; не пытаясь установить отсутствующий драйвер или пытаясь использовать альтернативный драйвер, ваши единственные варианты: 1. реконструировать весь драйвер и систему ADODB или 2. использовать возможности чтения, извлечения и анализа XML-файлов .NET для извлечь данные из этого файла.   -  person Zev Spitz    schedule 03.03.2021
comment
второй вариант выглядит простым и приятным, можете дать мне старт, заранее спасибо   -  person user4773407    schedule 03.03.2021
comment
Второй вариант выглядит просто по сравнению с первым вариантом; не потому, что это объективно легко, просто или красиво. Вам нужно знать внутреннюю файловую структуру файла .xlsx -- какие файлы куда помещаются; какой файл содержит данные, которые вы ищете; и какая структура XML используется для определения данных. В общем, это почти так же сложно и хрупко, как реверс-инжиниринг провайдера. // Поддерживаете ли вы свою версию Windows в актуальном состоянии? Вы используете последнюю версию браузера? Вы должны посмотреть на эту инсталляцию в том же свете.   -  person Zev Spitz    schedule 04.03.2021
comment
Я переименовал .xlsx в .zip, и я обнаружил, что это коллекция файлов .xml. Я думаю, что редактировать файлы xml проще, чем устанавливать соединение с помощью кода, хотя я все еще хочу узнать это когда-нибудь большое спасибо за помощь   -  person user4773407    schedule 04.03.2021
comment
Я переписал и вопрос, и ответ; Я думаю, что намерение теперь более ясно. Если изменения не будут одобрены вами, не стесняйтесь откатывать их или оставлять комментарии.   -  person Zev Spitz    schedule 13.04.2021


Ответы (1)


Для начала у вас вполне может быть уже установлен драйвер, но только для 32-битных программ, а ваша программа работает под 64-битной (или наоборот, но это реже).

Вы можете указать определенную среду в файле .csproj. Чтобы принудительно установить 32-битную версию, используйте:

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

и принудительно 64-битный:

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

Если драйвер был установлен в другой среде, ваш код должен успешно подключиться.

NB. Вы можете перечислить доступных поставщиков для текущей среды, используя следующий код:

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, начиная с Windows 2000 (доступен только для 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);
    }
};

Примечание. Я обнаружил, что для обновления данных мне нужно удалить значение 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, поддерживающий как чтение, так и запись. Я думаю, это является хорошей отправной точкой — он показывает, как читать из данной ячейки, и как записывать информацию обратно в ячейку.

person Zev Spitz    schedule 03.03.2021
comment
Уважаемый, я буду использовать код в своем вопросе для чтения данных из файла Excel, но этот код дает мне ошибку «microsoft.ace.oledb.12.0 не зарегистрирован на локальном компьютере», мне нужно знать, как исправить эту ошибку msg из моего приложения программно, а не вручную и не устанавливая никаких плагинов - person user4773407; 03.03.2021
comment
@user4773407 user4773407 Я полагаю, если бы вы действительно хотели, вы могли бы прочитать файл Excel с диска, извлечь его в виде ZIP-файла на диск, прочитать результирующие XML-файлы и извлечь данные таким образом. (Очевидно, вы даже не хотите использовать OpenXML SDK.) Я имею в виду, как далеко вы вы хотите зайти чтобы ничего не устанавливать? Хочешь писать на ассемблере? - person Zev Spitz; 03.03.2021
comment
я искал, чтобы читать данные из файла excel и снова писать в него, читать имена листов и столбцы на каждом листе, просто читать запись, а не уравнения или графики или редактировать представление ячеек - person user4773407; 03.03.2021
comment
@user4773407 user4773407 И выбранный вами подход - подключение с использованием OLEDB и ADO.NET даст вам именно это. Но он зависит от возможности использования соответствующего поставщика — поставщика Microsoft.ACE.OLEDB.12.0 — что означает, что поставщик должен быть установлен и в соответствующую разрядность для вашего кода. - person Zev Spitz; 03.03.2021
comment
Я не уверен, что означает ( битность ), поэтому есть ли какой-либо другой подход для достижения того, что я ищу, без установки каких-либо дополнительных плагинов? - person user4773407; 03.03.2021
comment
@ user4773407 Разрядность в этом контексте означает, что провайдер может быть установлен под 32-разрядной версией, и в этом случае его могут использовать только программы, работающие под 32-разрядной версией; или под 64-разрядной версией, и в этом случае его могут использовать только программы, работающие под 64-разрядной версией. (Провайдер может быть установлен в обоих.) - person Zev Spitz; 03.03.2021