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