Загрузка данных из внешних файлов Excel — одна из самых частых задач в практике программиста 1С. Однако при использовании классического метода через COM-объект Excel.Application разработчики часто сталкиваются с загадочными ошибками вроде «Неизвестная ошибка» при вызове метода Open. В рамках данной статьи мы подробно разберем, почему возникают эти проблемы, как настроить сервер для корректной работы COM и рассмотрим альтернативный, более современный способ загрузки данных с помощью встроенных средств платформы 1С.
Рассмотрим ситуацию, когда при выполнении кода ЭксельКнига = Эксель.Workbooks.Open(ПутьКФайлу); система выдает исключение. Если код выполняется на стороне сервера, основной причиной является то, что Microsoft Excel — это интерактивное приложение, которое «ожидает» наличия пользовательского окружения (рабочего стола, временных папок профиля). Когда сервер 1С (служба USR1CV8) пытается запустить Excel в фоновом режиме, он не находит необходимых директорий и завершает работу с ошибкой.
Проанализируем основные факторы, блокирующие работу:
Если вам критически важно использовать именно COM-соединение (например, для сложного форматирования или использования специфических макросов), выполним следующие шаги для настройки сервера.
Во-первых, необходимо вручную создать папки Desktop для системного профиля. Путь зависит от разрядности вашей операционной системы:
C:\Windows\SysWOW64\config\systemprofile\DesktopC:\Windows\System32\config\systemprofile\DesktopПосле создания папок убедитесь, что пользователь USR1CV8 (или тот, под которым работает сервер 1С) имеет к ним полный доступ. Также рассмотрим настройку через Службы компонентов (DCOM). Найдите в списке Microsoft Excel Application, перейдите в свойства и на вкладке «Удостоверение» попробуйте установить переключатель в положение «Текущий пользователь» или укажите данные конкретной учетной записи администратора.
Посмотрим на пример рабочего кода, который позволяет прочитать данные из двух колонок Excel (например, ИНН и КПП) и добавить их в табличную часть на форме. Разберем пошагово процесс открытия и обхода строк.
СтандартнаяОбработка = Ложь;
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выбор файла Excel";
Диалог.Фильтр = "Excel файлы(*.xls;*.xlsx)|*.xls;*.xlsx";
Если Диалог.Выбрать() Тогда
ПутьКФайлу = Диалог.ПолноеИмяФайла;
Иначе
Возврат;
КонецЕсли;
Попытка
// Пытаемся создать объект Excel
Эксель = Новый COMОбъект("Excel.Application");
Эксель.DisplayAlerts = 0; // Отключаем уведомления
Эксель.Visible = 0; // Делаем окно невидимым
Исключение
Сообщить("Ошибка при запуске Excel: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
Попытка
ЭксельКнига = Эксель.Workbooks.Open(ПутьКФайлу);
Лист = ЭксельКнига.Sheets(1); // Работаем с первым листом
// Определяем количество строк через SpecialCells(11) - это последняя ячейка
КоличествоСтрок = Лист.Cells(1, 1).SpecialCells(11).Row;
Для НомерСтроки = 1 По КоличествоСтрок Цикл
// Читаем значения ячеек
ЗначениеИНН = Лист.Cells(НомерСтроки, 1).Value;
ЗначениеКПП = Лист.Cells(НомерСтроки, 2).Value;
Если ЗначениеЗаполнено(ЗначениеИНН) Тогда
НоваяСтрока = Объект.ТЧКлиенты.Добавить();
НоваяСтрока.ИНН = СокрЛП(ЗначениеИНН);
НоваяСтрока.КПП = СокрЛП(ЗначениеКПП);
КонецЕсли;
КонецЦикла;
ЭксельКнига.Close(Ложь);
Эксель.Quit();
Исключение
Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
Эксель.Quit();
КонецПопытки;
Важный совет: Всегда используйте блоки Попытка ... Исключение и обязательно вызывайте Эксель.Quit(), иначе в памяти сервера будут накапливаться «зависшие» процессы excel.exe, что со временем приведет к сбою всей системы.
Современная платформа 1С позволяет читать файлы Excel напрямую, без установленного Microsoft Office на компьютере или сервере. Этот метод гораздо быстрее, стабильнее и работает даже на серверах под управлением Linux. Проанализируем, как это реализовать.
Выясним преимущества этого метода: он не требует регистрации COM-компонентов и не зависит от прав доступа к системным профилям Windows. Мы читаем файл в объект ТабличныйДокумент, а затем преобразуем его в ТаблицаЗначений.
// 1. Читаем файл в табличный документ
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ПутьКФайлу);
Исключение
Сообщить("Не удалось прочитать файл: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// 2. Определяем область данных (весь лист)
Область = ТабДок.Область(1, 1, ТабДок.ВысотаТаблицы, ТабДок.ШиринаТаблицы);
// 3. Используем ПостроительЗапроса для быстрой выгрузки в Таблицу Значений
Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(Область);
Построитель.Выполнить();
ТЗРезультат = Построитель.Результат.Выгрузить();
// 4. Загружаем данные в табличную часть объекта
// Важно: имена колонок в ТЗ будут Колонка1, Колонка2 и т.д.
Для Каждого СтрокаДанных Из ТЗРезультат Цикл
НоваяСтрока = Объект.ТЧКлиенты.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаДанных, "ИНН, КПП");
// Если имена колонок не совпадают, используем прямое присваивание:
НоваяСтрока.ИНН = СтрокаДанных.Колонка1;
НоваяСтрока.КПП = СтрокаДанных.Колонка2;
КонецЦикла;
При работе с экранными формами начинающие разработчики часто совершают ошибку, пытаясь напрямую присвоить таблицу значений переменной табличной части: ТЧКлиенты = ТЗРезультат;. Рассмотрим, почему это не работает. В 1С табличная часть — это объект коллекции, и для работы с ней нужно использовать специальные методы.
Если вам нужно полностью заменить данные в табличной части, используйте метод Загрузить():
// Имена колонок в ТЗРезультат должны СТРОГО совпадать с именами колонок ТЧ
Объект.ТЧКлиенты.Загрузить(ТЗРезультат);
Если же вы хотите добавить данные к уже существующим, лучше использовать цикл с методом Добавить(), как показано в предыдущих примерах. Это позволит вам дополнительно валидировать данные (например, проверять ИНН на корректность) перед записью.
Подведем итог: использование COM-объекта оправдано только в редких случаях, когда требуется сложная обработка файлов. В большинстве ситуаций (простая загрузка строк и колонок) лучшим выбором будет ТабличныйДокумент. Это обеспечит высокую скорость работы и отсутствие проблем с правами доступа на сервере.