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