Как правильно проверить наличие выбранных строк в таблице 1С:Управление торговлей 11?

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

При сопровождении и доработке типовых конфигураций, таких как 1С:Управление торговлей 11, разработчики часто сталкиваются с устаревшим или избыточным кодом проверки табличных частей. Попытка упростить такой код без глубокого анализа исходного алгоритма может привести к ошибкам выполнения и нарушению бизнес-логики программы. Рассмотрим типовой пример подобной проверки, проанализируем допущенные ошибки и разберем варианты оптимального решения задачи.

Анализ исходного кода и предложенной замены

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


ТабТовары = ТаблицаТоваров.Выгрузить;
Для Каждого Стр Из ТабТовары Цикл
    Стр.НомерСтроки = Индекс + 1;
    Если Стр.Выбран Тогда
        ЕстьТовары = Истина;
    КонецЕсли;
КонецЦикла;
Если Не ЕстьТовары Тогда
    Возврат Ложь;
КонецЕсли;

Разработчик предложил заменить эту конструкцию на следующую проверку:


Если ТаблицаТоваров.Количество = 0 Тогда
    Возврат;
КонецЕсли;

Выясним причину, почему такая замена категорически недопустима:

  1. Подмена логики проверки: Исходный алгоритм проверяет не просто наличие строк в таблице, а присутствие хотя бы одной строки с установленным флажком Выбран. В предложенном варианте проверяется только общее число записей. Если в таблице есть 10 товаров, но ни у одного не стоит отметка, предложенная замена пропустит выполнение дальше, тогда как оригинал вернет отказ.
  2. Нарушение сигнатуры функции: Исходный алгоритм вызывается внутри функции и явно возвращает булево значение Ложь. Предложенная строка содержит оператор Возврат; без значения, что в контексте функции вызовет синтаксическую ошибку времени компиляции либо нарушит обработку результата вызывающим кодом.
  3. Синтаксические ошибки обращения: В обоих вариантах обращения к методам Количество и Выгрузить выполнены без круглых скобок. В платформе 1С это методы, а не свойства. Обращение вида ТаблицаТоваров.Количество приведет к ошибке выполнения: «Поле объекта не обнаружено». Корректный синтаксис требует скобок: ТаблицаТоваров.Количество() и ТаблицаТоваров.Выгрузить().
  4. Проблемы с контекстом формы: В конфигурации 1С:УТ 11 реквизиты таблиц на управляемой форме имеют тип ДанныеФормыКоллекция. У этого типа вообще отсутствует метод Выгрузить(). Если код выполняется на клиенте, вызов такого метода приведет к аварийному завершению.
  5. Бесполезная модификация номера строки: Строка Стр.НомерСтроки = Индекс + 1; содержит обращение к неопределенной переменной Индекс, а также изменяет скопированную таблицу значений ТабТовары, изменения в которой никак не транслируются обратно в исходную таблицу формы без явной команды загрузки.

Вариант 1. Оптимальная проверка на сервере через метод Найти()

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

Посмотрим на пример правильной проверки:


Если ТаблицаТоваров.Найти(Истина, "Выбран") = Неопределено Тогда
    Возврат Ложь;
КонецЕсли;

Разберем преимущества этого подхода:

  1. Метод прекращает сканирование сразу же при обнаружении первой строки, удовлетворяющей условию Выбран = Истина.
  2. Не создается дубликат таблицы в оперативной памяти, что исключает лишнюю нагрузку при работе с большими документами.
  3. Код становится компактным, легко читаемым и надежным.

Вариант 2. Проверка на клиенте через НайтиСтроки() для данных формы

В управляемых формах 1С:Управление торговлей 11 табличная часть на клиенте представлена объектом ДанныеФормыКоллекция. У данного объекта нет метода Найти(), но доступен платформенный метод НайтиСтроки(), принимающий структуру отбора.

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


ПараметрыОтбора = Новый Структура("Выбран", Истина);
НайденныеСтроки = ТаблицаТоваров.НайтиСтроки(ПараметрыОтбора);

Если НайденныеСтроки.Количество() = 0 Тогда
    Возврат Ложь;
КонецЕсли;

Такой вызов возвращает массив ссылок на строки, удовлетворяющие критерию, не требуя выгрузки в промежуточные таблицы значений.

Вариант 3. Линейный обход с оператором Прервать

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

Разберем по шагам корректный цикл проверки:


ЕстьВыбранныеТовары = Ложь;

Для Каждого СтрТовар Из ТаблицаТоваров Цикл
    Если СтрТовар.Выбран Тогда
        ЕстьВыбранныеТовары = Истина;
        Прервать; // Прекращаем перебор сразу после нахождения первого совпадения
    КонецЕсли;
КонецЦикла;

Если Не ЕстьВыбранныеТовары Тогда
    Возврат Ложь;
КонецЕсли;

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

← На главную