Как получить реквизиты табличной части другого документа и программно заполнить строки

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

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

Почему данные «не видны» на клиенте

Первым делом проанализируем ситуацию, описанную автором темы. Попытка обратиться к данным через конструкцию Строка.РасходнаяНакладная.СписокНоменклатуры на клиенте обречена на провал. В управляемом приложении действует строгое разделение контекстов:

  1. На клиенте (&НаКлиенте): Ссылка на документ — это лишь уникальный идентификатор (GUID). Она не содержит в себе данных о табличных частях или реквизитах объекта. Именно поэтому отладчик по Shift+F9 не позволяет посмотреть внутрь документа.
  2. На сервере (&НаСервере): Здесь система имеет прямой доступ к базе данных. Чтобы «увидеть» состав накладной, нам необходимо передать ссылку на сервер и там выполнить получение данных.

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

Шаг 1: Настройка события на форме

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


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

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

Шаг 2: Получение данных на сервере через Запрос

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

Рассмотрим структуру серверной процедуры:


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

КонецПроцедуры

Шаг 3: Особенности реализации задачи 1.15

Проанализируем специфику задачи 1.15. В этой задаче требуется распределить сумму затрат по товарам из накладных. Важно помнить, что если в накладной несколько товаров, то сумма должна распределяться пропорционально (например, себестоимости).

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

Проблемы отладки на сервере

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

  1. Режим отладки сервера: Если вы работаете в клиент-серверном варианте (SQL), необходимо, чтобы служба 1С была запущена с ключом -debug. В противном случае точки останова на сервере будут игнорироваться.
  2. Подключение отладчика: Зайдите в меню Отладка -> Подключение и проверьте, что в списке доступных предметов есть «Сервер». Если его нет, нажмите кнопку «Автоматическое подключение» и установите галочку напротив «Серверные вызовы».
  3. Файловая база: В файловой базе таких проблем обычно нет, так как клиент и сервер работают в рамках одного процесса.

Альтернативный подход: Использование подбора

Рассмотрим совет из сообщения №5. Иногда удобнее использовать механизм подбора (кнопка «Подбор»). В этом случае пользователь выбирает одну или несколько накладных в отдельной форме, а затем в обработчике ОбработкаВыбора вы на сервере перебираете все выбранные ссылки и заполняете таблицу по аналогии с вышеуказанным кодом. Это предотвращает «дерганье» интерфейса при случайном изменении значения в строке.

Резюмируем: Для получения реквизитов табличной части другого документа (реквизита реквизита) необходимо:

Такой подход гарантирует высокую производительность системы и корректную работу в управляемом интерфейсе 1С:Предприятие 8.3.

← На главную