Как исправить ошибку «Переменная не определена (Сотрудник)» в 1С при переносе реквизита в табличную часть

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

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

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

Выясняем причину: почему возникает ошибка «Переменная не определена»?

Давайте проанализируем поведение платформы 1С. Когда реквизит Сотрудник находился в шапке документа, он был доступен напрямую в модуле формы как глобальное свойство объекта. Программа всегда «знала», какой конкретно сотрудник выбран в документе, и могла без проблем передать его в параметры макета или использовать в заголовке окна.

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

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

Разбор ошибок в исходном коде

Рассмотрим фрагмент проблемного кода, который привел к ошибке в конфигураторе:


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

Проанализируем две ключевые строки, на которых спотыкается компилятор 1С:

Строка с Ошибкой №1: Макет.Параметры = Сотрудник;

Здесь допущена двойная критическая ошибка. Во-первых, свойство Параметры у табличного макета (или его области) представляет собой коллекцию (структуру параметров), доступную только для чтения. Ей физически нельзя присвоить значение напрямую через оператор =. Правильное заполнение параметров всегда происходит точечно, например: Макет.Параметры.ИмяПараметра = Значение;. Во-вторых, сама переменная Сотрудник неопределена, так как система больше не видит ее в контексте документа.

Строка с Ошибкой №2: ТабДок.Показать("Трудовой договор по сотруднику" + Сотрудник);

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

Пошаговый алгоритм решения проблемы

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

Готовое программное решение

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


Процедура ОсновныеДействияФормыКнопкаПечати(Кнопка)
    
    // Создаем результирующий табличный документ
    ТабДок = Новый ТабличныйДокумент;
    
    // Получаем макет печатной формы
    Макет = ПолучитьМакет("Макет");
    
    // 1. Формируем и выводим область Шапки
    ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
    ОбластьШапка.Параметры.НомерДоговора = Номер; // Значение берется из реквизита шапки документа
    ОбластьШапка.Параметры.ДатаДоговора  = Дата;
    ОбластьШапка.Параметры.Дата          = Дата;
    ТабДок.Вывести(ОбластьШапка);
    
    // 2. Получаем область строки для циклического вывода сотрудников
    ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
    
    // Обходим табличную часть документа в цикле
    Для Каждого ТекСтрока Из Работники Цикл
        
        // Заполняем параметр конкретной строки макета данными текущей строки табличной части
        ОбластьСтрока.Параметры.Сотрудник = ТекСтрока.Сотрудник;
        
        // Выводим заполненную строку в итоговый табличный документ
        ТабДок.Вывести(ОбластьСтрока);
        
    КонецЦикла;
    
    // 3. Формируем текст для заголовка окна просмотра
    // Поскольку сотрудников может быть много, для заголовка возьмем первого сотрудника из списка
    ИмяСотрудникаДляОкна = "";
    Если Работники.Количество() > 0 Тогда
        ИмяСотрудникаДляОкна = " " + СокрЛП(Работники[0].Сотрудник);
    КонецЕсли;
    
    // Отображаем готовый печатный лист пользователю
    ТабДок.Показать("Трудовой договор по сотруднику" + ИмяСотрудникаДляОкна);
    
КонецПроцедуры

Полезный лайфхак: Оптимизация с помощью метода Заполнить()

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

Посмотрим на пример оптимизированного цикла:


Для Каждого ТекСтрока Из Работники Цикл
    // Метод автоматически сопоставит имена параметров макета и колонок ТЧ и заполнит их
    ОбластьСтрока.Параметры.Заполнить(ТекСтрока);
    ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;

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

Рекомендация по современным стандартам разработки в 1С

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

Если в дальнейшем вы будете переводить вашу конфигурацию на Управляемые формы (УФ), помните о важном правиле разделения контекста:

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

← На главную