Как программно заполнить таблицу во внешней обработке при вызове из формы документа (Обычные формы)

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Постановка задачи и анализ ситуации

Рассмотрим сценарий: в документе РеализацияТоваровУслуг добавлена кнопка «Статусы накладных». При нажатии должна открываться внешняя обработка, в которой поле выбора ВыборМЗ (Маршрутное задание) заполняется автоматически на основании текущей реализации. Главная проблема заключается в том, что после программной установки значения в поле выбора, таблица на форме обработки остается пустой, хотя при ручном (интерактивном) выборе пользователем всё работает корректно.

Шаг 1: Программное получение и открытие внешней формы

Для начала нам нужно извлечь файл обработки из справочника ВнешниеОбработки, сохранить его во временный файл и получить форму. Проанализируем правильный подход к этому процессу в коде формы документа:


Процедура СтатусыНакладныхНажатие(Элемент)
    // 1. Ищем обработку в справочнике
    ВнешняяФорма = Справочники.ВнешниеОбработки.НайтиПоНаименованию("Статусы накладных");
    Если ВнешняяФорма.Пустая() Тогда
        Сообщить("Внешняя обработка не найдена!");
        Возврат;
    КонецЕсли;

    // 2. Получаем двоичные данные и пишем во временный файл
    ИмяФайла = ПолучитьИмяВременногоФайла("epf");
    ДвоичныеДанные = ВнешняяФорма.ХранилищеВнешнейОбработки.Получить();
    ДвоичныеДанные.Записать(ИмяФайла);

    // 3. Получаем форму обработки
    Форма = ВнешниеОбработки.ПолучитьФорму(ИмяФайла);
    
    // 4. Логика поиска связанного объекта (Маршрутного задания)
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |    МаршрутноеЗаданиеДокументыРеализации.Ссылка КАК МЗ
    |ИЗ
    |    Документ.МаршрутноеЗадание.ДокументыРеализации КАК МаршрутноеЗаданиеДокументыРеализации
    |ГДЕ
    |    МаршрутноеЗаданиеДокументыРеализации.Реализация = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", Ссылка);
    Результат = Запрос.Выполнить().Выбрать();
    
    Если Результат.Следующий() Тогда
        // Передаем значение в реквизит формы обработки
        Форма.ВыборМЗ = Результат.МЗ;
        
        // ВАЖНО: Здесь нужно вызвать заполнение таблицы
        Форма.ЗагрузитьСтатусыДокументов(); 
        
        Форма.Открыть();
    Иначе
        Сообщить("Для текущей реализации нет маршрутного задания!");
    КонецЕсли;
КонецПроцедуры

Шаг 2: Проблема события «ПриИзменении»

Разберем важный нюанс: когда вы пишете Форма.ВыборМЗ = Значение, событие ВыборМЗПриИзменении, привязанное к элементу формы, не вызывается. События элементов управления (такие как ПриИзменении, Нажатие, АвтоПодбор) срабатывают только при интерактивном действии пользователя в интерфейсе.

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


// В модуле формы внешней обработки
Процедура ЗагрузитьСтатусыДокументов() Экспорт
    Если НЕ ЗначениеЗаполнено(ВыборМЗ) Тогда
        Возврат;
    КонецЕсли;
    
    // Ваш запрос для заполнения таблицы
    Запрос = Новый Запрос;
    // ... текст запроса ...
    Запрос.УстановитьПараметр("Ссылка", ВыборМЗ);
    
    // Заполняем таблицу значений на форме
    ТаблицаСтатуса = Запрос.Выполнить().Выгрузить();
    
    // Если это Табличное Поле, связанное с ТЗ, возможно потребуется перестроить колонки
    ЭлементыФормы.ТаблицаСтатуса.СоздатьКолонки();
КонецПроцедуры

Шаг 3: Использование Табличных частей вместо Таблиц значений

