Как настроить автоматический вызов команды внешней обработки по расписанию в 1С?

Программист 1С v8.3 (Управляемые формы)
← На главную

Часто возникает задача автоматизировать рутинные операции, которые выполняются с помощью внешних обработок. Например, ежедневную загрузку данных из файла. Вместо того чтобы пользователь каждый раз нажимал кнопку вручную, можно настроить регламентное задание, которое будет запускать нужную команду обработки в заданное время. Однако при переносе логики из интерактивного режима в серверный (фоновый) возникают типичные ошибки, связанные с разным контекстом выполнения. Рассмотрим, как правильно создать и настроить внешнюю обработку для вызова по расписанию.

Анализ проблемы и распространенные ошибки

Проанализируем ситуацию, с которой столкнулся автор вопроса. Он пытался запустить команду обработки регламентно, но его код не работал. Исходный код содержал несколько фундаментальных ошибок, которые характерны для начинающих разработчиков в управляемых формах.

Ошибка №1: Смешение клиентского и серверного контекста.

Регламентные задания выполняются исключительно на сервере. В серверном коде нет доступа к элементам пользовательского интерфейса и многим клиентским методам. Попытка использовать в модуле объекта обработки, предназначенной для регламентного задания, директивы &НаКлиенте и вызывать такие функции, как ПолучитьФорму() или ПоместитьФайл() (без предварительного вызова с клиента), приведет к ошибке.

В коде автора присутствовали такие строки:


//&НаКлиенте
//Процедура Команда1(Команда)
// ...
// Форма = ПолучитьФорму("ВнешняяОбработка." + ИмяОбработки + ".Форма");
// Форма.ЗагрузитьЗаявки(Неопределено);
//КонецПроцедуры

Этот код может работать только при интерактивном запуске пользователем, но он абсолютно неприменим для регламентного задания, у которого нет ни формы, ни клиентского сеанса в привычном понимании.

Ключевое правило: код в модуле объекта внешней обработки, который должен выполняться регламентно, пишется без директив &НаКлиенте и &НаСервере. Весь этот код по умолчанию будет исполняться в серверном контексте.

Ошибка №2: Неправильная регистрация команды для серверного вызова.

При использовании "Библиотеки стандартных подсистем" (БСП) внешние обработки регистрируются в системе через функцию СведенияОВнешнейОбработке(). В ней описываются команды, которые обработка предоставляет. У каждой команды есть параметр "Использование", который определяет, как она будет вызвана.

Изначально у автора было указано:


ДобавитьКоманду(ТаблицаКоманд, "Пересчет текущих итогов", "ЗагрузитьЗаявки", "ЗагрузитьЗаявки");

Здесь четвертым параметром (Использование) передается идентификатор команды, что неверно. Для того чтобы команду можно было вызвать из регламентного задания (т.е. на сервере без открытия формы), необходимо указать специальный тип использования — "ВызовСерверногоМетода".

Правильный вызов должен выглядеть так:


ДобавитьКоманду(ТаблицаКоманд, "Загрузка 123", "ЗагрузитьЗаявки", "ВызовСерверногоМетода");

Ошибка №3: Неверная логика в процедуре `ВыполнитьКоманду`.

Когда система (например, регламентное задание) вызывает команду с типом "ВызовСерверногоМетода", она обращается к экспортной процедуре ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) в модуле объекта обработки. Задача этой процедуры — принять идентификатор команды и запустить соответствующий код.

Автор совершил ошибку, пытаясь вызвать метод из параметра ПараметрыВыполненияКоманды:


Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
    Если ИдентификаторКоманды = "ЗагрузитьЗаявки" Тогда
        // НЕПРАВИЛЬНО!
        ПараметрыВыполненияКоманды.ЗагрузитьЗаявки(Неопределено); 
    КонецЕсли;
КонецПроцедуры

ПараметрыВыполненияКоманды — это структура, которая содержит контекст вызова (например, объекты, из которых была вызвана команда), но сама она не является объектом обработки и не содержит ее методов. Правильный подход — вызвать процедуру из самого модуля объекта.

Пошаговое решение: Создание корректной обработки для регламентного задания

