При разработке интерфейсов в платформе «1С:Предприятие 7.7» нередко возникает задача: на форме справочника или документа отображается таблица значений с подчиненными данными (например, списком штрихкодов номенклатуры), и пользователю предоставляется возможность открыть карточку строки на редактирование, после чего данные в таблице должны сразу же актуализироваться.
Рассмотрим типовую ошибку, с которой сталкиваются разработчики при попытке реализовать такое обновление, выясним ее причину и разберем надежные варианты решения задачи.
Проанализируем исходный фрагмент кода, приводящий к некорректной работе:
Элемент = ШК.ПолучитьЗначение(Позиция, "Штрихкод");
ОткрытьФорму(Элемент, Контекст);
ПолучитьСписокШтрихКодов(); // Процедура перезаполнения таблицы значений
Разработчик ожидает, что выполнение кода приостановится, пока пользователь редактирует штрихкод, и только после закрытия карточки выполнится процедура ПолучитьСписокШтрихКодов(). Однако на практике процедура обновления отрабатывает моментально, еще до того, как открытая форма появится на экране.
Причина поведения платформы: штатная процедура ОткрытьФорму() в 1С 7.7 работает асинхронно (неблокирующе). Она посылает системе команду открыть окно и незамедлительно передает управление следующей строке исходного кода. Поскольку пользователь еще физически не успел изменить и записать данные, процедура обновления считывает из базы старые значения.
Самый простой и быстрый способ решить проблему — приостановить выполнение программного кода в вызывающей форме до тех пор, пока пользователь не завершит работу с открываемым объектом. Для этого применим метод ОткрытьФормуМодально().
Посмотрим на пример базовой реализации:
Элемент = ШК.ПолучитьЗначение(Позиция, "Штрихкод");
ОткрытьФормуМодально(Элемент);
ПолучитьСписокШтрихКодов();
В этом случае платформа блокирует вызывающее окно и останавливает исполнение модуля на строке вызова. Как только пользователь сохранит или закроет карточку, управление перейдет к следующей строке, и таблица значений успешно заполнится новыми данными.
Однако у простого вызова ОткрытьФормуМодально() есть нюанс: если пользователь просто открыл элемент и нажал «Отмена» (или закрыл крестиком без сохранения), процедура ПолучитьСписокШтрихКодов() все равно выполнит повторное чтение данных из базы вхолостую.
Разберем по шагам, как оптимизировать этот процесс с помощью передачи параметра-флага:
0 и передадим ее вторым параметром в модальное окно.ПриЗаписи() изменим значение системного свойства Форма.Параметр на 1.1, производим обновление, если равен 0 — пропускаем лишнее чтение базы.Код кнопки в вызывающей форме:
Элемент = ШК.ПолучитьЗначение(Позиция, "Штрихкод");
ФлагЗаписи = 0;
ОткрытьФормуМодально(Элемент, ФлагЗаписи);
Если ФлагЗаписи = 1 Тогда
ПолучитьСписокШтрихКодов();
КонецЕсли;
Код в модуле формы редактируемого элемента справочника:
Процедура ПриЗаписи()
// Уведомляем вызывающую форму о том, что объект был успешно сохранен
Форма.Параметр = 1;
КонецПроцедуры
Модальный режим имеет существенный недостаток: он полностью блокирует интерфейс программы. Пользователь не может параллельно открыть другие справочники, скопировать значение из соседнего окна или использовать главное меню. Если требуется оставить открытие карточки обычным (немодальным), то использовать вызов следующей строкой нельзя.
В 1С 7.7 нельзя напрямую вызвать экспортную процедуру одной формы из другой формы через Контекст (это вызовет ошибку «Поле агрегатного объекта не обнаружено»). Рассмотрим подробнее, как обойти это ограничение штатным путем:
ОткрытьФорму(Элемент, Контекст).ПриЗаписи() вызовем эту глобальную процедуру. Данные в таблице значений обновятся прямо в момент сохранения карточки, даже если сама форма штрихкода еще не закрыта.Код в глобальном модуле конфигурации:
Процедура глОбновитьТаблицуШтрихКодов(КонтФормы) Экспорт
Если ТипЗначенияСтр(КонтФормы) = "ГрупповойКонтекст" Тогда
// Вызываем штатную логику пересчета или наполнения ТЗ в переданном контексте
КонтФормы.ПолучитьСписокШтрихКодов();
КонецЕсли;
КонецПроцедуры
Код вызова в исходной форме (справочник ТМЦ):
Элемент = ШК.ПолучитьЗначение(Позиция, "Штрихкод");
// Передаем собственный групповой контекст в открываемую форму
ОткрытьФорму(Элемент, Контекст);
Код в форме подчиненного элемента справочника (Штрихкод):
Процедура ПриЗаписи()
// Проверяем, передан ли контекст формы-владельца
Если ТипЗначенияСтр(Форма.Параметр) = "ГрупповойКонтекст" Тогда
глОбновитьТаблицуШтрихКодов(Форма.Параметр);
КонецЕсли;
КонецПроцедуры
Такой подход обеспечивает максимальное удобство для пользователя, исключает зависание интерфейса и гарантирует синхронизацию данных на экране сразу по нажатию кнопки «Записать».
Если в вашей конфигурации используются внешние компоненты расширения платформы (такие как 1С++ или FormEx), задачу можно решить еще гибче:
Для типовых конфигураций без сторонних библиотек наиболее быстрым и надежным остается применение ОткрытьФормуМодально() с проверкой флага записи либо вынос процедуры обновления в глобальный модуль.