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