Как реализовать подбор в поле табличной части документа на управляемых формах

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

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

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

Рассмотрим ситуацию, когда при попытке вызвать форму подбора программист сталкивается с ошибкой: «Не найден экспортируемый метод: ВыборКодаЗавершение». Эта ошибка возникает в момент создания объекта ОписаниеОповещения. Разберем причину ее появления, проанализировав код:


ОповещениеОЗакрытии = Новый ОписаниеОповещения("ВыборКодаЗавершение", Объект, ДополнительныеПараметры);

Проблема заключается во втором параметре конструктора. Объект ОписаниеОповещения должен знать, в каком программном модуле находится процедура обратного вызова (в нашем случае — ВыборКодаЗавершение). Когда мы указываем Объект, платформа ищет метод в модуле самого документа (прикладного объекта), где экспортируемые процедуры клиентского контекста недоступны. Поскольку наша процедура находится в модуле формы, вторым параметром всегда должна выступать сама форма — ЭтаФорма.

Реализация подбора через НачалоВыбора

Рассмотрим пошагово правильную реализацию подбора. Сначала необходимо перехватить стандартное событие начала выбора у элемента табличной части. Для этого мы устанавливаем свойство СтандартнаяОбработка в значение Ложь, чтобы подавить системное открытие списка справочника и вызвать нашу логику.


&НаКлиенте
Процедура ЗемельныеУчасткиКодКатегорииЗемельНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    // Передаем имя поля и название макета (или другого параметра для логики подбора)
    ВыборКода("КодКатегорииЗемель", "КатегорииЗемельныхУчастков");
КонецПроцедуры

Далее мы описываем процедуру ВыборКода, которая подготавливает параметры для открытия формы и формирует описание оповещения.


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

    ДополнительныеПараметры = Новый Структура;
    ДополнительныеПараметры.Вставить("ИмяКода", ИмяКода);
    
    // ВАЖНО: Передаем ЭтаФорма, чтобы платформа нашла экспортную процедуру в модуле формы
    ОповещениеОЗакрытии = Новый ОписаниеОповещения("ВыборКодаЗавершение", ЭтаФорма, ДополнительныеПараметры);
    
    ОткрытьФорму("ОбщаяФорма.ФормаВыбораКода", ПараметрыФормы, ЭтаФорма, , , , ОповещениеОЗакрытии);
КонецПроцедуры

Обработка результата выбора

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


&НаКлиенте
Процедура ВыборКодаЗавершение(РезультатЗакрытия, ДополнительныеПараметры) Экспорт
    
    Если РезультатЗакрытия = Неопределено Тогда
        Возврат; // Пользователь просто закрыл форму
    КонецЕсли;

    ИмяКода = ДополнительныеПараметры.ИмяКода;
    
    // Вариант 1: Использование ТекущиеДанные (простой, но имеющий нюансы)
    ДанныеСтроки = Элементы.ЗемельныеУчастки.ТекущиеДанные;
    Если ДанныеСтроки <> Неопределено Тогда
        ДанныеСтроки[ИмяКода] = РезультатЗакрытия;
        Модифицированность = Истина;
    КонецЕсли;
    
КонецПроцедуры

Анализ рисков при работе с ТекущиеДанные

Использование конструкции Элементы.Таблица.ТекущиеДанные является самым простым способом, но содержит скрытую угрозу. Представим ситуацию: пользователь нажал кнопку выбора в строке №1, открылась форма подбора. Пока форма открыта, пользователь (случайно или намеренно) переключился в табличной части на строку №2. Когда форма подбора закроется, ТекущиеДанные будут указывать уже на строку №2, и выбранное значение запишется не туда, куда планировалось.

Для создания отказоустойчивого кода рекомендуется использовать идентификатор строки. Разберем, как модифицировать наш алгоритм для безопасной работы:

Шаг 1. Передача идентификатора в параметры оповещения:

В процедуре ВыборКода добавим получение идентификатора текущей строки:


ИдентификаторСтроки = Элементы.ЗемельныеУчастки.ТекущаяСтрока;
ДополнительныеПараметры.Вставить("ИдентификаторСтроки", ИдентификаторСтроки);

Шаг 2. Поиск строки по идентификатору при завершении:

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


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

Итоги и рекомендации

При реализации подбора в табличные части на управляемых формах следует придерживаться следующих правил:

  1. Всегда используйте ЭтаФорма (или просто опускайте этот параметр внутри модуля формы, если это допустимо контекстом) в конструкторе ОписаниеОповещения.
  2. Процедура завершения (callback) обязательно должна иметь признак Экспорт.
  3. Для надежной записи результата передавайте в ДополнительныеПараметры идентификатор строки (ТекущаяСтрока), а не полагайтесь на ТекущиеДанные в момент возврата.
  4. Не забывайте устанавливать СтандартнаяОбработка = Ложь, чтобы избежать двойного открытия форм выбора.

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

← На главную