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

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

Разработка на обычных формах в среде «1С:Предприятие 8» (например, в таких конфигурациях, как УПП 1.3, КА 1.1 или УТ 10.3) имеет множество специфических нюансов. Один из самых частых «подводных камней», с которым сталкиваются даже опытные разработчики, — это динамическое заполнение таблицы значений (ТЗ) во внешних обработках и вывод этих данных на форму. Выполняется запрос, данные гарантированно выгружаются, но при открытии формы табличное поле остается абсолютно пустым.

В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем природу сопутствующих ошибок и рассмотрим рабочие способы их решения.

---

Причина 1. Потеря связи между данными и элементом формы (Переприсвоение ссылки)

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


Результат = Запрос.Выполнить();
ЭтотОбъект.тзЦены = Результат.Выгрузить(); 
ЭтотОбъект.ПолучитьФорму("Форма").ОткрытьМодально();

Выясним причину, почему этот код не работает. Когда вы создаете элемент управления Табличное поле на обычной форме и связываете его через свойство Данные с реквизитом ЭтотОбъект.тзЦены, платформа 1С жестко связывает элемент формы с конкретным объектом таблицы значений в оперативной памяти, который инициализируется при создании объекта обработки.

Когда вы выполняете код ЭтотОбъект.тзЦены = Результат.Выгрузить();, происходит следующее:

  1. Метод Выгрузить() создает в памяти новый объект типа ТаблицаЗначений.
  2. Переменной (реквизиту) тзЦены присваивается ссылка на этот новый объект.
  3. Элемент управления на форме (Табличное поле) при этом по-прежнему остается связанным со старым объектом таблицы значений (который теперь пуст). Связь разрывается.

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

Решение проблемы потери связи

Для того чтобы данные отобразились на форме, необходимо переприсвоить свойство Значение у элемента формы и вызвать генерацию колонок. Рассмотрим этот код:


Результат = Запрос.Выполнить();
// Записываем новую ТЗ в реквизит объекта
ЭтотОбъект.тзЦены = Результат.Выгрузить(); 

НужнаяФорма = ЭтотОбъект.ПолучитьФорму("Форма");

// Восстанавливаем связь элемента формы с новыми данными
НужнаяФорма.ЭлементыФормы.тзЦены.Значение = ЭтотОбъект.тзЦены;

// Генерируем колонки на форме заново под структуру новой ТЗ
НужнаяФорма.ЭлементыФормы.тзЦены.СоздатьКолонки();

НужнаяФорма.ОткрытьМодально();

---

Причина 2. Ошибка «Метод объекта не обнаружен (СоздатьКолонки)»

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

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


// ОШИБОЧНЫЙ КОД! У объекта ТаблицаЗначений нет метода СоздатьКолонки
ЭтотОбъект.тзЦены.СоздатьКолонки(); 

Правильное обращение всегда идет через коллекцию элементов формы:


// ПРАВИЛЬНЫЙ КОД
Форма.ЭлементыФормы.ИмяТабличногоПоля.СоздатьКолонки();

Б. Неверный тип элемента управления на форме.
Если вы написали обращение через ЭлементыФормы, но все равно получаете эту ошибку, проверьте свойства элемента на форме в конфигураторе. Возможно, элемент с именем тзЦены был создан как Поле ввода или Поле выбора, а не как Табличное поле. Убедитесь, что тип элемента управления выбран правильно.

---

Причина 3. Ошибка «Метод объекта не обнаружен (Загрузить)»

В попытках обойти проблему потери связи, разработчики часто пытаются использовать метод Загрузить():


// ОШИБОЧНЫЙ КОД
ЭтотОбъект.тзЦены.Загрузить(Результат.Выгрузить());

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

Если вам нужно именно скопировать данные из одной таблицы значений в другую без потери объектной связи, мы рекомендуем использовать построчный перенос данных с сохранением ссылочной целостности:


ТаблицаИсточник = Запрос.Выполнить().Выгрузить();

// Очищаем старую ТЗ, но сохраняем сам объект в памяти
ЭтотОбъект.тзЦены.Очистить(); 

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

// Теперь связь с формой сохранена, достаточно просто обновить колонки
НужнаяФорма = ЭтотОбъект.ПолучитьФорму("Форма");
НужнаяФорма.ЭлементыФормы.тзЦены.СоздатьКолонки();

---

Важное замечание по поводу метода «ЗначениеВРеквизитФормы»

Иногда на форумах для решения подобных проблем советуют использовать конструкцию:

ЗначениеВРеквизитФормы(тз, "тзЦены");

Внимание: Этот метод предназначен исключительно для Управляемых форм (работающих на тонком или веб-клиенте под управлением платформы 1С 8.2 и выше). В обычных формах (толстый клиент) этого метода нет. Его использование приведет к критической ошибке компиляции модуля.

---

Альтернативное решение: Использование Табличной части

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

Разберем этот вариант по шагам:

  1. В конфигураторе откройте вашу внешнюю обработку и на вкладке «Табличные части» добавьте новую ТЧ (например, с именем тзЦены).
  2. Добавьте в эту табличную часть необходимые колонки с нужными типами данных.
  3. Перенесите эту табличную часть на форму в виде элемента «Табличное поле».
  4. В коде заполнения используйте простой и быстрый метод:

РезультатЗапроса = Запрос.Выполнить();

// Очищаем табличную часть обработки
ЭтотОбъект.тзЦены.Очистить();

// Загружаем данные напрямую из результата запроса
ЭтотОбъект.тзЦены.Загрузить(РезультатЗапроса.Выгрузить());

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

← На главную