В процессе разработки в системе 1С:Предприятие 8 часто возникает задача автоматизации бизнес-логики, зависящей от наполненности документа. Типичный пример: если в заказе более 20 позиций, необходимо автоматически установить признак выдачи скидочного купона. Начинающие разработчики часто сталкиваются с ошибками при попытке получить итоговое количество строк. В этой статье мы подробно разберем, почему возникает ошибка «Колонка не принадлежит коллекции», как ее исправить и как сделать ваш код профессиональным.
Рассмотрим ситуацию, с которой столкнулся автор темы. В обработчике события ПередЗаписью модуля объекта документа была предпринята попытка получить количество строк следующим образом:
ВсегоПозиций = Позиции.Итог("КоличествоСтрок");
При выполнении этого кода система выдает ошибку: «Недопустимое значение параметра (параметр номер '1') (Колонка не принадлежит коллекции)». Давайте проанализируем ситуацию и выясним причину. Метод Итог() предназначен для суммирования значений числовых колонок, которые физически существуют в табличной части (например, «Сумма», «Количество», «Вес»).
Важно понимать: в 1С табличная часть не содержит скрытой колонки с именем КоличествоСтрок. Несмотря на то что в интерфейсе мы видим номера строк, они являются динамическими индексами коллекции, а не данными в колонке. Поэтому попытка вызвать Итог по несуществующему имени поля закономерно приводит к аварийному завершению работы программы.
Для того чтобы узнать, сколько всего записей содержится в табличной части, нам не нужно ничего суммировать. Коллекция строк табличной части имеет встроенный метод, который возвращает число элементов. Разберем правильный синтаксис:
// Вместо метода Итог используем Количество()
ВсегоПозиций = Позиции.Количество();
Метод Количество() работает мгновенно, так как он просто возвращает размер массива строк в памяти. Это самый эффективный способ решения задачи. Теперь посмотрим, как интегрировать это в обработчик события документа.
Проанализируем программный код, который решает поставленную задачу. Нам нужно проверить количество строк и, если оно превышает 20, установить значение реквизита СкидочныйКупон в значение Истина.
Рассмотрим по шагам обновленную процедуру ПередЗаписью:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// 1. Получаем итоги по существующим числовым колонкам
ИтоговаяСумма = Позиции.Итог("Сумма");
ИтоговыйВес = Позиции.Итог("Вес");
// 2. Получаем общее количество строк в таблице
ВсегоПозиций = Позиции.Количество();
// 3. Проверяем условие и устанавливаем флаг
Если ВсегоПозиций > 20 Тогда
СкидочныйКупон = Истина;
Иначе
СкидочныйКупон = Ложь;
КонецЕсли;
КонецПроцедуры
Обратите внимание, что мы разделили получение сумм по колонкам и получение общего количества строк. Это делает код понятным и исключает ошибки исполнения.
Профессиональные разработчики часто используют более лаконичные конструкции для установки булевых (логических) значений. Вместо громоздкого блока Если ... Тогда ... Иначе, мы можем присвоить результат сравнения напрямую реквизиту. Проанализируем пример:
// Оптимизированный вариант
СкидочныйКупон = (Позиции.Количество() > 20);
Такая запись эквивалентна предыдущей, но занимает всего одну строку и легче читается. Переменная СкидочныйКупон получит значение Истина, если выражение в скобках верно, и Ложь в противном случае.
Выясним важный нюанс, который часто упускают при разработке акций. Что если пользователь добавил одну и ту же номенклатуру в разные строки? Например, 21 строку с одним и тем же товаром (возможно, с разными характеристиками или просто по ошибке).
Чтобы посчитать количество уникальных позиций, нам потребуется предварительно выгрузить колонку в таблицу значений и свернуть ее. Рассмотрим этот алгоритм:
// Копируем колонку Номенклатура в отдельную таблицу
ТаблицаТоваров = Позиции.Выгрузить( , "Номенклатура");
// Схлопываем дублирующиеся строки
ТаблицаТоваров.Свернуть("Номенклатура");
// Теперь считаем уникальные записи
КоличествоУникальных = ТаблицаТоваров.Количество();
Для того чтобы ваше решение было гибким и соответствовало стандартам разработки (например, БСП), проанализируем следующие рекомендации:
1. Избавление от "магических чисел" (Хардкода)
Сегодня условие — 20 позиций, а завтра руководство может изменить его на 25. Если число 20 прописано прямо в коде, вам придется каждый раз менять конфигурацию и обновлять базу у пользователей. Рекомендуется вынести этот параметр в Константы или в специальный Регистр сведений с настройками маркетинговых акций.
2. Место выполнения кода
Проверка в ПередЗаписью хороша для гарантии данных в базе. Однако пользователь увидит результат только после сохранения документа. Для улучшения UX (пользовательского опыта) желательно продублировать эту логику в модуле формы в событии ПриИзменении табличной части. Таким образом, флаг СкидочныйКупон будет устанавливаться мгновенно на глазах у менеджера.
3. Учет режима загрузки данных
Если документ загружается из внешней системы (через обмен или из Excel), расчеты в ПередЗаписью могут помешать. Хорошим тоном считается добавление проверки свойства ОбменДанными.Загрузка:
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Мы проанализировали типичную ошибку начинающего программиста 1С и нашли верный способ подсчета строк в табличной части. Вместо использования Итог() для виртуальных полей, всегда применяйте метод Количество(). Помните о разнице между общим числом строк и уникальными позициями, а также старайтесь избегать жесткого кодирования числовых параметров в тексте процедур. Использование этих простых правил сделает вашу разработку более надежной и профессиональной.