При работе в среде 1С:Предприятие на обычных формах (8.1, 8.2 или 8.3 в режиме совместимости) часто возникает задача автоматизации: нужно открыть внешнюю обработку прямо из документа, передать в неё ссылку и сразу заполнить таблицу данными. В этой статье мы подробно разберем, как реализовать этот механизм, проанализируем типичные ошибки начинающих разработчиков и выясним, почему программное заполнение полей не всегда приводит к желаемому результату.
Рассмотрим сценарий: в документе РеализацияТоваровУслуг добавлена кнопка «Статусы накладных». При нажатии должна открываться внешняя обработка, в которой поле выбора ВыборМЗ (Маршрутное задание) заполняется автоматически на основании текущей реализации. Главная проблема заключается в том, что после программной установки значения в поле выбора, таблица на форме обработки остается пустой, хотя при ручном (интерактивном) выборе пользователем всё работает корректно.
Для начала нам нужно извлечь файл обработки из справочника ВнешниеОбработки, сохранить его во временный файл и получить форму. Проанализируем правильный подход к этому процессу в коде формы документа:
Процедура СтатусыНакладныхНажатие(Элемент)
// 1. Ищем обработку в справочнике
ВнешняяФорма = Справочники.ВнешниеОбработки.НайтиПоНаименованию("Статусы накладных");
Если ВнешняяФорма.Пустая() Тогда
Сообщить("Внешняя обработка не найдена!");
Возврат;
КонецЕсли;
// 2. Получаем двоичные данные и пишем во временный файл
ИмяФайла = ПолучитьИмяВременногоФайла("epf");
ДвоичныеДанные = ВнешняяФорма.ХранилищеВнешнейОбработки.Получить();
ДвоичныеДанные.Записать(ИмяФайла);
// 3. Получаем форму обработки
Форма = ВнешниеОбработки.ПолучитьФорму(ИмяФайла);
// 4. Логика поиска связанного объекта (Маршрутного задания)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| МаршрутноеЗаданиеДокументыРеализации.Ссылка КАК МЗ
|ИЗ
| Документ.МаршрутноеЗадание.ДокументыРеализации КАК МаршрутноеЗаданиеДокументыРеализации
|ГДЕ
| МаршрутноеЗаданиеДокументыРеализации.Реализация = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Результат = Запрос.Выполнить().Выбрать();
Если Результат.Следующий() Тогда
// Передаем значение в реквизит формы обработки
Форма.ВыборМЗ = Результат.МЗ;
// ВАЖНО: Здесь нужно вызвать заполнение таблицы
Форма.ЗагрузитьСтатусыДокументов();
Форма.Открыть();
Иначе
Сообщить("Для текущей реализации нет маршрутного задания!");
КонецЕсли;
КонецПроцедуры
Разберем важный нюанс: когда вы пишете Форма.ВыборМЗ = Значение, событие ВыборМЗПриИзменении, привязанное к элементу формы, не вызывается. События элементов управления (такие как ПриИзменении, Нажатие, АвтоПодбор) срабатывают только при интерактивном действии пользователя в интерфейсе.
Чтобы данные в таблице заполнились автоматически при программном вызове, необходимо сделать процедуру заполнения таблицы в модуле формы обработки экспортной. Для этого добавим ключевое слово Экспорт в заголовке процедуры:
// В модуле формы внешней обработки
Процедура ЗагрузитьСтатусыДокументов() Экспорт
Если НЕ ЗначениеЗаполнено(ВыборМЗ) Тогда
Возврат;
КонецЕсли;
// Ваш запрос для заполнения таблицы
Запрос = Новый Запрос;
// ... текст запроса ...
Запрос.УстановитьПараметр("Ссылка", ВыборМЗ);
// Заполняем таблицу значений на форме
ТаблицаСтатуса = Запрос.Выполнить().Выгрузить();
// Если это Табличное Поле, связанное с ТЗ, возможно потребуется перестроить колонки
ЭлементыФормы.ТаблицаСтатуса.СоздатьКолонки();
КонецПроцедуры
Как мы видели в обсуждении, использование произвольной ТаблицыЗначений на форме может вызвать трудности с динамическим созданием колонок и типами данных. Рассмотрим более надежный метод: использование Табличной части самого объекта обработки.
СтатусыДокументов и добавьте в неё все необходимые реквизиты (Документ, Статус, Комментарий и т.д.).Загрузить(), который работает гораздо быстрее и стабильнее.
// В процедуре заполнения обработки
РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда
// Обращаемся к данным объекта
ЭтотОбъект.СтатусыДокументов.Загрузить(РезультатЗапроса.Выгрузить());
КонецЕсли;
Важно: Если вы используете обычные формы, убедитесь, что в свойствах элемента ТабличноеПоле на форме в поле «Данные» указана именно ваша табличная часть (например, СтатусыДокументов).
Выясним причину, по которой изменения в коде внешней обработки часто «не видны» при запуске из документа. Это происходит из-за кэширования временных файлов платформой 1С. Разберем, как правильно отлаживать такой код:
Проанализируем ситуацию: вы сохранили изменения во внешнем файле .epf на диске, но при нажатии кнопки в документе 1С всё равно тянет старую версию из хранилища справочника ВнешниеОбработки. Чтобы проверить актуальный код, используйте следующий прием в процедуре открытия:
Сообщить("Проверка связи") в процедуру ПриОткрытии обработки.
// В коде документа для отладки
// ИмяФайла = ПолучитьИмяВременногоФайла(); // закомментировать
ИмяФайла = "C:\MyWorks\Statuses.epf"; // прямой путь
Форма = ВнешниеОбработки.ПолучитьФорму(ИмяФайла);
Посмотрим на пример запроса, который может вызвать ошибку. В сообщении 16 автор столкнулся с ошибкой «Поле не найдено». Это произошло из-за неверного обращения к реквизитам табличной части. Проанализируем правильное построение связи между Реализацией и Маршрутным заданием:
Если нам нужно найти Маршрутное задание, в котором в табличной части ДокументыРеализации присутствует наш текущий документ, запрос должен выглядеть так:
ВЫБРАТЬ
ТЧ.Ссылка КАК СсылкаНаМЗ
ИЗ
Документ.МаршрутноеЗадание.ДокументыРеализации КАК ТЧ
ГДЕ
ТЧ.Реализация = &ТекущаяРеализация
И ТЧ.Ссылка.Проведен = ИСТИНА // желательно проверять только проведенные МЗ
Использование ЛЕВОЕ СОЕДИНЕНИЕ, как в исходном коде автора, избыточно, если нам нужно просто найти ссылку на родительский документ по табличной части. Достаточно простого обращения к физической таблице ТЧ документа.
Подведем итоги нашего разбора. Чтобы вызвать внешнюю форму и заполнить её данными, придерживайтесь следующего алгоритма:
Экспорт.Форма.Реквизит = Значение).Форма.МояПроцедураЗаполнения()).Форма.Открыть().Соблюдение этих правил обеспечит стабильную работу ваших интеграций и исключит «мистические» ошибки, связанные с пустыми данными в интерфейсе пользователя.