При разработке в среде 1С:Предприятие 8.2 и 8.3 на обычных формах (ОФ) программисты часто сталкиваются с неочевидным поведением интерфейса: при добавлении новой строки в табличную часть она физически создается, но визуально мгновенно пропадает. Это происходит в тех случаях, когда для элемента управления "Табличное поле" включен программный фильтр через свойство ОтборСтрок. Рассмотрим подробнее, почему это случается и как правильно организовать работу с двумя связанными таблицами.
Для начала проанализируем ситуацию. В системе 1С механизм ОтборСтрок является свойством именно элемента управления (визуального объекта на форме), а не самой табличной части как объекта данных. Когда мы работаем с формой, на которой одна таблица (например, "Скидки") фильтруется в зависимости от текущей строки другой таблицы ("Условия"), мы обычно используем событие ПриАктивизацииСтроки. В этом событии устанавливается фильтр по какому-либо полю связи.
Проблема заключается в следующем алгоритме работы системы:
УсловиеНомер = 5.Объект.Скидки.Добавить().УсловиеНомер равно 0 (или не определено).Следовательно, чтобы строка не исчезала, нам необходимо обеспечить заполнение ключевого поля связи в момент создания строки, еще до того, как форма успеет ее перерисовать.
Прежде чем приступать к исправлению кода заполнения, обратим внимание на важное замечание коллег из обсуждения: использование НомерСтроки для связи таблиц — это "мина замедленного действия". Номера строк в 1С непостоянны: они пересчитываются при удалении строк, при их перемещении (кнопками "вверх"/"вниз") или при сортировке. Если связь держится на номере, то при любом изменении порядка строк в главной таблице все подчиненные данные в другой таблице перемешаются или "отвалятся".
Рекомендуемое решение: добавим в обе табличные части реквизит КлючСвязи (тип Число). При добавлении новой строки в главную таблицу будем генерировать для нее уникальный идентификатор (например, на основе текущего времени в миллисекундах или просто максимальный существующий + 1). Именно этот ключ мы будем использовать для фильтрации подчиненной таблицы.
Рассмотрим, как должен выглядеть код в событии ПриАктивизацииСтроки главной таблицы ("Условия"). Мы будем устанавливать отбор в подчиненной таблице ("Скидки") по нашему новому полю КлючСвязи:
Процедура СписокУсловийПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элемент.ТекущаяСтрока;
Если ТекущиеДанные <> Неопределено Тогда
// Устанавливаем отбор в табличном поле "Скидки"
Отбор = ЭлементыФормы.Скидки.ОтборСтрок;
Отбор.КлючСвязи.Значение = ТекущиеДанные.КлючСвязи;
Отбор.КлючСвязи.Использование = Истина;
Иначе
// Если строк нет, выключаем отбор
ЭлементыФормы.Скидки.ОтборСтрок.КлючСвязи.Использование = Ложь;
КонецЕсли;
КонецПроцедуры
Теперь перейдем к решению главной задачи: как заполнить таблицу из внешней обработки (через процедуру Инициализировать), чтобы строки оставались видимыми. Ключевой момент — передать в обработку значение текущего ключа связи из формы.
Посмотрим на пример кода, который должен быть реализован внутри логики заполнения. Предположим, мы передали ТекущийКлючСвязи в параметры обработки:
// Внутри модуля обработки заполнения
Процедура ЗаполнитьСкидки(ДокументОбъект, ЗначениеКлюча)
// Добавляем строку непосредственно в объект документа
НоваяСтрока = ДокументОбъект.Скидки.Добавить();
// КРИТИЧЕСКИ ВАЖНО: заполняем поле связи СРАЗУ после добавления
НоваяСтрока.КлючСвязи = ЗначениеКлюча;
// Заполняем остальные реквизиты
НоваяСтрока.НаименованиеСкидки = "Сезонная 5%";
НоваяСтрока.Процент = 5;
КонецПроцедуры
Если вы используете механизм Добавить() непосредственно в коде формы, ситуация упрощается. Вы можете получить значение активного отбора прямо из элементов формы. Проанализируем ситуацию: если мы нажмем стандартную кнопку "Добавить" в командной панели табличного поля, 1С в обычных формах часто сама пытается подставить значение из отбора. Но при программном вызове метода Добавить() это нужно делать вручную.
Если ваша обработка работает через интерфейс Заполнить (стандартный механизм), она обычно получает в качестве параметра только Объект (сам документ). Однако объект ничего не знает о том, какая строка сейчас выбрана пользователем на экране. В этом случае есть два пути:
Как только поле КлючСвязи (или УсловиеНомер, если вы решили оставить старую логику) будет заполнено в коде добавления строки, механизм ОтборСтрок увидит, что новая строка соответствует критериям, и она останется видимой для пользователя.
Иногда даже при правильном заполнении реквизитов форма может не сразу "увидеть" изменения. В таких случаях после программного изменения состава табличной части рекомендуется принудительно обновить визуальное состояние табличного поля. Рассмотрим метод ОбновитьСтроки():
// В коде формы после вызова обработки заполнения
ЭлементыФормы.Скидки.ОбновитьСтроки();
Подведем итог: "Исчезновение" строк — это не ошибка платформы, а следствие работы фильтра. Чтобы избежать этой ситуации, всегда заполняйте поля, участвующие в отборах, сразу после вызова метода Добавить(). И помните, что связывать строки через НомерСтроки крайне нежелательно — используйте выделенные поля идентификаторов (ключи связи).