При разработке внешних обработок заполнения табличных частей для конфигураций на базе Библиотеки стандартных подсистем (БСП), таких как «1С:Розница 2.3», разработчики часто сталкиваются с неприятным поведением системы: перед выполнением команды программа принудительно требует записать документ. Это не всегда удобно, особенно если пользователь еще не завершил ввод данных или просто хочет «примерить» заполнение данных без фиксации в базе.
В этой статье мы подробно разберем, почему стандартный параметр РежимЗаписи = "НеЗаписывать" может не работать, проанализируем внутренние механизмы БСП и найдем надежный способ обработки данных «на лету».
Для начала проанализируем, как БСП обрабатывает вызов внешней команды. В процедуре СведенияОВнешнейОбработке мы описываем таблицу команд. У каждой команды есть поле Использование, которое определяет, как именно будет выполняться код. Рассмотрим два основных варианта, которые вызывают наибольшее количество вопросов:
Модифицированность формы.Проанализируем ситуацию пользователя: при использовании ЗаполнениеФормы в метод ВыполнитьКоманду передается только идентификатор команды. Если контекст формы не проброшен (например, команда вызвана из списка), система не видит объекта в оперативной памяти и требует его запись в базу данных.
Выясним причину, по которой установка ОписаниеКоманды.РежимЗаписи = "НеЗаписывать" не всегда помогает. В коде общих модулей БСП (например, ДополнительныеОтчетыИОбработкиКлиент) существует жесткая проверка. Если система определяет, что обработка должна изменить данные объекта, она перестраховывается. В некоторых версиях «Розницы 2.3» наблюдался баг, когда контекст ЭтоФормаОбъекта определялся некорректно, и флаг записи выставлялся в Истина принудительно.
Важный нюанс: если вы вызываете обработку из формы списка (динамического списка), то объекта в памяти еще не существует — есть только ссылка. В этом случае запись (или перечитывание из базы) неизбежна. Чтобы работать без записи, обработка должна вызываться только из формы открытого документа.
Рассмотрим наиболее надежный способ, который позволяет обойти ограничения сервера и работать напрямую с данными формы. Мы будем использовать тип команды ВызовКлиентскогоМетода.
Шаг 1. Настроим регистрацию обработки. В модуле объекта в функции СведенияОВнешнейОбработке укажем правильные параметры:
НоваяСтрока = ТаблицаКоманд.Добавить();
НоваяСтрока.Представление = "Заполнить ТЧ (без записи)";
НоваяСтрока.Идентификатор = "ЗаполнениеБезЗаписи";
НоваяСтрока.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();
НоваяСтрока.ПоказыватьОповещение = Истина;
НоваяСтрока.Модификатор = "ПечатьDefault"; // Необязательно
НоваяСтрока.РежимЗаписи = "НеЗаписывать";
Шаг 2. В модуле формы внешней обработки создадим экспортную процедуру. Именно она будет «точкой входа». Посмотрим на пример кода:
&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполнения) Экспорт
// Получаем форму документа, из которой вызвана обработка
ФормаДокумента = ПараметрыВыполнения.ЭтаФорма;
// Проверим, что мы находимся в форме объекта
Если ФормаДокумента = Неопределено Тогда
Возврат;
КонецЕсли;
// Обрабатываем данные напрямую в объекте формы
// Например, заполним табличную часть "Товары"
ЗаполнитьТабличнуюЧастьНаСервере(ФормаДокумента.Объект);
// Сообщаем форме, что данные изменились, чтобы появилась "звездочка" (Модифицированность)
ФормаДокумента.Модифицированность = Истина;
КонецПроцедуры
Разберем подробнее, что происходит в коде выше. Используя ПараметрыВыполнения.ЭтаФорма, мы получаем прямой доступ к расширению формы документа. Мы можем изменять ФормаДокумента.Объект (который является типом ДанныеФормыСтруктура), и эти изменения мгновенно отобразятся у пользователя на экране без обращения к базе данных.
Однако помните, что изменять ДанныеФормыСтруктура лучше на сервере. Для этого передайте ФормаДокумента.Объект в серверную процедуру модуля формы обработки:
&НаСервере
Процедура ЗаполнитьТабличнуюЧастьНаСервере(ДанныеФормыОбъект)
// Пример: Очистим и заполним заново
ДанныеФормыОбъект.Товары.Очистить();
НоваяСтрока = ДанныеФормыОбъект.Товары.Добавить();
НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Тестовый товар");
НоваяСтрока.Количество = 1;
НоваяСтрока.Цена = 100;
НоваяСтрока.Сумма = 100;
КонецПроцедуры
Если ваша обработка имеет сложный интерфейс (например, подбор товаров с фильтрами в отдельном окне), используем механизм оповещений. Рассмотрим этот сценарий по шагам:
ОповеститьОВыборе(СтруктураРезультата) или Оповестить("ЗаполнениеТЧ", СтруктураРезультата).ОбработкаОповещения (если это типовая форма, может потребоваться расширение) или в самой логике БСП данные подхватываются и записываются в ТЧ.Важный совет: В конфигурации «Розница 2.3» для типа команды ЗаполнениеФормы БСП ожидает, что в модуле объекта обработки будет процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполнения). Если вы видите ошибку «Контекста — 0», это значит, что ПараметрыВыполнения не содержат ключа ЭтаФорма. Проверьте, не вызываете ли вы команду из списка документов.
Проанализировав проблему, мы приходим к выводу, что для реализации заполнения табличной части без записи в «Розница 2.3» следует придерживаться следующих правил:
ПараметрыВыполнения.ЭтаФорма.Объект.Модифицированность = Истина для формы владельца, чтобы пользователь видел наличие несохраненных изменений.Соблюдение этой методики позволит вам создавать удобные инструменты для пользователей, сохраняя при этом целостность данных и логику работы типовой конфигурации.