При переходе с файлового режима работы базы данных на клиент-серверный (MSSQL) разработчики часто сталкиваются с тем, что привычный импорт данных из Excel перестает работать. Ошибка «Значение не является значением объектного типа (Close)» является лишь следствием того, что объект Excel.Application или его методы не инициализировались должным образом на стороне сервера. Проанализируем причины этой проблемы и разберем по шагам способы ее решения.
Когда мы работаем в файловом режиме, код выполняется на стороне клиента под учетной записью текущего пользователя Windows. В клиент-серверном режиме процедура загрузки чаще всего переносится на сервер. Рассмотрим ситуацию: программа пытается открыть файл, но по какой-то причине (права доступа, отсутствие папок профиля, неверный путь) метод Open() не срабатывает. Если код не содержит должных проверок, программа идет дальше и пытается выполнить Excel.ActiveWorkbook.Close(). Поскольку рабочая книга не была открыта, ActiveWorkbook возвращает Неопределено, что и вызывает ошибку. Выясним, как это исправить.
Проанализируем ситуацию, описанную в сообщениях форума: клиент и сервер 1С находятся на разных машинах. Когда пользователь выбирает файл на своем компьютере (например, C:\Import\data.xlsx), и этот путь передается на сервер, сервер пытается найти этот файл у себя локально. Разумеется, файла там нет.
Правильный алгоритм работы в клиент-серверном режиме:
ПоместитьФайл() или ПоместитьФайлы().Одной из самых «загадочных» причин сбоя COM-объектов Excel на сервере является отсутствие папок профиля для системной службы. Даже если Excel установлен, ему требуются папки Desktop для инициализации интерфейсов автоматизации. Рассмотрим, что нужно сделать:
Необходимо вручную создать папку Desktop по следующим путям (в зависимости от разрядности вашей системы и сервера 1С):
C:\Windows\SysWOW64\config\systemprofile\DesktopC:\Windows\System32\config\systemprofile\DesktopПосле создания папок обязательно предоставьте пользователю, от имени которого запущен сервер 1С (например, USR1CV8), полные права на эти директории.
Если создание папок не помогло, проанализируем настройки компонентов Windows. Сервер 1С обращается к Excel через механизм DCOM. Разберем процесс настройки:
Win+R, введите dcomcnfg и нажмите Enter.Рассмотрим самый надежный способ, который избавляет от необходимости устанавливать Microsoft Office на сервер и мучиться с правами DCOM. Начиная с версии платформы 8.3.6, 1С умеет читать файлы Excel (xlsx) нативно через объект ТабличныйДокумент. Посмотрим на пример кода:
// Создаем объект табличного документа
ТабДок = Новый ТабличныйДокумент;
// Читаем файл напрямую. СпособЧтенияЗначенийТабличногоДокумента.Значение
// позволяет получить данные в их исходном типе (числа, даты)
Попытка
ТабДок.Прочитать(ИмяФайлаНаСервере, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Исключение
Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Теперь мы можем работать с данными как с обычной таблицей 1С
Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
Значение = ТабДок.Область(НомерСтроки, 1).Текст;
// Обработка данных...
КонецЦикла;
Если ваш файл содержит несколько листов, мы можем проанализировать их следующим образом:
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
// Перебор именованных областей (листов)
Для Каждого ОбластьТД ИЗ ТабДок.Области Цикл
Сообщить("Обработка листа: " + ОбластьТД.Имя);
ТекущийЛист = ТабДок.ПолучитьОбласть(ОбластьТД.Имя);
КоличествоСтрок = ТекущийЛист.ПолучитьРазмерОбластиДанныхПоВертикали();
// Дальнейшая загрузка...
КонецЦикла;
Для ускорения процесса, если данных очень много, можно загрузить ТабличныйДокумент сразу в ТаблицуЗначений через ПостроительЗапроса. Посмотрим, как это реализовать:
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
ПЗ = Новый ПостроительЗапроса;
// Указываем область данных табличного документа как источник
ПЗ.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область());
ПЗ.ЗаполнитьНастройки();
ПЗ.Выполнить();
// Получаем готовую таблицу значений
ТаблицаРезультат = ПЗ.Результат.Выгрузить();
Подведем итог: ошибка Close — это симптом «падения» Excel при открытии. Если вы можете отказаться от COM-объектов в пользу ТабличногоДокумента, сделайте это. Это повысит стабильность системы, уберет зависимость от установленного Office и решит проблемы с правами доступа в клиент-серверном режиме.