Почему колонки табличного поля не видны при программном добавлении строк в ТаблицуЗначений на обычной форме 1С?

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

При разработке на платформе 1С:Предприятие 8.3 с использованием обычных форм, многие разработчики сталкиваются с вопросом корректного взаимодействия между реквизитами формы типа ТаблицаЗначений и визуальными элементами управления ТабличноеПоле. Распространенная ситуация, описанная в данной теме, возникает, когда вы добавляете реквизит формы типа ТаблицаЗначений, затем размещаете на форме ТабличноеПоле, связываете его с этим реквизитом и создаете колонки для табличного поля прямо в конфигураторе. Однако, при попытке программного добавления строк в связанную ТаблицуЗначений, возникает ошибка «Поле объекта не обнаружено», как если бы эти колонки вовсе не существовали. Почему так происходит и как правильно организовать работу с табличными данными на обычных формах? Разберем эту ситуацию подробно.

Различие между реквизитом формы и элементом формы

Прежде всего, давайте четко определим ключевое различие, которое является корнем многих проблем при работе с табличными данными на обычных формах. В 1С:Предприятии реквизит формы (в нашем случае, типа ТаблицаЗначений) и элемент формы «ТабличноеПоле» — это два совершенно разных объекта, выполняющих разные функции:

  1. Реквизит формы «ТаблицаЗначений»: Это программный объект, который существует в памяти и предназначен для хранения структурированных данных в табличном виде. Именно с этим объектом мы работаем из кода, когда добавляем, удаляем или изменяем строки и значения ячеек. Он является контейнером данных.
  2. Элемент формы «ТабличноеПоле»: Это визуальный элемент управления, который отображается на форме. Его основная задача — представить пользователю данные, которые хранятся в связанном с ним реквизите формы (источнике данных). Он отвечает за внешний вид, порядок колонок, их заголовки, ширину, доступность для редактирования и т.д.

Важно понимать, что когда вы создаете колонки для ТабличногоПоля в конфигураторе, вы определяете лишь визуальное представление данных. Эти колонки автоматически не создаются в программном объекте ТаблицаЗначений, который связан с этим табличным полем. Соответственно, при попытке обратиться к таким колонкам из кода напрямую к объекту ТаблицаЗначений, система не может их найти.

Где должны быть определены колонки для корректной работы

Для того чтобы программно добавлять строки в ТаблицуЗначений и корректно обращаться к значениям по именам колонок (например, НСтр.Организация), эти колонки должны быть явно определены для самого объекта ТаблицаЗначений (реквизита формы). Это критически важное условие, которое часто упускается из виду.

Если колонки созданы только для элемента формы ТабличноеПоле в конфигураторе, они определяют лишь визуальное отображение. Они не создают соответствующие колонки в программном объекте ТаблицаЗначений, что приводит к ошибке «Поле объекта не обнаружено» при попытке присвоить значение несуществующей колонке в строке таблицы.

Правильный подход к программному добавлению строк в ТаблицуЗначений

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

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


Процедура КоманднаяПанельОрганизацииЗаполнитьВсеми(Кнопка)
    // ...
    ОрганизацииБД = Справочники.Организации.Выбрать;
    Пока ОрганизацииБД.Следующий цикл
        Если Организации.Найти(ОрганизацииБД) = неопределено тогда
            ЭлементыФормы.Организации.ДобавитьСтроку; // Ошибка здесь!
            НСтр = ЭлементыФормы.Организации.ТекущаяСтрока; // И здесь!
            НСтр.Организация = ОрганизацииБД; // Ошибка: Поле объекта не обнаружено (Организация)
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

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

Корректный подход заключается в прямом взаимодействии с реквизитом формы Организации (который имеет тип ТаблицаЗначений):


НСтр = Организации.Добавить(); // Добавляем строку напрямую в реквизит формы ТаблицаЗначений
НСтр.Организация = ОрганизацииБД.Ссылка; // Присваиваем значение колонке

Здесь Организации.Добавить() возвращает объект типа СтрокаТаблицыЗначений, к которому уже можно обращаться по именам колонок, при условии, что эти колонки существуют в структуре ТаблицыЗначений Организации.

Обратите внимание на поправку ОрганизацииБД.Ссылка. Если ОрганизацииБД является выборкой (СправочникВыборка), то для присвоения в колонку типа СправочникСсылка необходимо использовать свойство Ссылка выборки. Также, поиск по выборке (Организации.Найти(ОрганизацииБД)) некорректен; следует искать по ссылке или другому уникальному идентификатору.

Программное создание колонок для ТаблицыЗначений

Наиболее надежный и рекомендуемый способ обеспечить доступ к колонкам при программном заполнении ТаблицыЗначений — это создать их программно для самого реквизита формы типа ТаблицаЗначений. Это делается с помощью метода Колонки.Добавить() объекта ТаблицаЗначений.

Рассмотрим по шагам, как это сделать:

  1. Получаем доступ к коллекцию колонок реквизита формы: У вашего реквизита формы (например, Организации) есть свойство Колонки, которое представляет собой коллекцию колонок этой таблицы значений.
  2. Используем метод Добавить(): Для добавления новой колонки вызываем метод Добавить() этой коллекции. Этот метод принимает несколько параметров:
    • Имя колонки (строка): Уникальное имя, по которому вы будете обращаться к колонке из кода (например, "Организация").
    • Тип колонки (ОписаниеТипов): Очень важно указать тип данных, который будет храниться в этой колонке. Это обеспечивает строгую типизацию и предотвращает ошибки. Например, для ссылки на справочник "Организации" это будет Новый ОписаниеТипов("СправочникСсылка.Организации").
    • Заголовок колонки (строка, необязательно): Текст, который будет отображаться в заголовке табличного поля для этой колонки.
    • Ширина колонки (число, необязательно): Желаемая ширина колонки в символах.

