При автоматизации Microsoft Excel через COM-объект программисты 1С часто сталкиваются с ситуацией, когда один и тот же код прекрасно работает на клиенте, но выдает «Неизвестную ошибку» при выполнении на сервере. Особенно это касается методов работы с графическими объектами, таких как AddPicture. Рассмотрим подробно причины этой проблемы и разберем по шагам все способы ее решения.
Типичный сценарий начинается с простого кода, который должен открыть книгу и вставить в нее изображение. Проанализируем пример, который часто приводит к ошибке на сервере:
ExcelDoc = Новый COMОбъект("Excel.Application");
ExcelDoc.Visible = Ложь;
РабочаяКнига = ExcelDoc.WorkBooks.Open("C:\1.xls");
ExcelDoc.ActiveSheet.Shapes.AddPicture("C:\1.jpg", Истина, Истина, 100, 100, 70, 70).Select();
Основная сложность здесь заключается в том, что серверный процесс 1С работает в неинтерактивном режиме под учетной записью службы (обычно usr1cv8), у которой нет рабочего стола и графической оболочки. Это накладывает серьезные ограничения на работу графического движка Excel.
Выясним одну из главных технических причин: несоответствие разрядности сервера 1С и установленного Microsoft Office. Если сервер 1С является 64-битным (x64), а Microsoft Excel установлен 32-битный (x86), возникают ошибки при передаче данных через COM-интерфейс, особенно при работе со сложными объектами типа Shapes.
Что нужно сделать: Для стабильной работы на сервере разрядность Excel должна совпадать с разрядностью сервера 1С. Если вы используете 64-битный сервер 1С, установите 64-битную версию Microsoft Office. Как показывает практика, это решает проблему «Неизвестной ошибки» в большинстве случаев.
Проанализируем специфику работы Windows. Excel при инициализации графических методов (вставка картинок, работа с диаграммами) требует наличия папки рабочего стола в профиле пользователя, даже если приложение запущено в фоновом режиме. У системной службы usr1cv8 таких папок по умолчанию может не быть.
Разберем, какие папки необходимо создать вручную:
C:\Windows\SysWOW64\config\systemprofile\DesktopC:\Windows\System32\config\systemprofile\DesktopПосле создания папки крайне важно дать пользователю, от имени которого запущен сервер 1С, полные права на эту директорию. Это «оживляет» графическую подсистему Excel в неинтерактивном сеансе.
Посмотрим на код с точки зрения надежности. Использование ActiveSheet или Select() на сервере — плохая практика. В неинтерактивном режиме «активного» листа может не существовать, а метод Select() пытается имитировать действия пользователя в интерфейсе, которого нет.
Перепишем код правильно, обращаясь к конкретным объектам напрямую:
// Открываем книгу и получаем ссылку на конкретный лист
РабочаяКнига = ExcelDoc.WorkBooks.Open("C:\1.xls");
НужныйЛист = РабочаяКнига.Sheets(1); // Обращаемся по индексу или имени
// Вставляем картинку без использования метода .Select()
// Параметры: Путь, LinkToFile, SaveWithDocument, Left, Top, Width, Height
Картинка = НужныйЛист.Shapes.AddPicture("C:\1.jpg", Ложь, Истина, 100, 100, 70, 70);
Обратите внимание на параметры LinkToFile и SaveWithDocument. На сервере рекомендуется устанавливать LinkToFile = Ложь и SaveWithDocument = Истина, чтобы изображение физически внедрилось в файл и не зависело от внешних путей.
Excel — приложение, ориентированное на печать. Для расчета координат объектов Shapes он обращается к драйверу принтера по умолчанию. Если у пользователя usr1cv8 принтер не определен, расчеты координат могут вернуть ошибку.
Попробуем выполнить следующие действия:
Если ошибка сохраняется, проанализируем ситуацию, разбивая длинную строку кода на отдельные вызовы. Это позволит точно понять, в какой момент происходит сбой: при обращении к коллекции Shapes или в момент выполнения AddPicture.
Попытка
Лист = РабочаяКнига.Sheets(1);
ВсеРисунки = Лист.Shapes;
НовыйРисунок = ВсеРисунки.AddPicture("C:\1.jpg", Ложь, Истина, 0, 0, -1, -1);
// Значения -1 в ширине/высоте позволяют вставить картинку в оригинальном размере
Исключение
Сообщить("Ошибка на этапе: " + ОписаниеОшибки());
КонецПопытки;
Рассмотрим более современный способ решения задачи. Работа с COM-объектами на сервере считается нестабильной (утечки памяти, зависшие процессы EXCEL.EXE). Мы можем использовать встроенные средства 1С для формирования файла Excel с картинками.
ТабДок = Новый ТабличныйДокумент;
// Создаем рисунок в 1С
КартинкаОбъект = Новый Картинка("C:\1.jpg");
Рисунок = ТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
Рисунок.Картинка = КартинкаОбъект;
// Позиционируем рисунок (например, в области первой ячейки)
Область = ТабДок.Область(1, 1);
Рисунок.Расположить(Область);
// Сохраняем сразу в формате Excel без использования COM
ТабДок.Записать("C:\Результат.xlsx", ТипФайлаТабличногоДокумента.XLSX);
Этот метод работает на сервере значительно быстрее, не требует установки Microsoft Office на сервер и лишен всех проблем с правами доступа и разрядностью COM-объектов.
Подводя итог, если вам необходимо использовать именно Excel через COM на сервере, начните с проверки разрядности (x64) и создания папок Desktop в системном профиле. Если же архитектура решения позволяет, лучшим выбором будет переход на использование нативного ТабличногоДокумента 1С, что обеспечит максимальную стабильность серверного кода.