Как во внешней обработке получить ссылку и объект открытого документа 1С

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

При разработке дополнительных внешних обработок заполнения для конфигураций на базе Библиотеки стандартных подсистем (БСП), таких как «1С:Зарплата и управление персоналом 3.1», «1С:ERP» или «1С:Управление торговлей», разработчики часто сталкиваются с ситуацией, когда код отлично отрабатывает при прямом открытии файла через меню «Файл — Открыть», но выдает ошибку при подключении обработки через справочник дополнительных отчетов и обработок. Разберем детально, почему это происходит и как правильно организовать работу с открытым документом.

Основные причины возникновения ошибки

Проанализируем типичные ошибки, которые приводят к сбою выполнения команды:

  1. Неверный контекст выполнения метода: метод ПолучитьОбъект() доступен исключительно на стороне сервера, в толстом клиенте или внешнем соединении. Если процедура выполняется на тонком клиенте (директива &НаКлиенте), вызов этого метода приведет к аварийному завершению.
  2. Неправильное расположение функции регистрации: согласно стандартам БСП, экспортная функция СведенияОВнешнейОбработке() должна располагаться в модуле объекта внешней обработки, а не в модуле формы.
  3. Попытка работы с новым документом: если документ еще не записан в базу данных, у него нет физической ссылки в таблицах СУБД (ссылка является пустой). Попытка вызвать метод ПолучитьОбъект() для пустой ссылки вернет Неопределено.
  4. Конфликт версий при прямой перезаписи: если документ уже открыт у пользователя на экране, а внешняя обработка на сервере считывает его из базы, изменяет и вызывает Записать(), то при попытке пользователя нажать «Записать» в самой форме возникнет ошибка блокировки данных: «Данные были изменены или удалены в другой сессии».

Вариант 1. Заполнение открытой формы документа через команду «ЗаполнениеФормы» (рекомендуемый способ)

Если задача заключается в том, чтобы перезаполнить или пересчитать табличную часть документа, который прямо сейчас открыт пользователем на экране, правильнее всего использовать стандартный механизм БСП с типом команды ЗаполнениеФормы. В этом случае изменения вносятся в структуру данных формы в оперативной памяти без принудительной записи в базу данных, что позволяет пользователю увидеть результат и при необходимости отменить или дозаполнить документ.

Рассмотрим структуру модуля объекта внешней обработки:


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

Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполнения = Неопределено) Экспорт
    
    Если ИдентификаторКоманды = "ПересчитатьНДФЛ" Тогда
        Для Каждого ОбъектФормы Из ОбъектыНазначения Цикл
            // В данном режиме ОбъектФормы представляет собой данные формы документа
            ОбъектФормы.НДФЛ.Очистить();
            
            Для Каждого СтрокаТЗ Из ОбъектФормы.НачисленияУдержанияВзносы Цикл
                СтрокаТЗ.НДФЛ = Окр(СтрокаТЗ.Начислено * 0.13, 0);
                СтрокаТЗ.КВыплате = СтрокаТЗ.Начислено - СтрокаТЗ.НДФЛ;
            КонецЦикла;
            // Метод Записать() не вызывается, данные сразу отображаются в открытом документе
        КонецЦикла;
    КонецЕсли;
    
КонецПроцедуры

Вариант 2. Пакетная фоновая обработка документов через «ВызовСерверногоМетода»

Если требуется обработать документы напрямую в базе данных (например, при вызове из формы списка документов без их интерактивного открытия), используется тип команды ВызовСерверногоМетода. В этом случае в массив ОбъектыНазначения передаются реальные ссылки на документы из базы данных.

Посмотрим на реализацию процедуры выполнения в модуле объекта:


Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполнения = Неопределено) Экспорт
    
    Для Каждого СсылкаНаДокумент Из ОбъектыНазначения Цикл
        
        Если Не ЗначениеЗаполнено(СсылкаНаДокумент) Тогда
            Продолжить;
        КонецЕсли;
        
        ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
        Если ДокументОбъект <> Неопределено Тогда
            ДокументОбъект.НДФЛ.Очистить();
            
            Для Каждого СтрокаТЗ Из ДокументОбъект.НачисленияУдержанияВзносы Цикл
                СтрокаТЗ.НДФЛ = Окр(СтрокаТЗ.Начислено * 0.13, 0);
                СтрокаТЗ.КВыплате = СтрокаТЗ.Начислено - СтрокаТЗ.НДФЛ;
            КонецЦикла;
            
            ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Вариант 3. Получение ссылки и объекта через клиентский метод

Если обработка требует открытия собственной вспомогательной формы или интерактивного диалога с пользователем перед выполнением расчетов, используется вариант ВызовКлиентскогоМетода. В таком сценарии доступ к данным формы документа-владельца получается через свойство ВладелецФормы.

Разберем пример кода в модуле формы внешней обработки:


&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения) Экспорт
    
    ФормаДокумента = ВладелецФормы;
    Если ФормаДокумента <> Неопределено Тогда
        // Получаем структуру данных документа на клиенте
        ДанныеОбъекта = ФормаДокумента.Объект;
        
        // Вызываем серверную процедуру для выполнения расчетов
        ПересчитатьТабличныеЧастиНаСервере(ДанныеОбъекта);
        
        // Устанавливаем признак модифицированности формы
        ФормаДокумента.Модифицированность = Истина;
    КонецЕсли;
    
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ПересчитатьТабличныеЧастиНаСервере(ДанныеОбъекта)
    
    ДанныеОбъекта.НДФЛ.Очистить();
    Для Каждого СтрокаТЗ Из ДанныеОбъекта.НачисленияУдержанияВзносы Цикл
        СтрокаТЗ.НДФЛ = Окр(СтрокаТЗ.Начислено * 0.13, 0);
        СтрокаТЗ.КВыплате = СтрокаТЗ.Начислено - СтрокаТЗ.НДФЛ;
    КонецЦикла;
    
КонецПроцедуры

Особенности отладки подключенных внешних обработок

Выясним, почему точки останова могут не срабатывать при вызове обработки из интерфейса конфигурации:

  1. Запуск из временного хранилища: при выполнении команды БСП выгружает двоичные данные обработки из базы данных во временный файл на диске. Конфигуратор не всегда автоматически связывает открытый исходный файл обработки с его временной копией. Для отладки подключите обработку вручную через механизм Отладка — Подключение, отметив флажки автоматического подключения фоновых заданий и серверных вызовов.
  2. Клиент-серверный режим: если база работает на сервере 1С:Предприятия, служба сервера должна быть запущена с ключом -debug. В противном случае остановка в серверных модулях не произойдет независимо от корректности кода.
← На главную