При работе с большими объемами данных в Excel стандартные механизмы OLE Automation (использование объекта Excel.Application) часто демонстрируют низкую производительность. В ситуациях, когда файлы содержат десятки тысяч строк, процесс записи может «зависать» или потреблять чрезмерное количество системных ресурсов. В таких случаях на помощь приходит технология ADO (ActiveX Data Objects), которая позволяет работать с листом Excel как с полноценной базой данных. Разберем подробно, как правильно настроить подключение и выполнить запись или изменение значений в ячейках.
Проанализируем типичную ситуацию: программист успешно открывает файл для чтения, но при попытке изменить значение в Recordset или вызвать метод Update получает отказ. Основная причина кроется в настройках провайдера и параметрах открытия набора записей. По умолчанию многие подключения открываются в режиме «только чтение» или с типом курсора, который не предполагает изменения данных. Чтобы решить эту проблему, необходимо последовательно настроить три составляющих: строку подключения, параметры самого объекта RecordSet и, в некоторых случаях, настройки системного реестра.
Выясним, какие параметры строки подключения критичны для записи. Рассмотрим два основных провайдера: Microsoft.ACE.OLEDB.12.0 (для файлов .xlsx и .xlsm) и Microsoft.Jet.OLEDB.4.0 (для старых файлов .xls).
Важным параметром является Mode. Для возможности записи необходимо явно указать Mode=ReadWrite или использовать числовое значение 3. Также обратите внимание на параметр IMEX.
Посмотрим на пример формирования строки подключения для формата XLSX:
ПутьКФайлу = "C:\my_folder\data.xlsx";
СтрокаПодключения = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ПутьКФайлу + ";";
// Добавляем параметры расширенных свойств
// HDR=NO означает, что первая строка — это данные, а не заголовки
// IMEX=0 позволяет производить запись
СтрокаПодключения = СтрокаПодключения + "Extended Properties=""Excel 12.0 Xml;HDR=NO;IMEX=0"";";
// Устанавливаем режим доступа к файлу
СтрокаПодключения = СтрокаПодключения + "Mode=ReadWrite;";
Connection = Новый COMОбъект("ADODB.Connection");
Connection.Open(СтрокаПодключения);
Даже если соединение открыто на запись, объект RecordSet по умолчанию может создаваться с типом «ForwardOnly» и блокировкой «ReadOnly». Чтобы иметь возможность менять значения Fields(...).Value, проанализируем необходимые свойства:
Разберем пример кода для изменения значения в первой строке третьей колонки:
RecordSet = Новый COMОбъект("ADODB.RecordSet");
RecordSet.ActiveConnection = Connection;
RecordSet.CursorType = 3;
RecordSet.LockType = 3;
// Запрос к листу. Не забываем про знак $ в конце имени листа
ТекстЗапроса = "SELECT * FROM [Лист1$]";
RecordSet.Open(ТекстЗапроса);
Если НЕ RecordSet.EOF Тогда
// Обращаемся к колонке по индексу (начиная с 0)
// Записываем новое значение в третью колонку (индекс 2)
RecordSet.Fields(2).Value = "Тестовое значение ADO";
// КРИТИЧЕСКИ ВАЖНО: вызвать метод Update для сохранения изменений
RecordSet.Update();
КонецЕсли;
RecordSet.Close();
Connection.Close();
Иногда удобнее не перебирать строки в RecordSet, а отправить прямой SQL-запрос на обновление. Это особенно эффективно, если нужно изменить конкретную ячейку или диапазон, зная условия.
Проанализируем синтаксис обращения к диапазонам. В ADO лист Excel воспринимается как таблица, а диапазон ячеек — как подмножество этой таблицы. Если мы используем HDR=NO, то имена колонок будут генерироваться автоматически как F1, F2, F3 и так далее.
// Пример обновления значения в колонке F2, где в колонке F1 стоит определенный код
Команда = Новый COMОбъект("ADODB.Command");
Команда.ActiveConnection = Connection;
// Обновляем диапазон ячеек с A2 по C100 на Листе1
// Устанавливаем значение в колонке F2 для строки, где F1 = 'Товар123'
ТекстSQL = "UPDATE [Лист1$A2:C100] SET F2 = '1500' WHERE F1 = 'Товар123'";
Команда.CommandText = ТекстSQL;
Команда.CommandType = 1; // adCmdText
Команда.Execute();
Рассмотрим подводные камни, с которыми часто сталкиваются разработчики при внедрении ADO для Excel:
TypeGuessRows. Если установить его в 0, драйвер будет сканировать все строки, что надежнее, но медленнее.Microsoft Access Database Engine. Если 1С 32-битная — соответственно 32-битный. Установка обеих версий на одну машину требует использования ключа /passive при инсталляции драйвера.DELETE не поддерживается драйвером Excel. Вы можете только обновлять ячейки (например, записывать туда пустые строки или нули), но физически удалить строку листа через ADO нельзя.Резюме: Для успешного изменения данных в Excel через ADO всегда проверяйте наличие Mode=ReadWrite в строке подключения, устанавливайте LockType = 3 для RecordSet и обязательно вызывайте метод Update(). Этот метод значительно ускорит выгрузку сложных отчетов из 1С в Excel по сравнению с классическим OLE.