Работа в среде 1С:Предприятие 8.3 в режиме обычного приложения (толстого клиента) имеет свои уникальные особенности, которые часто забываются после перерыва в практике. Одной из наиболее распространенных задач является создание обработки-подбора, которая должна считать данные из таблицы на форме и передать результат обратно в документ. В этой статье мы подробно разберем, почему стандартные циклы могут выдавать одинаковые значения и как правильно организовать взаимодействие между двумя формами.
Рассмотрим типичную ошибку начинающего разработчика. При попытке перебрать строки ТабличногоПоля часто используется свойство ТекущиеДанные. Проанализируем ситуацию: если мы напишем цикл, опираясь на текущую строку элемента формы, программа будет возвращать данные только той строки, на которой в данный момент установлен курсор (фокус) в интерфейсе.
Ошибочный код выглядит так:
// Ошибка: использование ТекущиеДанные внутри цикла
Для каждого Стр Из ЭлементыФормы.ТаблицаОстатков.ТекущиеДанные Цикл
Сообщить(ЭлементыФормы.ТаблицаОстатков.ТекущиеДанные.Номенклатура);
КонецЦикла;
В данном случае, даже если цикл выполнится 5 раз (по количеству колонок или иному признаку), вы получите 5 одинаковых сообщений. Это происходит потому, что ТекущиеДанные — это статичное свойство элемента управления, указывающее на конкретный объект в памяти, а не итератор по всей коллекции.
Чтобы перебрать все строки, нам нужно обращаться не к ЭлементуФормы (визуальному представлению), а к Данным, которые с ним связаны. В обычном приложении ТабличноеПоле всегда привязано к какому-либо источнику: ТаблицеЗначений, ТабличнойЧасти или СпискуЗначений.
Разберем правильный алгоритм действий:
ТабличноеПоле (свойство "Данные").Для каждого непосредственно к этой переменной (коллекции).Пример корректного кода:
// Перебираем непосредственно коллекцию данных (например, Таблицу Значений)
Для Каждого Стр Из ТаблицаОстатков Цикл
ТекстСообщения = "Номенклатура: " + Стр.Номенклатура +
", Количество: " + Стр.Колво;
Сообщить(ТекстСообщения);
КонецЦикла;
Здесь Стр — это объект строки таблицы, через который мы получаем доступ к любой колонке (Номенклатура, Обозначение, Колво) текущей итерации. Это надежный и быстрый способ обработки информации.
Следующий важный этап — возврат данных. Часто программисты пытаются использовать ссылку на документ, полученную из глобальной переменной или параметров, и вызывают метод ПолучитьОбъект(). Проанализируем, почему это приводит к тому, что данные в открытой форме документа не появляются.
Суть проблемы: Когда мы вызываем Ссылка.ПолучитьОбъект(), 1С создает в оперативной памяти новый экземпляр объекта. Мы можем успешно добавить в него строки и даже вызвать метод Записать(), но форма документа, которая уже открыта у пользователя на экране, ничего об этом не узнает. Она продолжает работать со своим собственным экземпляром объекта, который был загружен при открытии.
Рассмотрим, как делать НЕЛЬЗЯ:
// Этот код изменит данные в базе (если вызвать Записать),
// но не в открытом окне документа!
ОбъектДокумента = ДокСсылка.ПолучитьОбъект();
НоваяСтрока = ОбъектДокумента.Товары.Добавить();
НоваяСтрока.Номенклатура = ВыбранныйТовар;
// Пользователь не увидит изменений в текущей форме
Для того чтобы изменения отобразились в интерфейсе «здесь и сейчас», нам нужно работать именно с тем объектом, который «держит» форма документа. Рассмотрим два эффективных способа.
Если обработка открывается модально или с указанием владельца, мы можем напрямую обратиться к данным формы-родителя. В обычном приложении это реализуется через обращение к ЭтаФорма.ВладелецФормы.
Пример реализации в коде обработки:
// Проверяем, что владелец — это форма документа
Если ТипЗнч(ВладелецФормы) = Тип("Форма") Тогда
// Обращаемся к объекту документа владельца
ДокОбъект = ВладелецФормы.ЭтотОбъект;
Для Каждого СтрокаИст Из МояТаблицаОстатков Цикл
Если СтрокаИст.Забрать = Истина Тогда
НоваяСтрока = ДокОбъект.Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИст);
КонецЕсли;
КонецЦикла;
КонецЕсли;
При открытии обработки из формы документа мы можем передать сам объект ЭтотОбъект (не путать со ссылкой Ссылка!) в переменную обработки. Это позволит нам напрямую манипулировать табличной частью документа.
В форме документа:
ФормаПодбора = Обработки.ПодборНоменклатуры.ПолучитьФорму("Форма");
// Передаем ссылку на текущий объект документа в реквизит обработки
ФормаПодбора.ДокументОбъект = ЭтотОбъект;
ФормаПодбора.Открыть();
В форме обработки (при записи/завершении):
// ДокументОбъект — это реквизит обработки с типом ДокументОбъект.ИмяДокумента
Для Каждого Стр Из ТаблицаВыбора Цикл
НоваяСтр = ДокументОбъект.Товары.Добавить();
НоваяСтр.Номенклатура = Стр.Номенклатура;
НоваяСтр.Количество = Стр.Колво;
КонецЦикла;
Важный нюанс: После программного изменения табличной части документа из внешней обработки, визуальное обновление таблицы в форме владельца может не произойти мгновенно. В некоторых случаях полезно вызвать метод ОбновитьОтображениеДанных() для формы документа, чтобы пользователь сразу увидел результат подбора.
Подводя итог, при работе с таблицами и передачей данных между формами в обычном приложении 1С 8.3, всегда придерживайтесь следующих правил:
ТекущиеДанные для обхода всей таблицы в цикле.ПолучитьОбъект() по ссылке, так как это создаст копию в памяти.ВладелецФормы или прямой проброс ЭтотОбъект в параметры обработки.Соблюдение этих принципов позволит вам избежать ошибок "зачерствевшего мозга" и писать чистый, эффективный код, который предсказуемо ведет себя в интерфейсе пользователя.