Как правильно перебрать строки в Табличном поле и вернуть данные в форму документа в 1С 8.3

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

Работа в среде 1С:Предприятие 8.3 в режиме обычного приложения (толстого клиента) имеет свои уникальные особенности, которые часто забываются после перерыва в практике. Одной из наиболее распространенных задач является создание обработки-подбора, которая должна считать данные из таблицы на форме и передать результат обратно в документ. В этой статье мы подробно разберем, почему стандартные циклы могут выдавать одинаковые значения и как правильно организовать взаимодействие между двумя формами.

Проблема 1: Почему в цикле повторяется одна и та же строка?

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

Ошибочный код выглядит так:


// Ошибка: использование ТекущиеДанные внутри цикла
Для каждого Стр Из ЭлементыФормы.ТаблицаОстатков.ТекущиеДанные Цикл
    Сообщить(ЭлементыФормы.ТаблицаОстатков.ТекущиеДанные.Номенклатура);
КонецЦикла;

В данном случае, даже если цикл выполнится 5 раз (по количеству колонок или иному признаку), вы получите 5 одинаковых сообщений. Это происходит потому, что ТекущиеДанные — это статичное свойство элемента управления, указывающее на конкретный объект в памяти, а не итератор по всей коллекции.

Правильный обход коллекции данных

Чтобы перебрать все строки, нам нужно обращаться не к ЭлементуФормы (визуальному представлению), а к Данным, которые с ним связаны. В обычном приложении ТабличноеПоле всегда привязано к какому-либо источнику: ТаблицеЗначений, ТабличнойЧасти или СпискуЗначений.

Разберем правильный алгоритм действий:

  1. Выясняем имя данных в свойствах элемента ТабличноеПоле (свойство "Данные").
  2. Используем цикл Для каждого непосредственно к этой переменной (коллекции).

Пример корректного кода:


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

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

Проблема 2: Передача данных из обработки в открытый документ

Следующий важный этап — возврат данных. Часто программисты пытаются использовать ссылку на документ, полученную из глобальной переменной или параметров, и вызывают метод ПолучитьОбъект(). Проанализируем, почему это приводит к тому, что данные в открытой форме документа не появляются.

Суть проблемы: Когда мы вызываем Ссылка.ПолучитьОбъект(), 1С создает в оперативной памяти новый экземпляр объекта. Мы можем успешно добавить в него строки и даже вызвать метод Записать(), но форма документа, которая уже открыта у пользователя на экране, ничего об этом не узнает. Она продолжает работать со своим собственным экземпляром объекта, который был загружен при открытии.

Рассмотрим, как делать НЕЛЬЗЯ:


// Этот код изменит данные в базе (если вызвать Записать), 
// но не в открытом окне документа!
ОбъектДокумента = ДокСсылка.ПолучитьОбъект();
НоваяСтрока = ОбъектДокумента.Товары.Добавить();
НоваяСтрока.Номенклатура = ВыбранныйТовар;
// Пользователь не увидит изменений в текущей форме

Решение: Работа через Владельца формы или передача объекта

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

Способ №1: Использование свойства ВладелецФормы

Если обработка открывается модально или с указанием владельца, мы можем напрямую обратиться к данным формы-родителя. В обычном приложении это реализуется через обращение к ЭтаФорма.ВладелецФормы.

Пример реализации в коде обработки:


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

Способ №2: Передача ссылки на объект формы

При открытии обработки из формы документа мы можем передать сам объект ЭтотОбъект (не путать со ссылкой Ссылка!) в переменную обработки. Это позволит нам напрямую манипулировать табличной частью документа.

В форме документа:


ФормаПодбора = Обработки.ПодборНоменклатуры.ПолучитьФорму("Форма");
// Передаем ссылку на текущий объект документа в реквизит обработки
ФормаПодбора.ДокументОбъект = ЭтотОбъект; 
ФормаПодбора.Открыть();

В форме обработки (при записи/завершении):


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

Важный нюанс: После программного изменения табличной части документа из внешней обработки, визуальное обновление таблицы в форме владельца может не произойти мгновенно. В некоторых случаях полезно вызвать метод ОбновитьОтображениеДанных() для формы документа, чтобы пользователь сразу увидел результат подбора.

Резюме и рекомендации

Подводя итог, при работе с таблицами и передачей данных между формами в обычном приложении 1С 8.3, всегда придерживайтесь следующих правил:

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

← На главную