К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как получить значение из таблицы значений в 1С

Способы получить значение из таблицы значений 1С: поиск строк, обращение по индексу, методы Найти, НайтиСтроки, итоги по колонкам. Примеры кода и типичные ошибки.

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

У объекта «ТаблицаЗначений» есть несколько принципиально разных способов доступа к данным: прямое обращение по индексу строки, поиск методами Найти() и НайтиСтроки(), перебор в цикле, а также свёртка и итоги. Выбор способа влияет и на читаемость кода, и на скорость: неправильный метод на большой таблице может замедлить обработку в десятки раз.

Ниже разобраны рабочие приёмы с примерами кода, типичными ошибками и рекомендациями по выбору метода под конкретную задачу.

Обращение к строке по индексу и чтение ячейки

Каждая строка таблицы значений доступна по числовому индексу, начиная с нуля. Общий синтаксис: ТЗ[Индекс].ИмяКолонки. Например, чтобы прочитать значение колонки «Сумма» из первой строки:

ЗначениеЯчейки = ТаблицаТоваров[0].Сумма;

Имя колонки можно также передать строкой через квадратные скобки — это удобно, когда имя колонки заранее неизвестно и хранится в переменной:

ИмяКолонки = "Сумма";

ЗначениеЯчейки = ТаблицаТоваров[0][ИмяКолонки];

Главный риск прямого обращения — выход за границы таблицы. Если таблица пустая или индекс больше, чем Количество() - 1, платформа выдаст ошибку «Индекс находится за границами массива». Поэтому перед обращением по индексу проверяйте размер таблицы:

Если ТаблицаТоваров.Количество() > 0 Тогда

ПерваяСумма = ТаблицаТоваров[0].Сумма;

КонецЕсли;

Поиск строки методом Найти()

Метод Найти(Значение, ИмяКолонки) возвращает первую строку, где указанная колонка равна искомому значению. Если совпадений нет — возвращает Неопределено. Это самый частый способ получить конкретное значение по ключу:

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

Если СтрокаТовара <> Неопределено Тогда

Цена = СтрокаТовара.Цена;

Иначе

Сообщить("Товар не найден в таблице");

КонецЕсли;

Обязательно проверяйте результат на Неопределено до обращения к колонкам найденной строки. Обращение Неопределено.Цена — одна из самых распространённых ошибок при работе с таблицами значений.

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

Отбор нескольких строк через НайтиСтроки()

Когда нужно получить все строки, удовлетворяющие одному или нескольким условиям, применяется метод НайтиСтроки(ПараметрыОтбора). Условия передаются структурой, где ключ — имя колонки, а значение — искомое значение. Метод возвращает массив строк (возможно, пустой):

Отбор = Новый Структура;

Отбор.Вставить("Склад", ОсновнойСклад);

Отбор.Вставить("Активна", Истина);

НайденныеСтроки = ТаблицаТоваров.НайтиСтроки(Отбор);

Для Каждого Строка Из НайденныеСтроки Цикл

ОбщееКоличество = ОбщееКоличество + Строка.Количество;

КонецЦикла;

Все условия в структуре объединяются по «И»: строка попадёт в результат, только если совпадут значения всех перечисленных колонок. Отбор по условию «ИЛИ» или по сравнению «больше/меньше» через НайтиСтроки() не делается — такие задачи решаются циклом с проверкой или запросом.

Перебор строк в цикле и получение значений по условию

Универсальный способ — обход таблицы в цикле Для Каждого. Внутри цикла доступны все колонки текущей строки, и можно реализовать любую логику: сложные условия, накопление значений, поиск максимума:

МаксимальнаяСумма = 0;

СтрокаМаксимума = Неопределено;

Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл

Если СтрокаТовара.Сумма > МаксимальнаяСумма Тогда

МаксимальнаяСумма = СтрокаТовара.Сумма;

СтрокаМаксимума = СтрокаТовара;

КонецЕсли;

КонецЦикла;

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

Если строки нужны по индексу (например, обработка парами или с конца), подойдёт классический цикл со счётчиком: Для Индекс = 0 По ТЗ.Количество() - 1 Цикл. Обратный обход удобен при удалении строк внутри цикла — удаление при прямом обходе сдвигает индексы и приводит к пропуску строк.

bsl
Для Индекс = -ТЗ.Количество() + 1 По 0 Цикл
    Строка = ТЗ[-Индекс];
    Если Строка.Пометка Тогда
        ТЗ.Удалить(Строка);
    КонецЕсли;
КонецЦикла;

Итоги, свёртка и выгрузка колонки

Если нужна не строка, а агрегированное значение по колонке, перебор не обязателен. Метод Итог("Сумма") возвращает сумму по числовой колонке всей таблицы:

ОбщаяСумма = ТаблицаТоваров.Итог("Сумма");

Метод Свернуть("Номенклатура", "Количество,Сумма") группирует строки по указанным колонкам и суммирует числовые поля — это аналог группировки в запросе, выполненный в памяти. Учтите, что свёртка изменяет саму таблицу; если исходные строки ещё нужны, сначала сделайте копию методом Скопировать().

