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