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