Столбец двумерного массива, таблицы значений и списка: доступ из кода 1С
Содержание
Обратиться к колонке массива в 1С можно так: в двумерном массиве — Матрица[НомерСтроки][НомерКолонки], а всю колонку собрать циклом по строкам. В таблице значений колонку целиком отдаёт метод ВыгрузитьКолонку("ИмяКолонки") — он сразу возвращает обычный Массив.
Сложность в том, что «колонок» у самого типа Массив нет. Это одномерная коллекция. Колонка появляется, когда массив вложенный, когда данные лежат в таблице значений или когда речь о поле динамического списка на форме. Ниже — пять рабочих способов для каждого случая, с кодом для платформы 8.3.
Откуда у массива колонки: двумерный массив, таблица и список
Встроенный язык 1С знает несколько коллекций, и «колонка» в них устроена по-разному:
- 🔢 Массив массивов. Каждый элемент внешнего массива — строка, внутри неё лежат значения. Колонка — это элементы с одним и тем же индексом во всех строках.
- 📊 Таблица значений. Колонки здесь настоящие: у них есть имя, тип и заголовок. Они хранятся в коллекции
Колонки. - 🧩 Массив структур. Строка — структура, колонка — ключ структуры. Частый результат разбора JSON или ответа веб-сервиса.
- 🖥 Динамический список. Колонка — поле списка на управляемой форме. Обращение идёт к данным текущей или выделенной строки.
Индексация везде начинается с нуля. В массиве из 5 элементов последний индекс — 4, а Количество() вернёт 5. Эта разница — частая причина ошибки «за границами массива».
| Структура данных | Как взять значение | Как взять всю колонку |
|---|---|---|
| Массив массивов | М[2][1] | цикл по строкам |
| Массив (одномерный) | М[3] или М.Получить(3) | — |
| Таблица значений | Строка.Сумма, Строка["Сумма"], Строка[0] | ТЗ.ВыгрузитьКолонку("Сумма") |
| Табличная часть объекта | Строка.Количество | Объект.Товары.ВыгрузитьКолонку("Номенклатура") |
| Массив структур | М[0].Сумма | цикл по элементам |
| Динамический список | Элементы.Список.ТекущиеДанные.Сумма | цикл по ВыделенныеСтроки |
Способ 1. Индексы в двумерном массиве (массиве массивов)
Конструктор Новый Массив принимает несколько размерностей. Новый Массив(3, 4) создаёт внешний массив из трёх элементов, и каждый из них — массив из четырёх значений Неопределено.
Матрица = Новый Массив(3, 4);
// Заполним: значение = номер строки * 10 + номер колонки
Для НомерСтроки = 0 По 2 Цикл
Для НомерКолонки = 0 По 3 Цикл
Матрица[НомерСтроки][НомерКолонки] = НомерСтроки * 10 + НомерКолонки;
КонецЦикла;
КонецЦикла;
Значение = Матрица[2][1]; // 21 — третья строка, вторая колонка
Первый индекс — строка, второй — колонка. Матрица.Количество() вернёт 3 (строк), Матрица[0].Количество() — 4 (колонок).
Как получить всю колонку
Отдельного метода нет, колонку собирают циклом. Удобно вынести это в функцию общего модуля:
Функция КолонкаМатрицы(Матрица, НомерКолонки) Экспорт
Результат = Новый Массив;
Для Каждого СтрокаМатрицы Из Матрица Цикл
Если НомерКолонки < СтрокаМатрицы.Количество() Тогда
Результат.Добавить(СтрокаМатрицы[НомерКолонки]);
Иначе
Результат.Добавить(Неопределено);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Для матрицы выше КолонкаМатрицы(Матрица, 1) вернёт массив 1, 11, 21.
Проверка длины строки нужна потому, что вложенные массивы не обязаны быть одинаковыми. Если массив собирали вручную через Добавить(), в одной строке может оказаться 4 элемента, а в другой 3. Без проверки цикл упадёт на короткой строке.
Как записать значения в колонку
Запись — тот же цикл, только с присваиванием:
Для Каждого СтрокаМатрицы Из Матрица Цикл
СтрокаМатрицы[3] = 0; // обнулить четвёртую колонку
КонецЦикла;
Если с двумерными данными приходится часто работать по колонкам — суммировать, искать, сортировать, — переложите их в таблицу значений. Там всё это делается одной строкой кода.
Способ 2. Колонки таблицы значений и ВыгрузитьКолонку
В таблице значений к колонке обращаются тремя путями:
- По имени через точку:
Строка.Сумма. Самый читаемый вариант, но имя должно быть известно при написании кода. - По имени в квадратных скобках:
Строка["Сумма"]. Подходит, когда имя колонки лежит в переменной. - По номеру:
Строка[0]. Номер соответствует порядку колонок в коллекцииКолонки.
Выгрузить колонку в массив
Метод ВыгрузитьКолонку возвращает массив значений колонки по всем строкам, в порядке строк:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Контрагент,
| Контрагенты.ИНН КАК ИНН
|ИЗ
| Справочник.Контрагенты КАК Контрагенты";
Таблица = Запрос.Выполнить().Выгрузить();
МассивИНН = Таблица.ВыгрузитьКолонку("ИНН");
Параметром можно передать имя колонки, её номер или саму колонку из коллекции Колонки. Тот же метод есть у табличной части объекта: ДокументОбъект.Товары.ВыгрузитьКолонку("Номенклатура").
Обратная операция — ЗагрузитьКолонку(Массив, "ИмяКолонки"). Она раскладывает элементы массива по строкам таблицы: первый элемент в первую строку, второй во вторую. Готовьте массив той же длины, что и таблица.
Работа с коллекцией Колонки
Сама коллекция Колонки нужна, когда структура таблицы заранее неизвестна:
// Есть ли колонка
Если Таблица.Колонки.Найти("ИНН") <> Неопределено Тогда
// колонка на месте
КонецЕсли;
// Обойти все колонки строки
Для Каждого Колонка Из Таблица.Колонки Цикл
Сообщить(Колонка.Имя + ": " + Строка(Таблица[0][Колонка.Имя]));
КонецЦикла;
Таблица[0] — первая строка таблицы, к ней обращаются по индексу так же, как к элементу массива. Если таблица пустая, такая строка вызовет ошибку, поэтому сначала проверьте Таблица.Количество() > 0.
Для частых операций с колонкой у таблицы значений есть готовые методы:
- ➕
Таблица.Итог("Сумма")— сумма числовой колонки. - 🔍
Таблица.НайтиСтроки(Новый Структура("ИНН", "7701234567"))— строки с нужным значением. - 🔃
Таблица.Сортировать("Сумма Убыв")— сортировка по колонке. - 🧮
Таблица.Свернуть("Контрагент", "Сумма")— группировка с суммированием.
Способ 3. Методы Получить и Установить у массива
У одномерного массива, кроме квадратных скобок, есть методы Получить(Индекс) и Установить(Индекс, Значение). Работают они так же, как индекс в скобках:
Ставки = Новый Массив;
Ставки.Добавить(0);
Ставки.Добавить(10);
Ставки.Добавить(20);
А = Ставки[2]; // 20
Б = Ставки.Получить(2); // тоже 20
Ставки.Установить(0, 5); // то же, что Ставки[0] = 5
Для двумерного массива методы комбинируются: Матрица.Получить(2).Получить(1) — тот же элемент, что Матрица[2][1].
Где Получить удобнее скобок:
- 🔗 в цепочке вызовов, когда массив возвращает функция:
ПолучитьДанные().Получить(0); - 📝 в коде, который должен одинаково читаться с методами других коллекций.
Ни скобки, ни Получить() не защищают от выхода за границу. Перед обращением по вычисленному индексу проверяйте его:
Если Индекс >= 0 И Индекс < Ставки.Количество() Тогда
Значение = Ставки[Индекс];
КонецЕсли;
Способ 4. Колонка в массиве структур
Ответ HTTP-сервиса, прочитанный из JSON, или результат обработки часто приходит как массив структур. Колонка здесь — ключ:
Строки = Новый Массив;
Строки.Добавить(Новый Структура("Код, Сумма", "001", 1500));
Строки.Добавить(Новый Структура("Код, Сумма", "002", 2300));
Суммы = Новый Массив;
Для Каждого Элемент Из Строки Цикл
Значение = Неопределено;
Если Элемент.Свойство("Сумма", Значение) Тогда
Суммы.Добавить(Значение);
КонецЕсли;
КонецЦикла;
// Суммы: 1500, 2300
Метод Свойство с двумя параметрами сразу проверяет наличие ключа и кладёт значение во второй параметр. Обращение через точку Элемент.Сумма короче, но если ключа нет, код упадёт.
Если имя колонки передаётся строкой, используйте скобки: Элемент["Сумма"]. Для соответствия (Соответствие) запись такая же, но отсутствующий ключ вернёт Неопределено, а не ошибку.
Способ 5. Поле динамического списка на форме
В динамическом списке нет массива в памяти. Данные подгружаются порциями, и обращаться к «колонке» можно только через строки, которые сейчас есть на форме.
Текущая строка
&НаКлиенте
Процедура ПоказатьИНН(Команда)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
Сообщить(ТекущиеДанные.ИНН);
КонецПроцедуры
ТекущиеДанные возвращает Неопределено, когда список пуст или курсор не стоит на строке. Без этой проверки команда на пустом списке выдаст ошибку.
Колонка по выделенным строкам
Элементы.Список.ВыделенныеСтроки — массив ключей выделенных строк. Данные строки по ключу отдаёт метод таблицы формы ДанныеСтроки:
&НаКлиенте
Процедура СобратьИНН(Команда)
МассивИНН = Новый Массив;
Для Каждого Ключ Из Элементы.Список.ВыделенныеСтроки Цикл
Если ТипЗнч(Ключ) = Тип("СтрокаГруппировкиДинамическогоСписка") Тогда
Продолжить; // строка группировки, а не запись
КонецЕсли;
ДанныеСтроки = Элементы.Список.ДанныеСтроки(Ключ);
Если ДанныеСтроки <> Неопределено Тогда
МассивИНН.Добавить(ДанныеСтроки.ИНН);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Поле ИНН должно присутствовать в списке. Если колонку не вывели на форму, поле может не прийти в данные строки. Включите для него в настройках динамического списка признак «Использовать всегда» — тогда платформа будет выбирать его даже без колонки на форме.
Если пользователь выделил тысячи строк, разумнее передать массив ВыделенныеСтроки на сервер и получить нужные поля одним запросом с условием В (&Ссылки), а не перебирать данные строк на клиенте.
Какой способ доступа к колонке быстрее
Точные цифры зависят от сервера и объёма данных, но соотношение между способами стабильное.
| Задача | Быстрый вариант | Медленный вариант |
|---|---|---|
| Колонка таблицы целиком | ВыгрузитьКолонку() | цикл по строкам с Добавить() |
| Сумма по колонке | Итог() | цикл со сложением |
| Поиск строк по значению | НайтиСтроки() с индексом | перебор с Если |
| Значение массива по индексу | М[i] | М.Получить(i) — разница несущественна |
| Данные из базы | поле в тексте запроса | обращение через точку к реквизиту ссылки в цикле |
Что даёт реальный выигрыш:
- Методы платформы вместо циклов.
ВыгрузитьКолонку,Итог,Свернутьвыполняются внутри платформы, а цикл на встроенном языке интерпретируется построчно. На таблице в сотни тысяч строк разница заметна. - Индекс перед повторным поиском. Если по одной колонке ищете много раз, добавьте индекс:
Таблица.Индексы.Добавить("ИНН"). Для разового поиска индекс не нужен — его построение само стоит времени. - Поиск колонки вне цикла.
Колонки.Найти()и разбор имени колонки делайте один раз до цикла, а не на каждой строке. - Без обращений через точку к ссылкам.
Строка.Контрагент.ИННвнутри цикла — это отдельное чтение из базы на каждую строку. Получите ИНН в запросе сразу. - Перебор
Для Каждого. Для обхода всех строк он читается проще цикла по индексу и не требует следить за границами.
Таблица значений существует только на сервере. Если колонку нужно показать или обработать на клиенте, выгрузите её в массив на сервере и верните массив — массив примитивных значений и ссылок между клиентом и сервером передаётся.
Ошибки при обращении к колонкам и как их найти
Сбои при работе с колонками обычно сводятся к пяти ситуациям.
Количество() либо отрицательный. Частая причина — цикл Для i = 0 По М.Количество() без - 1 или короткая строка в массиве массивов. Проверяйте границу перед обращением.Колонки.Найти() или Свойство().Новый Массив(3, 4), элементы изначально пустые. Либо в динамическом списке поле не выбирается — включите для него «Использовать всегда».ВыгрузитьКолонку отдаёт значения в текущем порядке строк. Отсортируйте таблицу до выгрузки.Ещё одна тонкость — изменение массива во время обхода. Если удаляете элементы, идите с конца, иначе индексы сдвинутся и часть элементов пропустится:
Для Сч = 1 По Ставки.Количество() Цикл
Индекс = Ставки.Количество() - Сч;
Если Ставки[Индекс] = 0 Тогда
Ставки.Удалить(Индекс);
КонецЕсли;
КонецЦикла;
Граница цикла вычисляется один раз при входе, а Ставки.Количество() - Сч пересчитывается на каждом шаге. После удаления элемента индексы оставшихся слева не меняются, поэтому обход доходит до нулевого элемента без пропусков.
Частые вопросы о колонках массивов в 1С
Можно ли создать массив сразу с тремя измерениями?
Новый Массив(2, 3, 4) создаёт массив массивов массивов, обращение — М[1][2][3]. На практике больше двух измерений неудобно отлаживать.Как узнать количество колонок в таблице значений?
Таблица.Колонки.Количество(). Имя колонки по номеру — Таблица.Колонки[0].Имя.Как транспонировать двумерный массив — сделать колонки строками?
Новая[j][i] = Старая[i][j]. Встроенного метода для этого нет.Чем ФиксированныйМассив отличается при чтении колонки?
Добавить и Установить у него нет.Как получить колонку из списка значений?
СписокЗначений.ВыгрузитьЗначения() возвращает массив значений элементов списка.