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

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

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

Разбор типичных ошибок при обращении к данным другого документа

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

Разберем основные ошибки, с которыми столкнулся автор темы:

  1. Несоответствие имен полей в запросе и в коде: В запросе поле может называться ФИО, а в коде разработчик пытается обратиться к Выборка.Студент. Это приводит к ошибке «Поле объекта не обнаружено».
  2. Неправильная типизация: Часто в табличных частях хранятся ссылки на справочники, а параметры передаются в виде строк или наоборот. Для корректной работы запроса типы данных должны совпадать.
  3. Избыточные соединения: Использование ЛЕВОЕ СОЕДИНЕНИЕ между табличной частью и шапкой того же документа в запросе часто является лишним, так как платформа позволяет обращаться к реквизитам шапки через точку от поля Ссылка.

Корректный способ получения данных через запрос

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


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

Профессиональные рекомендации и оптимизация

Выясним, как сделать этот механизм еще более надежным и производительным. Рассмотрим несколько важных аспектов, которые помогут в реальной разработке.

1. Обращение через точку (Разделение на поля). В запросе выше мы использовали конструкцию ПосещениеСтуденты.Ссылка.Подгруппа. Это наиболее эффективный способ получения реквизитов шапки из табличной части. Платформа 1С автоматически преобразует это в оптимальное соединение (SQL JOIN) на уровне базы данных. Нет необходимости вручную прописывать соединение с таблицей Документ.Посещение.

2. Избегайте «запросов в цикле». В приведенном примере запрос выполняется один раз, так как предполагается, что мы ищем данные по одному студенту, указанному в шапке. Однако, если бы документ ИсправлениеОценки содержал список студентов в своей табличной части, выполнять запрос для каждой строки было бы грубой ошибкой. В таком случае правильно было бы:

  1. Выгрузить табличную часть текущего документа в ТаблицуЗначений.
  2. Передать эту таблицу в запрос как параметр.
  3. Поместить её во временную таблицу и соединить с данными документа-основания за один раз.

3. Проверка статуса документа-основания. Проанализируем ситуацию, когда документ-основание был изменен или помечен на удаление. В запрос рекомендуется добавить условия:


ГДЕ
    ПосещениеСтуденты.Ссылка.Проведен = ИСТИНА
    И ПосещениеСтуденты.Ссылка.ПометкаУдаления = ЛОЖЬ

Это обезопасит вашу систему от формирования движений на основании неактуальных или «черновых» данных.

4. Выбор типа регистра. В обсуждении упоминается использование регистра накопления для хранения оценок. С точки зрения архитектуры 1С, для показателей, которые не суммируются (как деньги или товар), а представляют собой состояние (оценку), лучше использовать Регистр сведений. Это упростит получение последнего среза данных и не потребует создания парных движений «Приход»-«Расход» для исправления.

5. Использование псевдонимов (Алиасов). Всегда назначайте понятные псевдонимы полям запроса с помощью ключевого слова КАК. Это делает ваш код читаемым и предотвращает ошибки при обращении к ВыборкаДетальныеЗаписи.ИмяПоля.

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

← На главную