Как получить данные из формы открытого окна в 1С 7.7 и передать их обратно

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

Метод 1: Использование передачи Контекста (Штатный способ)

Наиболее надежный и правильный способ взаимодействия между формой документа и внешней обработкой — это передача ключевого слова Контекст при открытии. Это позволяет «связать» две формы. Рассмотрим ситуацию: у нас есть открытый документ «Чек», и нам нужно вызвать обработку для расчета скидки, которая затем вернет результат в этот же чек.

Для начала проанализируем, как вызвать внешнюю обработку из формы документа. На форму документа необходимо добавить кнопку, в формуле которой прописать вызов:


// В модуле формы документа Чек
Процедура ВызватьРасчет()
    // Передаем Контекст в качестве второго параметра функции ОткрытьФорму
    ОткрытьФорму("Отчет", Контекст, КаталогИБ() + "ВнешниеФормы\РасчетСкидки.ert");
КонецПроцедуры

Теперь разберем, что происходит внутри внешней обработки РасчетСкидки.ert. Чтобы получить доступ к данным чека, мы должны считать переданный параметр при открытии. Разберем этот процесс по шагам:

  1. Объявим переменную для хранения контекста документа на уровне модуля обработки.
  2. В предопределенной процедуре ПриОткрытии получим ссылку на форму-владельца.
  3. Выполним необходимые вычисления и программно изменим реквизиты исходного документа.

Посмотрим на пример реализации кода в модуле внешней обработки:


Перем КонтекстДок; // Глобальная переменная модуля

Процедура ПриОткрытии()
    // Получаем переданный контекст через Форма.Параметр
    КонтекстДок = Форма.Параметр;
    
    // Проверим, что контекст передан корректно
    Если ТипЗначенияСтр(КонтекстДок) <> "ГрупповойКонтекст" Тогда
        Предупреждение("Обработка должна запускаться только из формы документа!");
        СтатусВозврата(0);
        Возврат;
    КонецЕсли;
    
    // Теперь мы можем прочитать данные прямо из открытого чека
    ТекущаяСумма = КонтекстДок.СуммаОплаты;
    Сообщить("Сумма в открытом чеке: " + ТекущаяСумма);
КонецПроцедуры

Процедура ВыполнитьРасчет()
    // Допустим, мы рассчитали новую сумму
    НоваяСумма = КонтекстДок.СуммаОплаты * 0.9; // Скидка 10%
    
    // Передаем значение обратно в открытую форму документа
    КонтекстДок.СуммаОплаты = НоваяСумма;
    
    // ВАЖНО: Чтобы пользователь увидел изменения на экране, нужно обновить форму
    КонтекстДок.Форма.Обновить();
    
    Сообщить("Скидка успешно применена!");
    Форма.Закрыть(0);
КонецПроцедуры

Этот метод позволяет работать даже с незаписанными данными, которые пользователь только что ввел на экране. Обратите внимание, что изменения происходят в оперативной памяти (в контексте формы), и пользователю все равно нужно будет нажать «ОК» или «Записать» в самом документе, чтобы данные попали в базу.

Метод 2: Работа через внешнюю компоненту FormEx

Если перед нами стоит задача получить данные из открытого окна «без изменения конфигурации» (то есть мы не можем добавить кнопку в документ и передать Контекст), штатные средства 1С 7.7 бессильны. В этом случае на помощь приходит внешняя компонента FormEx.

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

Рассмотрим пример логики работы с FormEx:


// Пример использования FormEx (требуется загруженная компонента)
Сервис = СоздатьОбъект("Сервис");
ВсеОкна = Сервис.КоличествоОкон();

Для Номер = 1 По ВсеОкна Цикл
    ТекОкно = Сервис.ПолучитьОкно(Номер);
    Если ТекОкно.Заголовок = "Чек №..." Тогда
        // Получаем контекст формы этого окна
        Конт = ТекОкно.Контекст;
        // Работаем с данными
        Сумма = Конт.СуммаОплаты;
    КонецЕсли;
КонецЦикла;

Этот способ является наиболее близким к поведению 1С 8.x. Однако он требует наличия сторонних библиотек (dll) в каталоге программы и их регистрации в системе или динамической загрузки через ЗагрузитьВнешнююКомпоненту().

Метод 3: Использование Глобального модуля как посредника

Выясним еще одну хитрость, которую часто используют опытные разработчики. Если нужно обращаться к открытой форме из разных мест, можно создать в Глобальном модуле переменную глТекущийКонтекст.

В модуле формы документа (например, в процедуре ПриАктивизации или ПриОткрытии) мы пишем:

глТекущийКонтекст = Контекст;

Теперь любая внешняя обработка, запущенная через «Файл — Открыть», сможет прочитать данные из этой переменной. Но будьте осторожны: этот метод требует дисциплины в разработке, так как при переключении между разными окнами значение переменной должно корректно перезаписываться, иначе вы рискуете изменить данные не в том документе.

Сравнение подходов и выводы

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

  1. Если можно менять конфигурацию: Используйте Метод 1 (Передача Контекст). Это самый стабильный, быстрый и «чистый» способ программирования в 7.7. Он гарантирует, что вы работаете именно с тем объектом, из которого вызвали обработку.
  2. Если нельзя менять конфигурацию: Ваш единственный путь — внешние компоненты (FormEx или 1С++). Они расширяют объектную модель 7.7, добавляя функционал, который в 8-й версии стал стандартным.
  3. Если документ уже сохранен: Если вам не нужны текущие экранные данные, а достаточно тех, что в базе, используйте стандартный СоздатьОбъект("Документ.Чек") и НайтиДокумент(). Но помните, что так вы не увидите изменений, которые пользователь внес, но еще не сохранил.

В заключение отметим важный технический нюанс: при программном изменении реквизитов через контекст (КонтекстДок.Реквизит = Значение), 1С 7.7 не всегда автоматически пересчитывает связанные итоги или визуальные элементы. Всегда используйте КонтекстДок.Форма.Обновить() для синхронизации экранных данных.

← На главную