Как определить последнюю строку в таблице при выводе данных в макет 1С?

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

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

Способ 1. Использование счетчика и метода Количество()

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

Посмотрим на пример кода с использованием тернарного оператора ?():


Таблица = ДополнительныеОтпуска(Выборка.ДолжностьСсылка);
ВсегоСтрок = Таблица.Количество();
НомерСтроки = 0;

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

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

Способ 2. Обход таблицы значений по числовому индексу

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


ВсегоСтрок = Таблица.Количество();

Для Индекс = 0 По ВсегоСтрок - 1 Цикл
    Строка = Таблица[Индекс];
    
    ОбластьДополнительныйОтпуск.Параметры.СтрокаДополнительныйОтпуск = 
        Строка.НаименованиеДопОтпуска + " в количестве " + Строка.КоличествоДней + 
        " календарных дней - согласно действующему коллективному договору";
    
    ОбластьДополнительныйОтпуск.Параметры.ЗнакПослеСтроки = ?(Индекс = ВсегоСтрок - 1, ".", ";");
    
    ТабДокумент.Вывести(ОбластьДополнительныйОтпуск);
КонецЦикла;

Способ 3. Проверка индекса через метод Индекс()

Если мы предпочитаем обход через Для каждого, но не хотим вручную инициализировать и увеличивать отдельную переменную НомерСтроки, можно воспользоваться методом коллекции Индекс():


ПоследнийИндекс = Таблица.Количество() - 1;

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

Способ 4. Вывод данных напрямую из выборки запроса

Выгрузка результата запроса в память через метод Выгрузить() не всегда оправдана, так как создает дополнительную таблицу в оперативной памяти. Если данные нужны только для последовательного вывода в отчет, эффективнее использовать объект ВыборкаИзРезультатаЗапроса. У выборки также доступен метод Количество():


Выборка = Запрос.Выполнить().Выбрать();
ВсегоЗаписей = Выборка.Количество();
Счетчик = 0;

Пока Выборка.Следующий() Цикл
    Счетчик = Счетчик + 1;
    
    ОбластьДополнительныйОтпуск.Параметры.СтрокаДополнительныйОтпуск = 
        Выборка.НаименованиеДопОтпуска + " в количестве " + Выборка.КоличествоДней + 
        " календарных дней - согласно действующему коллективному договору";
    
    ОбластьДополнительныйОтпуск.Параметры.ЗнакПослеСтроки = ?(Счетчик = ВсегоЗаписей, ".", ";");
    
    ТабДокумент.Вывести(ОбластьДополнительныйОтпуск);
КонецЦикла;

Оптимизация исходного запроса

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЕжегодныеОтпуска.ВидЕжегодногоОтпуска.Наименование КАК НаименованиеДопОтпуска,
    |	ЕжегодныеОтпуска.КоличествоДнейОтпускаВГод КАК КоличествоДней
    |ИЗ
    |	Справочник.ДолжностиОрганизаций.ЕжегодныеОтпуска КАК ЕжегодныеОтпуска
    |ГДЕ
    |	ЕжегодныеОтпуска.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", Должность);

Правильное склонение единиц измерения

При формировании текстовых представлений вроде «в количестве N календарных дней» часто требуется согласовать числительное со словом (день, дня, дней). Для этого есть два надежных пути.

Вариант 1. Использование встроенной функции ЧислоПрописью()

Платформа 1С содержит встроенный механизм склонения предметов исчисления:


ФорматДней = "календарный день, календарных дня, календарных дней, м,,,,0";
СловоДней = СокрЛП(ЧислоПрописью(Строка.КоличествоДней, "НД=Ложь", ФорматДней));

// Результат: "5" + " " + "календарных дней"
СтрокаОтпуска = Строка.НаименованиеДопОтпуска + " в количестве " + 
    Строка(Строка.КоличествоДней) + " " + СловоДней;

Вариант 2. Программный алгоритм анализа остатка от деления

Если требуется собственная универсальная функция, логику склонения можно реализовать через остаток от деления на 10 и 100:


Функция ПолучитьПодписьДней(ЧислоДней)
    Остаток100 = ЧислоДней % 100;
    Остаток10 = ЧислоДней % 10;
    
    Если Остаток100 >= 11 И Остаток100 <= 14 Тогда
        Возврат "календарных дней";
    ИначеЕсли Остаток10 = 1 Тогда
        Возврат "календарный день";
    ИначеЕсли Остаток10 >= 2 И Остаток10 <= 4 Тогда
        Возврат "календарных дня";
    Иначе
        Возврат "календарных дней";
    КонецЕсли;
КонецФункции

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

← На главную