Передача данных между формами в 1С:Предприятие 8.3 — одна из самых частых задач при разработке интерфейсов. Без правильной организации обмена информацией формы становятся изолированными, а пользователю приходится вводить одни и те же данные несколько раз. В этой статье разберём 5 проверенных способов передачи данных: от простых параметров до сложных механизмов с событиями и временными хранилищами.
Каждый метод имеет свои плюсы и минусы. Например, параметры формы подходят для разовых передач небольших данных, а общие модули или временные хранилища — для работы с большими объёмами или когда формы открываются независимо. Мы не только покажем код, но и объясним, когда какой способ применять, чтобы избежать типичных ошибок.
Особое внимание уделим проблеме "зависших" ссылок на объекты при передаче через параметры — это частая причина падений 1С, о которой мало где пишут. Также разберём, как безопасно передавать СправочникСсылка или ДокументОбъект без риска потери данных при закрытии формы.
1. Передача данных через параметры формы
Самый простой и быстрый способ — передать данные при открытии формы через её параметры. Этот метод идеален для разовых операций, когда одна форма вызывает другую и нужно передать 1-2 значения (например, ссылку на документ или фильтр для списка).
Как это работает:
- При открытии формы указываем параметры в методе
ОткрытьФорму(). - В принимающей форме описываем эти параметры в модуле объекта.
- Используем переданные данные в обработчиках (например, при создании или загрузке формы).
Пример кода для передачи ссылки на документ "Заказ клиента":
// Отправляющая форма (кнопка "Открыть детали заказа")
Процедура КомандыОткрытьДеталиЗаказа(Команда)
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("СсылкаНаДокумент", Объект.Ссылка);
ОткрытьФорму("Документ.ЗаказКлиента.Форма.ФормаДетали", ПараметрыФормы);
КонецПроцедуры
// Принимающая форма (модуль объекта)
Перем СсылкаНаДокумент;
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("СсылкаНаДокумент") Тогда
СсылкаНаДокумент = Параметры.СсылкаНаДокумент;
ЗагрузитьДанныеДокумента(СсылкаНаДокумент);
КонецЕсли;
КонецПроцедуры
⚠️ Внимание: При передаче СсылкаНаДокумент или других объектных типов через параметры убедитесь, что принимающая форма не пытается использовать их после закрытия исходной формы. Это приведёт к ошибке "Объект не найден (Object not found)", так как ссылки становятся недействительными.
Если нужно передать несколько параметров, используйте Структура вместо отдельных аргументов. Это упрощает поддержку кода и добавляет гибкость.
2. Использование общих модулей для хранения данных
Когда данные нужно передавать между формами, которые открываются независимо (например, из разных разделов программы), параметры не подойдут. Здесь поможет общий модуль с экспортируемыми переменными или методами. Этот способ удобен для:
- 📌 Глобальных настроек (например, текущий пользователь или филиал).
- 📌 Кэширования часто используемых данных (справочники, курсы валют).
- 📌 Обмена данными между формами, которые не связаны напрямую.
Пример организации общего модуля "ОбменДаннымиМеждуФормами":
// Общий модуль (свойство "Глобальный" = Истина)
Перем ТекущийЗаказКлиента Экспорт;
Перем СписокВыбранныхТоваров Экспорт;
// Метод для очистки данных
Процедура ОчиститьДанные() Экспорт
ТекущийЗаказКлиента = Неопределено;
СписокВыбранныхТоваров = Новый Массив;
КонецПроцедуры
Как использовать в формах:
// Форма 1: сохраняем данные
ОбменДаннымиМеждуФормами.ТекущийЗаказКлиента = Объект.Ссылка;
// Форма 2: читаем данные
Если Не ОбменДаннымиМеждуФормами.ТекущийЗаказКлиента = Неопределено Тогда
Сообщить("Текущий заказ: " + ОбменДаннымиМеждуФормами.ТекущийЗаказКлиента);
КонецЕсли;
⚠️ Внимание: Данные в общих модулях хранятся в памяти сеанса. Если пользователь закроет 1С или сеанс будет прерван, информация потеряется. Для долговременного хранения используйте регистры сведений или временные хранилища.
3. Временные хранилища: надёжный обмен большими данными
Если нужно передать большой объём данных (например, таблицу значений с тысячей строк) или обеспечить сохранность информации между сеансами, используйте временные хранилища (ПоместитьВоВременноеХранилище() / ПолучитьИзВременногоХранилища()). Этот метод работает даже если формы открываются в разных сеансах или на разных клиентах (при правильной настройке).
Преимущества временных хранилищ:
- 🔹 Сохраняют данные между сеансами (если не очищать вручную).
- 🔹 Поддерживают любые типы данных 1С (таблицы, деревья значений, объекты).
- 🔹 Можно передавать данные между разными базами (при использовании распределённого временного хранилища).
Пример передачи таблицы товаров:
// Форма 1: помещаем данные во временное хранилище
ТаблицаТоваров = ПолучитьТаблицуТоваров(); // Ваш метод получения данных
Идентификатор = ПоместитьВоВременноеХранилище(ТаблицаТоваров, УникальныйИдентификатор());
// Форма 2: получаем данные
Если ЗначениеЗаполнено(Идентификатор) Тогда
ТаблицаТоваров = ПолучитьИзВременногоХранилища(Идентификатор);
Если ТаблицаТоваров = Неопределено Тогда
Сообщить("Данные устарели или удалены!");
Иначе
ЗагрузитьТовары(ТаблицаТоваров);
КонецЕсли;
КонецЕсли;
| Метод | Макс. размер данных | Сохранность между сеансами | Поддержка сложных типов |
|---|---|---|---|
| Параметры формы | Ограничен размером стека | ❌ Нет | ✅ Да (но риск потери ссылок) |
| Общие модули | Ограничен памятью сеанса | ❌ Нет | ✅ Да |
| Временные хранилища | До 2 ГБ (зависит от СУБД) | ✅ Да (до очистки) | ✅ Да |
| События | Ограничен размером сообщения | ❌ Нет | ✅ Да (сериализуемые типы) |
Как очистить временное хранилище?
Используйте метод ОчиститьВременноеХранилище(Идентификатор). Если не очищать вручную, данные удалятся автоматически при перезапуске сервера 1С или по истечении времени жизни (настраивается в конфигураторе).
4. Передача данных через события
Механизм событий в 1С позволяет передавать данные между формами без прямой связи. Одна форма публикует событие, а другая — подписывается на него. Этот способ полезен для:
- 🔔 Оповещения нескольких форм об изменении данных.
- 🔔 Динамического обновления интерфейса (например, при изменении статуса документа).
- 🔔 Реализации паттерна "Издатель-Подписчик".
Пример с событием "ЗаказОплачен":
// Общий модуль "СобытияЗаказов"
Перем ОповещениеОбОплате;
Процедура ИнициализироватьСобытия() Экспорт
ОповещениеОбОплате = Новый Оповещение("ЗаказОплачен", ЭтотОбъект);
КонецПроцедуры
Процедура ЗаказОплаченПриПодписке(СсылкаНаЗаказ, Сумма) Экспорт
// Логика обработки события
Сообщить("Заказ " + СсылкаНаЗаказ + " оплачен на сумму " + Сумма);
КонецПроцедуры
Как опубликовать событие из формы:
СобытияЗаказов.ОповещениеОбОплате.Опубликовать(Объект.Ссылка, Объект.СуммаДокумента);
Как подписаться на событие в другой форме:
Процедура ПриОткрытии(Отказ)
СобытияЗаказов.ИнициализироватьСобытия();
СобытияЗаказов.ОповещениеОбОплате.Подписаться("ЗаказОплаченПриПодписке");
КонецПроцедуры
⚠️ Внимание: События работают только в рамках одного сеанса. Если нужно передавать данные между разными сеансами или клиентами, используйте внешние события (ВнешнееСобытие) или механизм рассылки.
5. Обмен через реквизиты формы (для связанных форм)
Если формы связаны иерархически (например, основная форма и подчинённая), можно передавать данные через реквизиты. Этот метод удобен для:
- 📋 Передачи контекста (например, текущий клиент или период).
- 📋 Синхронизации данных между родительской и дочерней формами.
- 📋 Автоматического обновления подчинённой формы при изменении данных в основной.
Пример: форма "Список клиентов" открывает форму "Заказы клиента" и передаёт текущего клиента через реквизит.
// Основная форма (кнопка "Показать заказы")
Процедура КомандыПоказатьЗаказы(Команда)
НоваяФорма = Формы.ЗаказыКлиента.Создать();
НоваяФорма.Клиент = ТекущийКлиент; // Передаём через реквизит
НоваяФорма.Открыть();
КонецПроцедуры
// Подчинённая форма (модуль объекта)
Процедура ПриИзмененииКлиента()
ОбновитьСписокЗаказов(Клиент);
КонецПроцедуры
✅ Плюсы: данные автоматически синхронизируются при изменении реквизита.
❌ Минусы: работает только для связанных форм (родитель-потомок).
☑️ Проверка перед передачей данных
6. Альтернативные способы: файлы, HTTP-сервисы, прямые ссылки на объекты
В некоторых случаях стандартные методы 1С не подходят. Рассмотрим альтернативные варианты:
1. Обмен через файлы (JSON, XML, XDTO):
- 📄 Подходит для интеграции с внешними системами.
- 📄 Можно передавать данные между разными базами 1С.
Пример сохранения данных в JSON:
Данные = Новый Структура("Клиент, Дата", ТекущийКлиент, ТекущаяДата());
ЗаписатьJSON(ПутьКФайлу, Данные);
2. HTTP-сервисы:
- 🌐 Используйте, если формы работают в разных базах или на разных серверах.
- 🌐 Требует настройки HTTP-сервиса в конфигураторе.
3. Прямые ссылки на объекты (не рекомендуется):
- 🔗 Можно передавать
Ссылкана объект и загружать его заново в другой форме. - 🔗 Риск: если объект удалён или права доступа изменились, возникнет ошибка.
Пример с прямыми ссылками:
// Передаём ссылку (не сам объект!)
Параметры.Вставить("СсылкаНаДокумент", Объект.Ссылка);
// В другой форме загружаем объект по ссылке
Док = Параметры.СсылкаНаДокумент.ПолучитьОбъект();
⚠️ Внимание: При работе с HTTP-сервисами или файлами учитывайте безопасность. Не передавайте конфиденциальные данные (пароли, персональные данные) без шифрования.
Для передачи данных между формами в 1С выбирайте метод исходя из задачи: параметры — для разовых операций, общие модули — для глобальных данных, временные хранилища — для больших объёмов, события — для динамического обмена.
FAQ: Частые вопросы по передаче данных в 1С
Можно ли передавать объект документа целиком через параметры формы?
Технически можно, но крайне не рекомендуется. При закрытии исходной формы объект станет недействительным, и любая попытка обратиться к нему вызовет ошибку. Вместо этого передавайте Ссылка на объект и загружайте его заново в принимающей форме методом ПолучитьОбъект().
Как передать таблицу значений между формами без потери данных?
Лучше всего использовать временные хранилища или сериализацию в JSON. Пример:
// Сериализация в JSON
СтроковоеПредставление = ЗаписатьJSON(ТаблицаЗначений);
// Десериализация
ТаблицаЗначений = ПрочитатьJSON(СтроковоеПредставление);
Если таблица большая (тысячи строк), временное хранилище надёжнее.
Почему при передаче ссылки на справочник через параметры форма падает?
Скорее всего, вы передаёте не саму ссылку (СправочникСсылка.Номенклатура), а объект справочника (СправочникОбъект.Номенклатура). Объекты нельзя передавать между формами — только ссылки или примитивные типы (строка, число). Проверьте тип передаваемых данных:
Если ТипЗнч(Параметры.Номенклатура) = Тип("СправочникОбъект.Номенклатура") Тогда
Сообщить("Ошибка: передан объект, а не ссылка!");
КонецЕсли;
Как обновить данные в форме, если они изменились в другой форме?
Используйте механизм событий или периодический опрос (таймер). Пример с событием:
- В форме, где данные изменяются, опубликуйте событие (например,
"ДанныеОбновлены"). - В форме, где нужно обновить данные, подпишитесь на это событие и вызовите метод перезагрузки.
Для простых случаев можно использовать метод Обновить() у элементов формы (например, ЭлементыФормы.СписокТоваров.Обновить()).
Какие данные нельзя передавать через временные хранилища?
Временные хранилища не поддерживают:
- 🚫 Объекты с несериализуемыми данными (например,
COMОбъект). - 🚫 Динамические списки или формы.
- 🚫 Данные с циклическими ссылками (например, объект A ссылается на объект B, а объект B — на объект A).
Для проверки сериализуемости используйте функцию ЗначениеВСтрокуВнутр(Данные) — если она вернёт ошибку, данные не подходят для временного хранилища.