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

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

При разработке печатных форм в среде 1С:Предприятие разработчики часто сталкиваются с необходимостью вывода данных из табличных частей документов в табличные документы (макеты .mxl). Типичная проблема начинающих специалистов — попытка обратиться к реквизитам табличной части напрямую через ссылку на документ (например, ПриказПоПрактике.Студент) или некорректная обработка выборки внутри цикла печати. В результате данные либо выводятся «все в одну строку», либо не выводятся вовсе.

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

Выясняем причину: почему не работает обращение напрямую

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

Для вывода списка студентов в отдельные строки таблицы макета необходимо использовать циклы и выводить строки последовательно. Разберем по шагам, как это реализовать.

---

Решение №1. Исправление параметров в макете и коде (быстрый способ)

В коде автора темы для макета ДоговорПоКонтрагенту используется вложенный запрос к табличной части:


|    ПриказПоПрактике.РаспределениеПрактикантов.(
|        Студент КАК ФИО,
|        Контрагент КАК Контрагент,
|        Договор
|    ),

Обратите внимание на конструкцию Студент КАК ФИО. В самом цикле вывода строк ТЧ используется метод автоматического заполнения параметров области макета:


Для Каждого СтрСтуденты Из СписокСтудентовМассив Цикл
    ОбластьМакета.Параметры.Заполнить(СтрСтуденты);
    ТабличныйДокумент.Вывести(ОбластьМакета);
    Ном=Ном+1;
КонецЦикла;

Метод Заполнить() работает по принципу точного совпадения имен колонок таблицы значений (или структуры) и имен параметров в макете. Если в ячейке макета у вас написан параметр Студент, а в запросе вы переименовали поле в ФИО, то автоматического заполнения не произойдет, и ячейка останется пустой.

Для решения проблемы выполним следующие действия:

  1. Откроем макет печатной формы (в данном случае это макет ПФ_MXL_Договор) в конфигураторе.
  2. Найдем ячейку в области Строка, предназначенную для вывода ФИО студента.
  3. Откроем свойства этой ячейки (клавиша F4).
  4. Убедимся, что свойство «Заполнение» установлено в значение «Параметр». Если там стоит значение «Текст», программа просто выведет текст, написанный в конфигураторе, проигнорировав код 1С.
  5. В поле «Параметр» укажем имя, совпадающее с именем поля в запросе. Если в запросе написано Студент КАК ФИО, то параметр в макете должен называться ФИО (в ячейке макета это будет выглядеть как <ФИО>).
  6. Если мы хотим оставить параметр в макете под именем Студент, тогда в коде перед выводом области нужно заполнить параметр вручную:

Для Каждого СтрСтуденты Из СписокСтудентовМассив Цикл
    ОбластьМакета.Параметры.Заполнить(СтрСтуденты);
    // Явное ручное заполнение параметра, если имена различаются
    ОбластьМакета.Параметры.Студент = СтрСтуденты.ФИО; 
    ТабличныйДокумент.Вывести(ОбластьМакета);
    Ном = Ном + 1;
КонецЦикла;

---

Решение №2. Переход к «плоскому» запросу (Рекомендуемый стандарт)

Использование вложенных таблиц в запросах (когда табличная часть выбирается через точку от шапки документа) считается устаревшей практикой в 1С. Такие запросы сложнее читать, они неоптимально обрабатываются СУБД при больших объемах данных и требуют сложного обхода через выгрузку вложенных выборок. Более правильный и производительный подход — написание плоского запроса непосредственно к табличной части документа.

Проанализируем ситуацию и перепишем логику для ветки ДоговорПоКонтрагенту. Вместо обращения к шапке документа и последующего вытягивания ТЧ через точку, мы обратимся напрямую к таблице Документ.ПриказПоПрактике.РаспределениеПрактикантов:


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

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

---

Решение №3. Использование шаблонов заполнения ячеек

Иногда требуется вывести ФИО студента не в отдельную ячейку таблицы, а встроить его внутрь готового текстового предложения (например: «Студент [СтудентФИО] направляется на практику в...»). В этом случае использование типа заполнения «Параметр» не подойдет, так как он полностью затирает статический текст в ячейке.

Проанализируем, как использовать тип заполнения «Шаблон»:

  1. Выделим ячейку макета, в которой необходимо совместить текст и динамические данные.
  2. В окне свойств (клавиша F4) в поле «Заполнение» выберем значение «Шаблон».
  3. В тексте ячейки напишем статическую строку, а параметр, который должен заменяться на ФИО, поместим в квадратные скобки:
    Студент [ФИОСтудента] направляется на предприятие [НазваниеПредприятия].
  4. В коде печатной формы передача параметров будет выглядеть стандартно:

ОбластьСтрока.Параметры.ФИОСтудента = ВыборкаСтроки.Студент;
ОбластьСтрока.Параметры.НазваниеПредприятия = ВыборкаСтроки.Контрагент;

При выгрузке в табличный документ платформа 1С автоматически распознает квадратные скобки в шаблоне и подставит туда переданные значения переменных.

---

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

← На главную