Разберем по шагам, как создать внешнюю обработку, команду которой можно будет вызывать по расписанию.

  1. Подготовка модуля объекта

    Убедитесь, что в модуле объекта вашей внешней обработки нет директив компиляции &НаКлиенте и &НаСервере. Вся основная логика, регистрация и выполнение команд должны находиться в этом модуле.

  2. Правильная регистрация команды

    В функции СведенияОВнешнейОбработке() необходимо правильно зарегистрировать команду, указав тип использования "ВызовСерверногоМетода".

    
    Функция СведенияОВнешнейОбработке() Экспорт
        ПараметрыРегистрации = Новый Структура;
        ПараметрыРегистрации.Вставить("Вид", "ДополнительнаяОбработка");
        ПараметрыРегистрации.Вставить("Наименование", "Загрузка по расписанию");
        ПараметрыРегистрации.Вставить("Версия", "1.0");
        ПараметрыРегистрации.Вставить("БезопасныйРежим", Ложь);
        ПараметрыРегистрации.Вставить("Информация", "Автоматическая загрузка заявок");
    
        ТаблицаКоманд = ПолучитьТаблицуКоманд();
        ДобавитьКоманду(ТаблицаКоманд, 
            "Загрузить заявки (автоматически)", // Представление для пользователя
            "ЗагрузитьЗаявки",                   // Идентификатор команды
            "ВызовСерверногоМетода");             // Тип использования для серверного вызова
    
        ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
    
        Возврат ПараметрыРегистрации;
    КонецФункции
    
    Функция ПолучитьТаблицуКоманд()
        Команды = Новый ТаблицаЗначений;
        Команды.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
        Команды.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
        Команды.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
        Команды.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
        Команды.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка"));
        Возврат Команды;
    КонецФункции
    
    Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение = Ложь, Модификатор = "")
        НоваяКоманда = ТаблицаКоманд.Добавить();
        НоваяКоманда.Представление = Представление;
        НоваяКоманда.Идентификатор = Идентификатор;
        НоваяКоманда.Использование = Использование;
        НоваяКоманда.ПоказыватьОповещение = ПоказыватьОповещение;
        НоваяКоманда.Модификатор = Модификатор;
    КонецПроцедуры
    

    Примечание: Если ваша конфигурация использует БСП последней версии, регистрацию можно упростить, используя готовые функции из общих модулей, как было предложено в одном из сообщений.

  3. Реализация основной логики

    Вынесем всю логику по загрузке данных в отдельную процедуру. Это делает код более читаемым и структурированным. Для вызова из регламентного задания делать ее экспортной (Экспорт) не обязательно, но это может быть удобно для отладки, если вы захотите вызвать ее из формы обработки.

    
    Процедура ЗагрузитьЗаявки()
        //
        // Здесь размещается весь код по загрузке данных:
        // чтение файла, обработка данных, создание документов и т.д.
        //
        // Пример: запись в журнал регистрации для отладки
        ЗаписьЖурналаРегистрации("Загрузка по расписанию", УровеньЖурналаРегистрации.Информация, , , "Процедура ЗагрузитьЗаявки выполнена.");
    КонецПроцедуры
    
  4. Корректная реализация процедуры `ВыполнитьКоманду`

    Это "точка входа" для серверного вызова. Процедура должна проверять идентификатор вызванной команды и запускать соответствующую ей процедуру с основной логикой.

    
    Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
        Если ИдентификаторКоманды = "ЗагрузитьЗаявки" Тогда
            // Правильный вызов процедуры из этого же модуля
            ЗагрузитьЗаявки(); 
        КонецЕсли;
    КонецПроцедуры
    

    Теперь, когда регламентное задание вызовет команду с идентификатором "ЗагрузитьЗаявки", будет исполнена процедура ВыполнитьКоманду, которая, в свою очередь, запустит процедуру ЗагрузитьЗаявки() с вашей основной логикой.

Отладка обработки в регламентном задании

Отладка кода, который выполняется в фоновом режиме, имеет свои особенности. Просто поставить точку останова и ждать, что отладчик остановится, не получится. Рассмотрим два основных способа.

1. Подключение к фоновым заданиям

Для отладки серверного кода необходимо вручную подключиться к процессу выполнения:

  1. Запустите конфигуратор в режиме отладки.
  2. В главном меню выберите "Отладка" -> "Подключение...".
  3. В открывшемся окне найдите в списке "Фоновые задания" ваше запущенное задание и подключитесь к нему.
  4. После этого точки останова в модуле вашей обработки начнут срабатывать.

Чтобы упростить процесс, в параметрах конфигуратора (Сервис -> Параметры -> закладка "Отладка") можно включить автоматическое подключение к фоновым и регламентным заданиям.

2. Логирование

Надежный способ отладки, особенно когда не удается подключиться отладчиком. В ключевых точках кода добавляйте запись в журнал регистрации 1С. Это позволит отследить ход выполнения и значения переменных.


Процедура ЗагрузитьЗаявки()
    ЗаписьЖурналаРегистрации("Загрузка.Начало", УровеньЖурналаРегистрации.Информация, , , "Начало выполнения загрузки заявок.");
    
    // ... ваш код ...
    ИмяФайла = "C:\data\orders.xml";
    Попытка
        // ... код чтения файла ...
        ЗаписьЖурналаРегистрации("Загрузка.Успех", УровеньЖурналаРегистрации.Информация, , , "Файл " + ИмяФайла + " успешно обработан.");
    Исключение
        ОписаниеОшибки = ОписаниеОшибки();
        ЗаписьЖурналаРегистрации("Загрузка.Ошибка", УровеньЖурналаРегистрации.Ошибка, , , "Ошибка при обработке файла: " + ОписаниеОшибки);
    КонецПопытки;
    
    ЗаписьЖурналаРегистрации("Загрузка.Конец", УровеньЖурналаРегистрации.Информация, , , "Завершение выполнения загрузки заявок.");
КонецПроцедуры

После выполнения задания вы сможете проанализировать записи в журнале регистрации и понять, на каком этапе возникла проблема.

← На главную