Как найти строку в таблице значений в 1С 8 и получить ее номер: аналоги методов из 1С 7.7

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

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

В чем принципиальная разница между 1С 7.7 и 1С 8 при поиске строк

В платформе 1С 7.7 поиск выглядел следующим образом: метод модифицировал переменную с номером строки, после чего разработчик позиционировал таблицу значений на этот номер:


// Пример из 1С 7.7
стр = 0;
ТЗ.НайтиЗначение(МойДоговор, стр, "Договор");
ТЗ.ПолучитьСтрокуПоНомеру(стр);
Контрагент = ТЗ.Контрагент;

В платформе 1С 8 от концепции «текущей строки» и обязательной адресации по номерам при поиске отказались. Таблица значений представляет собой коллекцию строк типа СтрокаТаблицыЗначений. Методы поиска возвращают сразу ссылку на нужный элемент коллекции или коллекцию найденных строк. Выясним причину: работа напрямую с объектом строки избавляет от необходимости повторно позиционироваться в таблице и существенно упрощает чтение кода.

Способ 1. Одиночный поиск через метод Найти()

Прямым функциональным аналогом поиска первого вхождения является метод таблицы значений Найти(). Рассмотрим его особенности:

  1. Метод принимает искомое значение и необязательный список имен колонок для поиска через запятую. Если колонки не указаны, поиск выполняется по всей таблице.
  2. Метод возвращает либо первую найденную СтрокаТаблицыЗначений, либо значение Неопределено, если совпадений не обнаружено.
  3. Поскольку возвращается сразу строка, к ее колонкам можно обращаться через точку без предварительного позиционирования.

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


НайденнаяСтрока = ТЗ.Найти(МойДоговор, "Договор");

Если НайденнаяСтрока <> Неопределено Тогда
    Контрагент = НайденнаяСтрока.Контрагент;
Иначе
    // Обработка ситуации, когда значение не найдено
КонецЕсли;

Способ 2. Множественный поиск через метод НайтиСтроки()

Если требуется найти не одно, а сразу все совпадения, либо поиск должен выполняться по сложному условию (сочетанию нескольких колонок), применяют метод НайтиСтроки(). Проанализируем различия:

  1. Параметром метода выступает объект Структура, где ключи соответствуют именам колонок таблицы, а значения — искомым значениям.
  2. Метод всегда возвращает объект Массив. Если совпадений нет, массив будет пустым (в отличие от метода Найти(), возвращающего Неопределено).
  3. Метод НайтиСтроки() умеет использовать встроенные индексы таблицы значений, что критично для производительности на больших объемах данных.

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


Отбор = Новый Структура;
Отбор.Вставить("Договор", МойДоговор);

МассивНайденныхСтрок = ТЗ.НайтиСтроки(Отбор);

Если МассивНайденныхСтрок.Количество() > 0 Тогда
    ПерваяСтрока = МассивНайденныхСтрок[0];
    Контрагент = ПерваяСтрока.Контрагент;
КонецЕсли;

Как получить номер или индекс найденной строки

В процессе разработки часто возникает вопрос: что делать, если алгоритму действительно необходима позиция строки в коллекции? Здесь важно не путать объект ТаблицаЗначений и табличную часть прикладного объекта (документа или справочника).

  1. У строки табличной части документа или справочника есть встроенное системное свойство НомерСтроки (нумерация начинается с 1).
  2. У объекта СтрокаТаблицыЗначений свойства НомерСтроки нет. Нумерация элементов в таблице значений базируется на понятии индекса, который всегда начинается с 0.

Чтобы получить позицию строки в таблице значений, следует вызвать метод Индекс() самой таблицы, передав в него полученную строку:


НайденнаяСтрока = ТЗ.Найти(МойДоговор, "Договор");

Если НайденнаяСтрока <> Неопределено Тогда
    // Получаем индекс строки (от 0 до ТЗ.Количество() - 1)
    ИндексСтроки = ТЗ.Индекс(НайденнаяСтрока);
    
    // Если требуется номер для вывода пользователю (начиная с 1):
    НомерПоПорядку = ИндексСтроки + 1;
КонецЕсли;

Как скопировать в другую таблицу строки с первой по найденную

Рассмотрим прикладную задачу, возникшую в обсуждении: как выгрузить во вторую таблицу диапазон строк от начала таблицы (индекс 0) до позиции найденной строки включительно. В платформе 1С 8 для этого не требуется вручную создавать колонки и переносить каждую ячейку в цикле. Достаточно использовать метод Скопировать() с передачей массива нужных строк.

Разберем по шагам реализацию этой задачи:


НайденнаяСтрока = ТЗ.Найти(МойДоговор, "Договор");

Если НайденнаяСтрока <> Неопределено Тогда
    ИндексКонца = ТЗ.Индекс(НайденнаяСтрока);
    
    // Формируем массив строк нужного диапазона
    МассивДляКопирования = Новый Массив;
    Для Индекс = 0 По ИндексКонца Цикл
        МассивДляКопирования.Добавить(ТЗ[Индекс]);
    КонецЦикла;
    
    // Создаем новую таблицу с идентичной структурой и нужными строками
    ВтораяТЗ = ТЗ.Скопировать(МассивДляКопирования);
КонецЕсли;

Оптимизация: когда использовать индексы таблицы значений

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


// Добавляем индекс по часто запрашиваемой колонке
ТЗ.Индексы.Добавить("Договор");

// Теперь поиск через НайтиСтроки будет выполняться значительно быстрее
Отбор = Новый Структура("Договор", МойДоговор);
Результат = ТЗ.НайтиСтроки(Отбор);

Важные нюансы работы с индексами:

  1. Метод Найти() не использует индексы коллекции Индексы — ускорение работает только для метода НайтиСтроки().
  2. Любое изменение структуры таблицы значений (добавление или удаление колонок через коллекцию Колонки) сбрасывает все созданные индексы.
  3. При копировании таблицы методом Скопировать() индексы в новую таблицу не переносятся, их необходимо настраивать заново.

Ограничения контекста исполнения

Необходимо помнить, что тип ТаблицаЗначений является серверным объектом. Он доступен на стороне сервера, в толстом клиенте и во внешнем соединении, но отсутствует в тонком и веб-клиенте управляемого приложения. При работе на клиенте данные таблиц обычно хранятся в объекте ДанныеФормыКоллекция, у которого нет методов Найти() или Скопировать(). Поэтому любые сложные манипуляции со строками, выборками и индексами следует выносить в серверные процедуры и функции модуля формы или общих модулей.

← На главную