Работа с табличными данными на управляемых формах 1С:Предприятие 8.3 часто вызывает вопросы у начинающих разработчиков. Основная сложность заключается в том, что визуальное представление таблицы и сами данные — это разные объекты с разными наборами методов. В этой статье мы подробно разберем, как правильно манипулировать данными таблиц, почему возникают ошибки "Метод объекта не обнаружен" и как оптимизировать обновление строк таблицы результатами запроса.
Первое, что нам необходимо проанализировать, — это разница между тем, что мы видим на экране, и тем, что хранится в памяти сервера. Рассмотрим типичную ситуацию: у нас есть реквизит формы ТабКлиенты с типом Таблица значений (в контексте формы это ДанныеФормыКоллекция) и элемент формы с тем же именем.
Разберем основные ошибки при обращении к этим объектам:
Элементы.ТабКлиенты, мы обращаемся к объекту типа ТаблицаФормы. Это визуальный элемент. У него есть свойства Видимость, Доступность, но у него нет метода Выгрузить(). Попытка вызвать его приведет к ошибке.ТабКлиенты на сервере имеет тип ДанныеФормыКоллекция. У этого типа есть метод Выгрузить(), но он возвращает объект ТаблицаЗначений. Важно помнить, что у ДанныеФормыКоллекция нет метода ВыгрузитьКолонку().Если нам нужно получить массив значений определенной колонки из таблицы, находящейся на форме, мы не можем сделать это в одно действие. Проанализируем правильный алгоритм действий на сервере:
Сначала мы должны преобразовать данные формы в полноценную таблицу значений, а затем уже использовать специфические методы этой таблицы. Рассмотрим пример кода:
&НаСервере
Процедура ВыгрузитьДанныеВМассив()
// 1. Выгружаем данные из реквизита формы в объект "ТаблицаЗначений"
ТЗ = ТабКлиенты.Выгрузить();
// 2. Теперь у объекта ТЗ доступен метод ВыгрузитьКолонку()
МассивДоговоров = ТЗ.ВыгрузитьКолонку("Договор");
// Теперь МассивДоговоров содержит чистые значения, а не строки таблицы
КонецПроцедуры
Существует также альтернативный метод — использование функции РеквизитФормыВЗначение. Посмотрим на ситуацию, когда это целесообразно. Данный метод превращает данные формы в прикладной объект (например, в ТаблицуЗначений или в ДокументОбъект). Однако стоит учитывать, что этот метод более ресурсоемкий, чем простой Выгрузить(), и его стоит применять только если вам нужны методы именно прикладного объекта.
Часто возникает обратная задача: нужно выполнить запрос и заполнить его результатами колонки в уже существующей таблице на форме. Рассмотрим распространенную ошибку, которую совершают программисты при обходе коллекции в цикле.
Разберем некорректный пример кода:
// ОШИБОЧНЫЙ КОД
Для каждого СТР из ТЗ Цикл
ТабКлиенты.ДатаАктивности = ТЗ.Дата; // Ошибка! Нельзя присваивать значение всей таблице
КонецЦикла;
В данном примере автор пытается присвоить значение колонке всей таблицы, используя имя таблицы, а не текущую строку. Выясним причину ошибки: при обходе таблицы в цикле Для каждого, мы получаем доступ к конкретной строке. Именно к свойствам этой строки и нужно обращаться.
Правильный вариант обхода коллекции выглядит так:
&НаСервере
Процедура ОбновитьДатыАктивности(РезультатЗапроса)
ТЗРезультат = РезультатЗапроса.Выгрузить();
// Предположим, количество строк в ТабКлиенты совпадает с ТЗРезультат
Для Индекс = 0 По ТабКлиенты.Количество() - 1 Цикл
СтрокаФормы = ТабКлиенты[Индекс];
СтрокаРезультата = ТЗРезультат[Индекс];
СтрокаФормы.ДатаАктивности = СтрокаРезультата.Дата;
КонецЦикла;
КонецПроцедуры
Если ваша задача — заполнить одну и ту же колонку для всех строк таблицы одинаковым значением (например, датой из регистра), 1С предоставляет более изящный и быстрый способ через промежуточную таблицу значений. Рассмотрим этот метод подробнее.
Использование метода Загрузить() у реквизита формы полностью заменяет содержимое таблицы. Если мы сначала выгрузим таблицу в ТЗ, изменим нужную колонку методом ЗаполнитьЗначения(), а потом загрузим обратно, это будет работать крайне быстро.
&НаСервере
Процедура ЗаполнитьКолонкуОднойДатой()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ДатаАктивности.ДатаПоследнейАктивности КАК Дата
|ИЗ
| РегистрСведений.ДатаАктивности КАК ДатаАктивности";
Результат = Запрос.Выполнить();
Если НЕ Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
ОбщаяДата = Выборка.Дата;
// Преобразуем данные формы в ТЗ для быстрой обработки
ТЗ = ТабКлиенты.Выгрузить();
// Массово заполняем колонку
ТЗ.ЗаполнитьЗначения(ОбщаяДата, "ДатаАктивности");
// Загружаем данные обратно в реквизит формы
ТабКлиенты.Загрузить(ТЗ);
КонецЕсли;
КонецПроцедуры
Важное замечание: Метод Загрузить() полностью перерисовывает таблицу в интерфейсе. Если в таблице были выделенные строки или фокус стоял на определенной ячейке, после выполнения этого метода фокус может сброситься. Если сохранение позиции курсора критично для пользователя, лучше использовать перебор строк в цикле Для каждого непосредственно по реквизиту ТабКлиенты без выгрузки в промежуточную ТЗ.
Для успешной работы с таблицами на управляемых формах придерживайтесь следующих правил:
ТаблицаЗначений и методы выгрузки данных недоступны на клиенте. Передавайте управление на сервер через &НаСервере.Элементы.ИмяТаблицы — для дизайна и свойств колонки, ИмяТаблицы (реквизит) — для манипуляций со строками.ВыгрузитьКолонку() не находится, значит вы вызываете его у ДанныеФормыКоллекция. Сначала вызовите Выгрузить(), чтобы получить ТаблицуЗначений.Выборка.Следующий() или Выгрузить()), всегда проверяйте, не пустой ли результат, чтобы избежать ошибок исполнения.Разбирая эти ситуации по шагам, мы видим, что работа с данными в 1С требует четкого понимания того, в каком контексте (Клиент или Сервер) и с каким типом объекта мы взаимодействуем в данный момент.