Как в 1С ограничить количество строк в цикле при подготовке данных для печати чеков?

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

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

Зачем ограничивать количество строк?

Прежде чем переходить к коду, проанализируем ситуацию. Ограничение в 45–50 строк — это не случайная цифра. Большинство современных драйверов ККТ (например, АТОЛ или Штрих-М) имеют внутренние аппаратные лимиты. Если отправить в один чек слишком много позиций, можно столкнуться со следующими проблемами:

Рассмотрим несколько способов реализации такого ограничения непосредственно в коде конфигурации.

Способ 1: Использование вспомогательного счетчика

Это классический метод, который подходит для любого типа коллекции (массив, таблица значений, список значений). Мы вводим дополнительную переменную-счетчик, увеличиваем ее на каждой итерации и проверяем условие выхода.

Разберем по шагам реализацию в функции ПолучитьСписокЛицевыхСчетовДляПечатиЧеков:


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

Важный нюанс: Обратите внимание, что инкремент счетчика лкКол = лкКол + 1 должен находиться внутри блока Если, проверяющего условие отбора. Если вы поставите его вне этого условия, цикл прервется после анализа 45 строк документа вообще, даже если ни одна из них не подошла под критерии печати.

Способ 2: Контроль по количеству элементов в результирующей коллекции

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

Проанализируем этот пример:


Функция ПолучитьСписокЛицевыхСчетовДляПечатиЧеков(СуммыПлатежей)
    СписокЛицевыхСчетов = Новый СписокЗначений;
    
    Для Каждого ТекущаяСтрока Из СуммыПлатежей Цикл
        Если ТекущаяСтрока.НомерЧекаККМ = 0 Тогда
            
            СписокЛицевыхСчетов.Добавить(ТекущаяСтрока.Объект);
            
            // Проверяем текущий размер списка
            Если СписокЛицевыхСчетов.Количество() = 45 Тогда
                Прервать;
            КонецЕсли;
            
        КонецЕсли;
    КонецЦикла;
    
    Возврат СписокЛицевыхСчетов;
КонецФункции

Этот метод считается более "чистым" с точки зрения кода, так как мы избавляемся от ручного управления переменной лкКол. Однако стоит помнить, что метод Количество() у некоторых тяжелых объектов может работать медленнее, чем обращение к простой числовой переменной (хотя для СписокЗначений разница будет неощутима).

Способ 3: Использование метода НайтиСтроки (оптимизация)

Если СуммыПлатежей — это ТаблицаЗначений, мы можем оптимизировать процесс, предварительно отобрав все подходящие строки, а затем пройдясь только по первым 45 элементам полученного массива.

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


ПараметрыОтбора = Новый Структура("НомерЧекаККМ", 0);
НайденныеСтроки = СуммыПлатежей.НайтиСтроки(ПараметрыОтбора);

// Определяем верхнюю границу цикла (не более 45 и не более всего найденного)
КоличествоИтераций = Мин(НайденныеСтроки.Количество(), 45);

Для Индекс = 0 По КоличествоИтераций - 1 Цикл
    ТекущаяСтрока = НайденныеСтроки[Индекс];
    СписокЛицевыхСчетов.Добавить(ТекущаяСтрока.Объект);
КонецЦикла;

Этот подход позволяет избежать лишних проверок Если ... Тогда внутри основного цикла, что делает код более линейным и понятным.

Альтернатива: Использование запроса с конструкцией ВЫБРАТЬ ПЕРВЫЕ

Если данных очень много, самым правильным с точки зрения производительности платформы 1С будет использование механизма запросов. Вместо того чтобы выгружать тысячи строк в память и обходить их циклом, мы можем попросить СУБД вернуть нам только нужную порцию данных.

Разберем пример запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 45
    |   ТЧ.Объект КАК Объект
    |ИЗ
    |   &ТаблицаПлатежей КАК ТЧ
    |ГДЕ
    |   ТЧ.НомерЧекаККМ = 0";

Запрос.УстановитьПараметр("ТаблицаПлатежей", СуммыПлатежей);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    СписокЛицевыхСчетов.Добавить(Выборка.Объект);
КонецЦикла;

Использование конструкции ВЫБРАТЬ ПЕРВЫЕ 45 гарантирует, что система не будет тратить ресурсы на обработку лишних записей. Это особенно актуально, если таблица СуммыПлатежей содержит данные из крупного документа (например, реестра платежей на тысячи строк).

Важные рекомендации по пакетной обработке

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

Чтобы избежать потери данных, рекомендуется реализовать пакетную логику:

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

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

← На главную