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