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