Пакетная выгрузка данных из 1С в Microsoft Excel с использованием объекта COMSafeArray — один из самых быстрых способов передачи больших объемов информации через COM-соединение. Однако при присвоении заполненного массива свойству диапазона Range.Value разработчики часто сталкиваются с исключением Произошла исключительная ситуация (0x800a03ec). Разберем по шагам причины этой ошибки и способы ее устранения.
Проанализируем природу взаимодействия 1С и Microsoft Excel. COM-интерфейс Excel ожидает стандартные OLE-типы данных (числа, строки, булевы значения, даты). Если в таблице значений присутствуют объекты 1С сложных или ссылочных типов, COM-маршалер не может выполнить их автоматическое преобразование.
К ошибке 0x800a03ec приводят следующие типы значений в ячейках:
СправочникСсылка), документов (ДокументСсылка), перечислений и планов видов характеристик. Перед помещением в массив их обязательно нужно приводить к строковому представлению с помощью функции Строка() или получать необходимые реквизиты (например, наименование или код).Null и Неопределено: эти типы могут вызывать сбой при передаче через вариантную структуру VT_VARIANT. Их рекомендуется заменять на пустую строку "" или число 0.0001-01-01) находится за пределами допустимого диапазона дат Excel (исчисление начинается с 1900 года). Пустую дату следует выгружать как пустую строку.Выясним еще одну частую проблему — расчет границ ячеек. Количество строк и колонок в объекте COMSafeArray должно строго совпадать с количеством строк и колонок в целевом диапазоне Range. Если в вычислениях конечной ячейки допущена ошибка со смещением индексов (так называемая ошибка «на единицу»), Excel не сможет сопоставить матрицу данных с диапазоном и вернет исключение.
Рассмотрим правильный алгоритм пакетной выгрузки таблицы значений в Excel. Создадим двумерный COMSafeArray с типом VT_VARIANT, выполним явное приведение типов для каждой ячейки и запишем данные в точно рассчитанный диапазон ячеек.
// Получаем исходную таблицу значений
ТЗ = Построитель.Результат.Выгрузить();
КоличествоСтрок = ТЗ.Количество();
КоличествоКолонок = ТЗ.Колонки.Количество();
Если КоличествоСтрок = 0 Тогда
Возврат;
КонецЕсли;
// Допустим, нам нужно выгрузить колонки начиная с 4-й (индекс 3)
ИндексНачалаКолонок = 3;
ЧислоВыгружаемыхКолонок = КоличествоКолонок - ИндексНачалаКолонок;
// Создаем COM-массив: измерения (КоличествоКолонок, КоличествоСтрок)
МассивКом = Новый COMSafeArray("VT_VARIANT", ЧислоВыгружаемыхКолонок, КоличествоСтрок);
Для ИндСтроки = 0 По КоличествоСтрок - 1 Цикл
СтрокаТЗ = ТЗ[ИндСтроки];
Для ИндКолонки = 0 По ЧислоВыгружаемыхКолонок - 1 Цикл
ТекущееЗначение = СтрокаТЗ[ИндКолонки + ИндексНачалаКолонок];
// Нормализация типов данных
Если ТекущееЗначение = Неопределено Или ТекущееЗначение = Null Тогда
ЗначениеДляExcel = "";
ИначеЕсли ТипЗнч(ТекущееЗначение) = Тип("Дата") И Не ЗначениеЗаполнено(ТекущееЗначение) Тогда
ЗначениеДляExcel = "";
ИначеЕсли ТипЗнч(ТекущееЗначение) = Тип("Число") Или ТипЗнч(ТекущееЗначение) = Тип("Булево") Тогда
ЗначениеДляExcel = ТекущееЗначение;
ИначеЕсли ТипЗнч(ТекущееЗначение) = Тип("Строка") Тогда
ЗначениеДляExcel = ТекущееЗначение;
Иначе
// Все ссылочные и составные типы приводим к строке
ЗначениеДляExcel = Строка(ТекущееЗначение);
КонецЕсли;
// Установка значения в COMSafeArray (Колонка, Строка)
МассивКом.SetValue(ИндКолонки, ИндСтроки, ЗначениеДляExcel);
КонецЦикла;
КонецЦикла;
// Задаем начальные координаты вставки на листе Excel (строка 15, колонка 1)
НачальнаяСтрока = 15;
НачальнаяКолонка = 1;
КонечнаяСтрока = НачальнаяСтрока + КоличествоСтрок - 1;
КонечнаяКолонка = НачальнаяКолонка + ЧислоВыгружаемыхКолонок - 1;
// Получаем диапазон точного размера и передаем массив
Ячейка1 = Sheet.Cells(НачальнаяСтрока, НачальнаяКолонка);
Ячейка2 = Sheet.Cells(КонечнаяСтрока, КонечнаяКолонка);
Диапазон = Sheet.Range(Ячейка1, Ячейка2);
Диапазон.Value = МассивКом;
Посмотрим на дополнительные нюансы, которые помогут избежать ошибок при интеграции:
Value вызовет исключительную ситуацию.COMSafeArray и COM-сервером Excel возможна только в операционной системе Windows. При работе на сервере под управлением Linux следует формировать отчеты через ТабличныйДокумент с последующим вызовом метода Записать в формате XLSX.