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