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