Для получения всех значений одной колонки в виде массива используйте ВыгрузитьКолонку("Номенклатура"). Обратная операция — ЗагрузитьКолонку(Массив, "Номенклатура") — записывает массив значений в колонку.

Сравнение способов получения значения

ТЗ[Индекс].Колонка

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

Найти()

Поиск первой строки по одному условию. Возвращает Неопределено, если не найдено — нужна проверка.

НайтиСтроки()

Отбор по нескольким условиям «И». Возвращает массив строк, не подходит для условий «ИЛИ» и сравнений.

Цикл Для Каждого

Любая логика и сложные условия. Медленнее встроенных методов на больших таблицах.

Итог() / Свернуть()

Агрегированные значения без цикла. Свернуть изменяет саму таблицу.

Производительность и большие таблицы

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

Для ускорения повторного поиска создайте индекс по колонке: ТЗ.Индексы.Добавить("Номенклатура"). После этого Найти() и НайтиСтроки() по этой колонке будут работать значительно быстрее. Индекс имеет смысл добавлять, когда поиск выполняется многократно — на одиночный поиск затраты на построение индекса могут не окупиться.

Альтернатива для тяжёлых выборок — получить данные запросом сразу с нужным отбором и группировкой, а не фильтровать таблицу значений в памяти. Запрос на сервере СУБД почти всегда быстрее программного перебора.

Типичные ошибки
01
Обращение к колонкам результата Найти() без проверки на Неопределено — ошибка выполнения при отсутствии строки.
02
Проверка результата НайтиСтроки() на Неопределено вместо проверки Количество() > 0 — метод возвращает пустой массив, а не Неопределено.
03
Сравнение ссылок с строковыми представлениями в Найти() — типы не совпадают, строка не находится.
04
Удаление строк при прямом обходе циклом со счётчиком — сдвиг индексов и пропуск строк.
05
Свертка исходной таблицы без копии — потеря детальных строк, которые нужны дальше по алгоритму.

Проверка результата и отладка

После получения значения полезно убедиться, что оно корректно: тип соответствует ожиданиям, значение заполнено. Для проверки типа используйте ТипЗнч(Значение), для проверки заполненности — ЗначениеЗаполнено(Значение).

При отладке содержимое всей таблицы удобно смотреть в конфигураторе через «Вычислить выражение» — таблица значений отображается в виде сетки. Программно структуру таблицы можно проверить через коллекцию ТЗ.Колонки: цикл по ней покажет имена и типы всех колонок, что помогает понять, почему обращение к колонке завершилось ошибкой «Поле не найдено».

Контрольные точки

Как проверить результат

Результат Найти()
Норма

Возвращена строка, значения колонок читаются

Тревожный признак

Неопределено — строка не найдена, проверьте тип и значение отбора

Результат НайтиСтроки()
Норма

Массив, Количество() > 0

Тревожный признак

Пустой массив — условия отбора не совпали ни с одной строкой

Обращение по индексу
Норма

Индекс от 0 до Количество()-1

Тревожный признак

Ошибка «Индекс за границами» — таблица пуста или индекс неверен

Значение ячейки
Норма

Ожидаемый тип через ТипЗнч()

Тревожный признак

Неопределено или NULL — колонка не заполнена в источнике

Частые вопросы

Как получить значение из таблицы значений, если имя колонки хранится в переменной?

Используйте обращение через квадратные скобки: СтрокаТЗ[ИмяКолонки], где ИмяКолонки — строковая переменная. Тот же приём работает и для строки, полученной по индексу: ТЗ[0][ИмяКолонки].

Чем Найти() отличается от НайтиСтроки()?

Найти() возвращает одну первую подходящую строку или Неопределено и умеет искать только по одной колонке. НайтиСтроки() принимает структуру с несколькими условиями и возвращает массив всех подходящих строк, при отсутствии совпадений — пустой массив.

Как найти строку по условию «больше» или «содержит»?

Встроенные методы поиска работают только на точное равенство. Для сравнений и частичного совпадения переберите таблицу циклом с оператором Если, либо получите данные запросом с соответствующим условием ГДЕ — второй вариант предпочтительнее на больших объёмах.

Почему Найти() не находит строку, хотя значение в таблице есть?

Чаще всего не совпадают типы: в колонке ссылка, а ищут строку, или число сравнивается со строкой. Также проверьте лишние пробелы и регистр в строковых значениях — сравнение выполняется точно.

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

Табличная часть поддерживает те же методы, что и таблица значений: Найти(), НайтиСтроки(), Итог(), обращение по индексу. Например: ДокОбъект.Товары.Найти(Номенклатура, "Номенклатура"). Дополнительно доступен поиск по номеру строки через НайтиПоНомеру().

Как быстро получить сумму по колонке без цикла?

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

Итог

Что важно запомнить

Для известной позиции используйте обращение по индексу с проверкой границ, для поиска по значению — Найти() с проверкой на Неопределено, для отбора по нескольким условиям — НайтиСтроки() со структурой. Итоги считайте методом Итог() без цикла, а при многократном поиске по большой таблице добавляйте индекс или переносите отбор в запрос.