Колонка из массива в 1С: берём значения одного поля

· 8 мин

Содержание

У обычного Массива в 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") или Строка(...), иначе получите разделители тысяч.
  • Ссылки вместо значений. В колонке типа СправочникСсылка лежат ссылки. Чтобы получить текстовое представление, обращайтесь к реквизиту (Ссылка.Наименование) в цикле или берите нужный реквизит прямо в запросе. Цикл с обращением к реквизиту по ссылке читает объект из базы, на больших списках это заметно медленнее.
  • Изменение массива внутри цикла. Не удаляйте элементы из массива, по которому идёте циклом Для Каждого. Собирайте результат в отдельный массив.

Если массив передаётся с клиента на сервер, а не создаётся на месте, колонка выгружается там, где лежит таблица. Не гоняйте таблицу значений туда-обратно ради одной колонки, а передайте на сервер уже готовый массив.

Что делать с выгруженной колонкой дальше

Массив значений одной колонки пригодится в типовых задачах:

  1. Поиск значения. Артикулы.Найти("A-100") вернёт индекс или Неопределено.
  2. Условие в запросе. Массив передаётся параметром и используется в конструкции В (&Массив).
  3. Сумма или максимум. Цикл с накоплением, у массива нет встроенного Итог. Если нужна сумма колонки, у таблицы значений есть Итог("Количество"), и массив не нужен.
  4. Фиксация результата. Новый ФиксированныйМассив(Артикулы) защитит значения от случайных изменений.
Откуда у вас данные?

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

Можно ли выгрузить колонку из обычного массива без цикла?
Только если это таблица значений: тогда подойдёт ВыгрузитьКолонку. У массива структур такого метода нет, нужен цикл или предварительная загрузка в таблицу.
Как выгрузить сразу две колонки?
Метод возвращает одну колонку за вызов. Вызовите его дважды или скопируйте таблицу с нужными колонками через Скопировать(, "Колонка1, Колонка2"), если требуется таблица с двумя колонками.
Сохранится ли порядок значений?
Да, порядок элементов в полученном массиве совпадает с порядком строк в таблице на момент выгрузки.
Что произойдёт с повторяющимися значениями?
Они останутся: ВыгрузитьКолонку ничего не сворачивает. Для уникальных значений используйте копию таблицы с Свернуть.
Работает ли `ВыгрузитьКолонку` на клиенте?
Да, метод есть у таблицы значений и на клиенте, и на сервере. Ограничения касаются того, какие данные у вас доступны на клиенте, а не самого метода.