Как мы видели в обсуждении, использование произвольной ТаблицыЗначений на форме может вызвать трудности с динамическим созданием колонок и типами данных. Рассмотрим более надежный метод: использование Табличной части самого объекта обработки.

  1. В конфигураторе (или во внешней обработке) создайте Табличную часть СтатусыДокументов и добавьте в неё все необходимые реквизиты (Документ, Статус, Комментарий и т.д.).
  2. В коде заполнения используйте метод Загрузить(), который работает гораздо быстрее и стабильнее.

// В процедуре заполнения обработки
РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда
    // Обращаемся к данным объекта
    ЭтотОбъект.СтатусыДокументов.Загрузить(РезультатЗапроса.Выгрузить());
КонецЕсли;

Важно: Если вы используете обычные формы, убедитесь, что в свойствах элемента ТабличноеПоле на форме в поле «Данные» указана именно ваша табличная часть (например, СтатусыДокументов).

Шаг 4: Отладка внешних обработок

Выясним причину, по которой изменения в коде внешней обработки часто «не видны» при запуске из документа. Это происходит из-за кэширования временных файлов платформой 1С. Разберем, как правильно отлаживать такой код:

Проанализируем ситуацию: вы сохранили изменения во внешнем файле .epf на диске, но при нажатии кнопки в документе 1С всё равно тянет старую версию из хранилища справочника ВнешниеОбработки. Чтобы проверить актуальный код, используйте следующий прием в процедуре открытия:

  1. Временно закомментируйте код извлечения двоичных данных из справочника.
  2. Укажите прямой путь к файлу на вашем диске, где вы ведете разработку.
  3. Вставьте Сообщить("Проверка связи") в процедуру ПриОткрытии обработки.

// В коде документа для отладки
// ИмяФайла = ПолучитьИмяВременногоФайла(); // закомментировать
ИмяФайла = "C:\MyWorks\Statuses.epf"; // прямой путь
Форма = ВнешниеОбработки.ПолучитьФорму(ИмяФайла);

Типичные ошибки при работе с запросами

Посмотрим на пример запроса, который может вызвать ошибку. В сообщении 16 автор столкнулся с ошибкой «Поле не найдено». Это произошло из-за неверного обращения к реквизитам табличной части. Проанализируем правильное построение связи между Реализацией и Маршрутным заданием:

Если нам нужно найти Маршрутное задание, в котором в табличной части ДокументыРеализации присутствует наш текущий документ, запрос должен выглядеть так:


ВЫБРАТЬ
    ТЧ.Ссылка КАК СсылкаНаМЗ
ИЗ
    Документ.МаршрутноеЗадание.ДокументыРеализации КАК ТЧ
ГДЕ
    ТЧ.Реализация = &ТекущаяРеализация
    И ТЧ.Ссылка.Проведен = ИСТИНА // желательно проверять только проведенные МЗ

Использование ЛЕВОЕ СОЕДИНЕНИЕ, как в исходном коде автора, избыточно, если нам нужно просто найти ссылку на родительский документ по табличной части. Достаточно простого обращения к физической таблице ТЧ документа.

Итоги и рекомендации

Подведем итоги нашего разбора. Чтобы вызвать внешнюю форму и заполнить её данными, придерживайтесь следующего алгоритма:

  1. Подготовка формы: Процедура заполнения таблицы в обработке должна иметь префикс Экспорт.
  2. Передача параметров: Сначала присваивайте значения реквизитам полученной формы (Форма.Реквизит = Значение).
  3. Принудительный вызов: Сразу после присвоения вызывайте экспортную процедуру заполнения (Форма.МояПроцедураЗаполнения()).
  4. Визуализация: Только после выполнения всех расчетов вызывайте Форма.Открыть().
  5. Контроль типов: Всегда проверяйте, что передаваемая ссылка соответствует ожидаемому типу в обработке, чтобы избежать пустых таблиц из-за несоответствия типов в параметрах запроса.

Соблюдение этих правил обеспечит стабильную работу ваших интеграций и исключит «мистические» ошибки, связанные с пустыми данными в интерфейсе пользователя.

← На главную