Пример программного создания колонки:


// Предположим, что реквизит формы называется 'Организации' и имеет тип ТаблицаЗначений.
// Создаем колонку с именем "Организация", типом "СправочникСсылка.Организации" и заголовком "Организация".
Организации.Колонки.Добавить("Организация", Новый ОписаниеТипов("СправочникСсылка.Организации"), "Организация");

Рекомендуется выполнять программное создание колонок при инициализации формы, например, в обработчике события ПриОткрытии или ПриСозданииНаСервере для управляемых форм, или в ПриОткрытии для обычных форм.

Назначение метода СоздатьКолонки() для ТабличногоПоля

После того как вы программно определили колонки для вашего реквизита формы ТаблицаЗначений, вам необходимо сообщить элементу формы ТабличноеПоле, что он должен отобразить эти колонки. Именно для этой цели служит метод СоздатьКолонки() у элемента формы ТабличноеПоле.

ЭлементыФормы.Организации.СоздатьКолонки();

Этот метод служит для автоматического создания визуальных колонок в табличном поле на основе колонок, которые уже существуют в его источнике данных (в данном случае, в реквизите формы ТаблицаЗначений). Если колонки для ТаблицыЗначений были определены программно, вызов СоздатьКолонки() для табличного поля обеспечит их корректное отображение на форме, используя их имена и заголовки, если они были заданы при создании.

Полное и корректное решение проблемы

Суммируя все вышесказанное, для решения проблемы "Поле объекта не обнаружено" и корректной работы с ТаблицейЗначений и ТабличнымПолем на обычных формах, предлагаем следующий алгоритм действий:

  1. Объявите реквизит формы: В конфигураторе на вашей обычной форме создайте реквизит, например, с именем Организации и типом ТаблицаЗначений.
  2. Разместите табличное поле на форме: Добавьте на форму элемент управления ТабличноеПоле. В его свойствах установите свойство Данные в значение вашего реквизита Организации. Не создавайте колонки для этого табличного поля в конфигураторе вручную! Если вы их создадите, они могут конфликтовать или быть избыточными.
  3. Программно создайте колонки для реквизита формы: В обработчике события формы (например, ПриОткрытии) программно добавьте необходимые колонки к вашему реквизиту Организации.
  4. Сообщите табличному полю о структуре: После создания колонок для реквизита, вызовите метод СоздатьКолонки() для элемента формы ТабличноеПоле, чтобы он обновил свое визуальное представление согласно структуре источника данных.
  5. Добавляйте строки непосредственно в реквизит формы: В дальнейшем, при заполнении таблицы данными, всегда работайте напрямую с реквизитом формы Организации, используя метод Добавить().

Пример полного рабочего кода для вашей ситуации:


// 1. В модуле формы (например, в ПриОткрытии)
Процедура ПриОткрытии()
    // Программно создаем колонки для реквизита формы ТаблицаЗначений "Организации"
    // Имя колонки, Тип, Заголовок
    Организации.Колонки.Добавить("Организация", Новый ОписаниеТипов("СправочникСсылка.Организации"), "Организация");
    Организации.Колонки.Добавить("ИНН", Новый ОписаниеТипов("Строка", , , 12), "ИНН"); // Пример с другой колонкой
    // ... можно добавить другие колонки по необходимости

    // После того как колонки созданы в ТаблицеЗначений,
    // заставляем ТабличноеПоле пересоздать свои визуальные колонки на основе источника данных.
    ЭлементыФормы.Организации.СоздатьКолонки();
КонецПроцедуры

// 2. В процедуре заполнения (ваш пример из сообщения 9)
Процедура КоманднаяПанельОрганизацииЗаполнитьВсеми(Кнопка)
    // Очистим таблицу перед заполнением, если нужно
    Организации.Очистить();

    ОрганизацииБД = Справочники.Организации.Выбрать();
    Пока ОрганизацииБД.Следующий Цикл
        // Проверяем, существует ли организация в таблице (лучше искать по уникальному идентификатору, например, ссылке)
        Если Организации.Найти(ОрганизацииБД.Ссылка, "Организация") = Неопределено Тогда // Ищем по ссылке в колонке "Организация"
            // Добавляем новую строку напрямую в реквизит формы ТаблицаЗначений
            НСтр = Организации.Добавить();
            // Присваиваем значения колонкам новой строки
            НСтр.Организация = ОрганизацииБД.Ссылка; // Присваиваем ссылку из выборки
            НСтр.ИНН = ОрганизацииБД.ИНН; // Если в выборке есть поле ИНН
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Таким образом, мы видим, что решение состоит в четком разграничении ролей реквизита формы и элемента формы. Данные (включая их структуру, т.е. колонки) хранятся в реквизите формы ТаблицаЗначений, и работать с ними программно нужно именно через этот реквизит. Элемент формы ТабличноеПоле служит исключительно для визуализации этих данных на экране, и его метод СоздатьКолонки() помогает синхронизировать его внешний вид со структурой данных.

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

← На главную