Разработка и Конфигурация · 10 мин
Как получить значение из таблицы значений в 1С
Способы получить значение из таблицы значений 1С: поиск строк, обращение по индексу, методы Найти, НайтиСтроки, итоги по колонкам. Примеры кода и типичные ошибки.
Таблица значений — один из самых часто используемых объектов встроенного языка 1С. В ней хранятся результаты запросов, данные табличных частей, промежуточные расчёты и выгрузки из файлов. Задача «получить значение из таблицы значений» возникает постоянно: нужно найти строку по условию, прочитать ячейку по индексу, посчитать итог по колонке или перебрать все строки с проверкой условия.
У объекта «ТаблицаЗначений» есть несколько принципиально разных способов доступа к данным: прямое обращение по индексу строки, поиск методами Найти() и НайтиСтроки(), перебор в цикле, а также свёртка и итоги. Выбор способа влияет и на читаемость кода, и на скорость: неправильный метод на большой таблице может замедлить обработку в десятки раз.
Ниже разобраны рабочие приёмы с примерами кода, типичными ошибками и рекомендациями по выбору метода под конкретную задачу.
Обращение к строке по индексу и чтение ячейки
Каждая строка таблицы значений доступна по числовому индексу, начиная с нуля. Общий синтаксис: ТЗ[Индекс].ИмяКолонки. Например, чтобы прочитать значение колонки «Сумма» из первой строки:
ЗначениеЯчейки = ТаблицаТоваров[0].Сумма;
Имя колонки можно также передать строкой через квадратные скобки — это удобно, когда имя колонки заранее неизвестно и хранится в переменной:
ИмяКолонки = "Сумма";
ЗначениеЯчейки = ТаблицаТоваров[0][ИмяКолонки];
Главный риск прямого обращения — выход за границы таблицы. Если таблица пустая или индекс больше, чем Количество() - 1, платформа выдаст ошибку «Индекс находится за границами массива». Поэтому перед обращением по индексу проверяйте размер таблицы:
Если ТаблицаТоваров.Количество() > 0 Тогда
ПерваяСумма = ТаблицаТоваров[0].Сумма;
КонецЕсли;
Поиск строки методом Найти()
Метод Найти(Значение, ИмяКолонки) возвращает первую строку, где указанная колонка равна искомому значению. Если совпадений нет — возвращает Неопределено. Это самый частый способ получить конкретное значение по ключу:
СтрокаТовара = ТаблицаТоваров.Найти(ИскомаяНоменклатура, "Номенклатура");
Если СтрокаТовара <> Неопределено Тогда
Цена = СтрокаТовара.Цена;
Иначе
Сообщить("Товар не найден в таблице");
КонецЕсли;
Обязательно проверяйте результат на Неопределено до обращения к колонкам найденной строки. Обращение Неопределено.Цена — одна из самых распространённых ошибок при работе с таблицами значений.
Сравнение в методе Найти() выполняется по значению с учётом типа. Если в колонке хранится ссылка на справочник, а вы ищете строку с наименованием — совпадения не будет, даже если тексты совпадают. Также поиск по нескольким условиям одним вызовом Найти() невозможен — для этого используйте НайтиСтроки() со структурой отбора.
Отбор нескольких строк через НайтиСтроки()
Когда нужно получить все строки, удовлетворяющие одному или нескольким условиям, применяется метод НайтиСтроки(ПараметрыОтбора). Условия передаются структурой, где ключ — имя колонки, а значение — искомое значение. Метод возвращает массив строк (возможно, пустой):
Отбор = Новый Структура;
Отбор.Вставить("Склад", ОсновнойСклад);
Отбор.Вставить("Активна", Истина);
НайденныеСтроки = ТаблицаТоваров.НайтиСтроки(Отбор);
Для Каждого Строка Из НайденныеСтроки Цикл
ОбщееКоличество = ОбщееКоличество + Строка.Количество;
КонецЦикла;
Все условия в структуре объединяются по «И»: строка попадёт в результат, только если совпадут значения всех перечисленных колонок. Отбор по условию «ИЛИ» или по сравнению «больше/меньше» через НайтиСтроки() не делается — такие задачи решаются циклом с проверкой или запросом.
Перебор строк в цикле и получение значений по условию
Универсальный способ — обход таблицы в цикле Для Каждого. Внутри цикла доступны все колонки текущей строки, и можно реализовать любую логику: сложные условия, накопление значений, поиск максимума:
МаксимальнаяСумма = 0;
СтрокаМаксимума = Неопределено;
Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
Если СтрокаТовара.Сумма > МаксимальнаяСумма Тогда
МаксимальнаяСумма = СтрокаТовара.Сумма;
СтрокаМаксимума = СтрокаТовара;
КонецЕсли;
КонецЦикла;
Для досрочного выхода из цикла, когда нужное значение уже найдено, используйте оператор Прервать — это экономит время на больших таблицах. Оператор Продолжить пропускает текущую итерацию и переходит к следующей строке.
Если строки нужны по индексу (например, обработка парами или с конца), подойдёт классический цикл со счётчиком: Для Индекс = 0 По ТЗ.Количество() - 1 Цикл. Обратный обход удобен при удалении строк внутри цикла — удаление при прямом обходе сдвигает индексы и приводит к пропуску строк.
Для Индекс = -ТЗ.Количество() + 1 По 0 Цикл
Строка = ТЗ[-Индекс];
Если Строка.Пометка Тогда
ТЗ.Удалить(Строка);
КонецЕсли;
КонецЦикла;Итоги, свёртка и выгрузка колонки
Если нужна не строка, а агрегированное значение по колонке, перебор не обязателен. Метод Итог("Сумма") возвращает сумму по числовой колонке всей таблицы:
ОбщаяСумма = ТаблицаТоваров.Итог("Сумма");
Метод Свернуть("Номенклатура", "Количество,Сумма") группирует строки по указанным колонкам и суммирует числовые поля — это аналог группировки в запросе, выполненный в памяти. Учтите, что свёртка изменяет саму таблицу; если исходные строки ещё нужны, сначала сделайте копию методом Скопировать().
Для получения всех значений одной колонки в виде массива используйте ВыгрузитьКолонку("Номенклатура"). Обратная операция — ЗагрузитьКолонку(Массив, "Номенклатура") — записывает массив значений в колонку.
Сравнение способов получения значения
Быстрый доступ к известной строке. Требует проверки границ, не подходит для поиска по значению.
Поиск первой строки по одному условию. Возвращает Неопределено, если не найдено — нужна проверка.
Отбор по нескольким условиям «И». Возвращает массив строк, не подходит для условий «ИЛИ» и сравнений.
Любая логика и сложные условия. Медленнее встроенных методов на больших таблицах.
Агрегированные значения без цикла. Свернуть изменяет саму таблицу.
Производительность и большие таблицы
Методы Найти() и НайтиСтроки() выполняют линейный перебор строк. На таблице в несколько тысяч строк это незаметно, но если поиск вызывается внутри цикла по другой таблице, сложность становится квадратичной, и обработка может занять минуты.
Для ускорения повторного поиска создайте индекс по колонке: ТЗ.Индексы.Добавить("Номенклатура"). После этого Найти() и НайтиСтроки() по этой колонке будут работать значительно быстрее. Индекс имеет смысл добавлять, когда поиск выполняется многократно — на одиночный поиск затраты на построение индекса могут не окупиться.
Альтернатива для тяжёлых выборок — получить данные запросом сразу с нужным отбором и группировкой, а не фильтровать таблицу значений в памяти. Запрос на сервере СУБД почти всегда быстрее программного перебора.
Проверка результата и отладка
После получения значения полезно убедиться, что оно корректно: тип соответствует ожиданиям, значение заполнено. Для проверки типа используйте ТипЗнч(Значение), для проверки заполненности — ЗначениеЗаполнено(Значение).
При отладке содержимое всей таблицы удобно смотреть в конфигураторе через «Вычислить выражение» — таблица значений отображается в виде сетки. Программно структуру таблицы можно проверить через коллекцию ТЗ.Колонки: цикл по ней покажет имена и типы всех колонок, что помогает понять, почему обращение к колонке завершилось ошибкой «Поле не найдено».
Как проверить результат
Возвращена строка, значения колонок читаются
Неопределено — строка не найдена, проверьте тип и значение отбора
Массив, Количество() > 0
Пустой массив — условия отбора не совпали ни с одной строкой
Индекс от 0 до Количество()-1
Ошибка «Индекс за границами» — таблица пуста или индекс неверен
Ожидаемый тип через ТипЗнч()
Неопределено или NULL — колонка не заполнена в источнике
Частые вопросы
Как получить значение из таблицы значений, если имя колонки хранится в переменной?
Используйте обращение через квадратные скобки: СтрокаТЗ[ИмяКолонки], где ИмяКолонки — строковая переменная. Тот же приём работает и для строки, полученной по индексу: ТЗ[0][ИмяКолонки].
Чем Найти() отличается от НайтиСтроки()?
Найти() возвращает одну первую подходящую строку или Неопределено и умеет искать только по одной колонке. НайтиСтроки() принимает структуру с несколькими условиями и возвращает массив всех подходящих строк, при отсутствии совпадений — пустой массив.
Как найти строку по условию «больше» или «содержит»?
Встроенные методы поиска работают только на точное равенство. Для сравнений и частичного совпадения переберите таблицу циклом с оператором Если, либо получите данные запросом с соответствующим условием ГДЕ — второй вариант предпочтительнее на больших объёмах.
Почему Найти() не находит строку, хотя значение в таблице есть?
Чаще всего не совпадают типы: в колонке ссылка, а ищут строку, или число сравнивается со строкой. Также проверьте лишние пробелы и регистр в строковых значениях — сравнение выполняется точно.
Как получить значение из табличной части документа?
Табличная часть поддерживает те же методы, что и таблица значений: Найти(), НайтиСтроки(), Итог(), обращение по индексу. Например: ДокОбъект.Товары.Найти(Номенклатура, "Номенклатура"). Дополнительно доступен поиск по номеру строки через НайтиПоНомеру().
Как быстро получить сумму по колонке без цикла?
Вызовите метод Итог(): ТЗ.Итог("Сумма"). Он работает только с числовыми колонками. Если нужна сумма по отбору, сначала получите строки через НайтиСтроки() и просуммируйте их в цикле, либо используйте Свернуть() с группировкой.
Что важно запомнить
Для известной позиции используйте обращение по индексу с проверкой границ, для поиска по значению — Найти() с проверкой на Неопределено, для отбора по нескольким условиям — НайтиСтроки() со структурой. Итоги считайте методом Итог() без цикла, а при многократном поиске по большой таблице добавляйте индекс или переносите отбор в запрос.