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

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

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

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

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

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

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

Как создать таблицу значений и получить в неё данные

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

Таблица = Новый ТаблицаЗначений;

Таблица.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));

Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));

Запрос = Новый Запрос("ВЫБРАТЬ Номенклатура, Количество ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки");

ТаблицаОстатков = Запрос.Выполнить().Выгрузить();

При создании таблицы вручную обязательно указывайте типы колонок через ОписаниеТипов. Колонка без типа примет любое значение, но сортировка и свёртка по такой колонке могут работать непредсказуемо: числа, записанные как строки, сортируются лексикографически («10» окажется раньше «2»).

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

Базовый способ обработки — цикл Для каждого ... Из ... Цикл. Он подходит, когда нужно обработать каждую строку: заполнить дополнительные поля, проверить условия, сформировать по строкам документы.

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

Если СтрокаТЗ.Количество < 0 Тогда

СтрокаТЗ.Количество = 0; // обнуляем отрицательные остатки

КонецЕсли;

КонецЦикла;

Если нужен доступ по индексу (например, для пропуска первой строки или обработки в обратном порядке), используйте цикл Для Сч = 0 По Таблица.Количество() - 1 Цикл и обращение Таблица[Сч]. Помните, что индексация строк начинается с нуля — обращение к Таблица[Таблица.Количество()] вызовет ошибку.

Для удаления строк внутри цикла перебирайте таблицу с конца к началу или собирайте строки для удаления в отдельный массив, а удаляйте после цикла. Удаление текущей строки в прямом цикле «Для каждого» приводит к пропуску соседних элементов.

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

Как найти и отобрать нужные строки

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

Метод Найти(Значение, ИмяКолонки) возвращает первую найденную строку или Неопределено. Он подходит для проверки существования значения и для поиска по уникальному ключу.

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

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

СтрокаТовара = Таблица.Добавить();

СтрокаТовара.Номенклатура = ТекущийТовар;

КонецЕсли;

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

Для отбора всех строк, удовлетворяющих условию, используйте НайтиСтроки(СтруктураОтбора). Отбор задаётся структурой, где ключ — имя колонки, значение — искомое значение. Условия объединяются по «И».

Отбор = Новый Структура("Склад, Организация", Склад1, Организация1);

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

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

// обработка отобранных строк

КонецЦикла;

Ограничение метода — сравнение только на равенство. Если нужны условия «больше», «меньше», «содержит подстроку», используйте цикл с проверкой условия или построитель запроса по таблице.

Маршрут решения

Как выбрать способ отбора

Нужно проверить существование одного значенияИспользуйте Найти() — быстрее и короче цикла
Нужны все строки с конкретными значениями колонокИспользуйте НайтиСтроки() со структурой отбора
Условие сложное: диапазоны, неравенства, вычисляемые поляПереберите таблицу циклом с проверкой условия или выполните запрос к таблице через ВЫБРАТЬ ... ПОМЕСТИТЬ
Отбор выполняется многократно в циклеПостройте индекс методом Таблица.Индексы.Добавить() — поиск ускорится в разы

Как отсортировать таблицу значений

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

Таблица.Сортировать("Дата Возр, Сумма Убыв");

Сортировка меняет физический порядок строк, поэтому если исходный порядок важен (например, порядок строк документа), сначала сделайте копию: КопияТаблицы = Таблица.Скопировать(), и сортируйте копию.

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

Как сгруппировать данные и посчитать итоги

Свёртка таблицы методом Свернуть()

Метод Свернуть("КолонкиГруппировки", "КолонкиСуммирования") аналогичен группировке в запросе: строки с одинаковыми значениями колонок группировки объединяются, а по указанным колонкам суммируются значения. Остальные колонки удаляются.

ТаблицаИтогов = Таблица.Скопировать();

ТаблицаИтогов.Свернуть("Номенклатура, Склад", "Количество, Сумма");

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

Сумма по одной колонке методом Итог()

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

bsl
ВсегоПоДокументу = ТаблицаТоваров.Итог("Сумма");
КоличествоСтрок = ТаблицаТоваров.Количество();

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

Как скопировать, объединить и выгрузить таблицу

Метод Скопировать() создаёт полную копию таблицы, СкопироватьКолонки() — пустую таблицу с той же структурой. Второй вариант удобен, когда нужно заполнить результат отбором строк по сложному условию.

Результат = Таблица.СкопироватьКолонки();

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

Если Строка.Сумма > 100000 Тогда

НоваяСтрока = Результат.Добавить();

ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);

КонецЕсли;

КонецЦикла;

Для выгрузки в табличный документ или Excel таблицу значений обычно переносят построчно в макет, либо используют Выгрузить() результата запроса сразу в табличный документ. В управляемых формах таблицу значений, размещённую в реквизите формы, можно отобразить напрямую — платформа сама построит элемент формы «таблица».

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

После обработки таблицы полезно выполнить контрольные проверки: совпадает ли итог по суммовым колонкам до и после свёртки, не потерялись ли строки при отборе, корректны ли типы колонок. Для отладки выводите таблицу в сообщение или в табличный документ.

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

Сообщить(Строка(Строка.Номенклатура) + " | " + Строка.Количество);

КонецЦикла;

При работе в управляемых формах помните про контекст: на клиенте недоступны запросы и прямой доступ к данным, поэтому получение и тяжёлая обработка таблиц выполняется в серверных процедурах с директивой &НаСервере. Реквизит формы типа «ТаблицаЗначений» при передаче между клиентом и сервером сериализуется — лишние вызовы сервера с большой таблицей заметно тормозят работу.

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

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

Итог по суммовой колонке до и после свёртки
Норма

Суммы совпадают

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

Сумма изменилась — свёрнута лишняя колонка или потеряны строки

Количество строк после отбора
Норма

Число строк соответствует ожидаемому по данным источника

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

Строк больше или меньше ожидаемого — проверьте структуру отбора и типы значений

Типы колонок после загрузки из внешнего источника
Норма

Числа хранятся как числа, даты как даты

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

Числа в строковом виде — сортировка и итоги работают неверно

Итог

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

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

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

Чем таблица значений отличается от дерева значений?

Дерево значений хранит иерархию: у каждой строки есть коллекция подчинённых строк. Таблица значений — плоская структура без вложенности. Результат запроса с итогами по группировкам выгружается в дерево методом Выгрузить(ТипОбходаРезультатаЗапроса.ПоГруппировкам), обычная выборка — в таблицу значений.

Как удалить дубли строк в таблице значений?

Проще всего свернуть таблицу по всем колонкам без колонок суммирования: Таблица.Свернуть("Колонка1,Колонка2,Колонка3"). Одинаковые строки объединятся в одну. Альтернатива — передать таблицу в запрос и применить ВЫБРАТЬ РАЗЛИЧНЫЕ.

Можно ли выполнить запрос к уже заполненной таблице значений?

Да. Передайте таблицу в запрос как параметр, выберите её во временную таблицу через конструкцию ВЫБРАТЬ ... ПОМЕСТИТЬ из параметра, а затем выполняйте к ней обычные запросы с соединениями, группировками и условиями. Это удобно для сложных отборов, которых не хватает у НайтиСтроки().

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

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

Почему Свернуть() удалил нужные колонки?

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