Почему не выполняется цикл по массиву строк в таблице значений 1С?

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

При разработке сложных алгоритмов обработки данных в 1С:Предприятии программисты часто сталкиваются с ситуацией, когда код кажется логически верным, но при выполнении программа "проскакивает" цикл. В этой статье мы подробно разберем, почему массив, полученный методом НайтиСтроки, может оказаться пустым, проанализируем влияние длины строк на поиск и выясним, как правильно работать с деревьями значений на управляемых формах (на примере конфигурации БГУ 2.0).

Разбор ситуации: анализ исходного кода

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


Запрос2 = Запрос.Скопировать();
Запрос2.Свернуть("Контрагент, лицензия, Код, Договор","Сумма");
Запрос3 = Запрос2.Скопировать();                    
Запрос3.Свернуть("Код","Сумма");

Для каждого стр из Запрос3 цикл
    НовСтр = _РеестрДокПОбНЛ.Добавить();
    НовСтр.УИД = (Новый УникальныйИдентификатор);
    НовСтр.КодОпер = стр.Код; // Здесь кроется потенциальная проблема
    НовСтр.СумНеоблОпер = стр.Сумма;
    
    // Пытаемся найти строки по коду
    Запрос4 = Запрос2.НайтиСтроки(Новый Структура("Код", НовСтр.КодОпер));
    
    Для Каждого Стр2 Из Запрос4 Цикл 
        // В этом месте цикл часто не отрабатывает
        Сообщить(Стр2);    
        // ... дальнейшая логика заполнения дерева значений
    КонецЦикла;
КонецЦикла;

Проанализируем ситуацию: первый цикл по Запрос3 отрабатывает корректно, однако второй цикл по коллекции Запрос4 полностью игнорируется. Это происходит потому, что метод НайтиСтроки возвращает пустой массив строк. Выясним причину этого поведения.

Причина №1: Несоответствие длины строк и обрезка данных

Самая коварная ошибка в 1С — это неявное ограничение длины строки в реквизитах таблиц значений. Если колонка таблицы КодОпер (в которую мы записываем значение) имеет тип Строка(7), а исходный стр.Код имеет длину 8 символов (например, "12345678"), произойдет следующее:

  1. При присваивании НовСтр.КодОпер = стр.Код; значение "12345678" превратится в "1234567".
  2. Платформа молча отсекает восьмой символ, не выдавая ошибок.
  3. При выполнении Запрос2.НайтиСтроки(Новый Структура("Код", "1234567")) система ищет точное совпадение в таблице Запрос2, где коды остались полными ("12345678").
  4. Результат поиска будет пустым, так как "1234567" не равно "12345678".

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

Причина №2: Различие типов данных

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

Проанализируем типы через отладчик:

Если типы различаются, приведите их к одному виду перед поиском, используя функции Строка() или Число().

Оптимизация поиска: использование индексов

Когда мы работаем с большими объемами данных (например, формирование отчетности по НДС в БГУ 2.0), вложенные циклы с использованием НайтиСтроки могут значительно замедлить работу системы. Чтобы поиск выполнялся мгновенно, необходимо использовать индексацию.

Разберем, как добавить индекс для таблицы значений:


// Перед началом циклов добавим индексы для ускорения поиска
Запрос2.Индексы.Добавить("Код");
Запрос.Индексы.Добавить("Контрагент, Лицензия");

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

Работа с иерархическими структурами на форме (Дерево значений)

В тексте автора упоминается объект _ПредТипДог, который является деревом значений на управляемой форме. Часто новички сталкиваются с тем, что данные в коде заполняются, но на форме "ничего нет". Рассмотрим правильный алгоритм добавления строк в дерево:


// Сначала добавляем строку верхнего уровня
Стр_СведКАгент = _ПредТипДог.ПолучитьЭлементы().Добавить();
Стр_СведКАгент.НаимОрг = Стр2.Контрагент;
Стр_СведКАгент.ИННЮЛ = Стр2.Контрагент.ИНН;

// Добавляем подчиненную строку (второй уровень иерархии)
Запрос5 = Запрос.НайтиСтроки(Новый Структура("Контрагент, Лицензия", Стр2.Контрагент, Стр2.Лицензия));

Для Каждого Стр3 Из Запрос5 Цикл
    // Обратите внимание: элементы добавляются ВНУТРЬ родительской строки
    Стр_ДокПОбНЛ = Стр_СведКАгент.ПолучитьЭлементы().Добавить();
    Стр_ДокПОбНЛ.СумОпер = Стр3.Сумма;
    
    // Если нужно добавить третий уровень
    Стр_НижнийУровень = Стр_ДокПОбНЛ.ПолучитьЭлементы().Добавить();
    Стр_НижнийУровень.ТипДок = "Договор";
КонецЦикла;

Если данные все равно не отображаются, убедитесь, что:

  1. Колонки дерева на форме привязаны к соответствующим путям данных.
  2. В элементах формы для таблицы (дерева) не установлены фильтры.
  3. Для отображения иерархии в интерфейсе можно программно вызвать метод развертки: Элементы._ПредТипДог.Развернуть(Стр_СведКАгент.ПолучитьИдентификатор(), Истина);.

Рекомендации по качеству кода (Чистый код в 1С)

Проанализируем именование переменных в примере автора. Использование имен Запрос2, Запрос3 для таблиц значений является грубым нарушением стандартов разработки. Это путает других программистов, так как Запрос в 1С — это отдельный объект для работы с БД.

Рассмотрим, как правильно называть переменные:

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

Резюме: контрольный список для отладки

Если ваш цикл по результату НайтиСтроки не выполняется, проверьте следующее:

  1. Длина колонок: Не обрезается ли строка при записи в таблицу-приемник?
  2. Тип данных: Совпадают ли типы искомого значения и колонки таблицы (Строка/Число/Ссылка)?
  3. Пробелы: Нет ли лишних пробелов в строковых данных (используйте СокрЛП())?
  4. Индексы: Добавлен ли индекс для колонки поиска для ускорения работы?
  5. Структура поиска: Правильно ли указано имя колонки в структуре (учитывайте регистр)?

Использование этих простых правил позволит вам избежать большинства "необъяснимых" ошибок при работе с коллекциями данных в 1С:Предприятии.

← На главную