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