Столбец для массива в 1С: таблица значений, массив массивов, табличный документ

· 9 мин

Содержание

У объекта Массив в 1С нет столбцов: это одномерный список значений, у него только индекс и содержимое. Чтобы получить столбцы, берут ТаблицаЗначений и добавляют колонки методом Колонки.Добавить(). Если данные уже лежат в массиве, их загружают в новую колонку одной строкой через ЗагрузитьКолонку().

Запрос «добавить столбец в массив» на практике означает одну из трёх задач: нужна двумерная структура «строки × поля», нужно дописать поле к уже заполненной таблице или нужен лишний столбец в печатной форме. Ниже по каждой задаче свой способ и рабочий код. Примеры написаны для платформы 8.3 и выполняются на сервере и на клиенте.

Почему у массива нет столбцов и что брать вместо него

Массив хранит элементы по порядку: индексы идут с нуля, Массив[0], Массив[1] и так далее. Добавить к нему «ещё одно измерение» методом платформы нельзя. Можно только имитировать двумерность разными коллекциями.

Выбор зависит от того, что вы делаете с данными дальше:

КоллекцияКогда подходитОграничения
ТаблицаЗначенийНужны именованные столбцы, сортировка, свёртка, поиск, вывод в формуТяжелее массива по памяти, на миллионах строк заметно
Массив массивовНебольшой расчёт внутри процедуры, имён полей не надоНет имён колонок, легко запутаться в индексах
Массив структурКаждая «строка» — набор именованных свойствНет встроенной сортировки и свёртки
ТабличныйДокументРезультат нужно показать или напечататьЭто не коллекция для вычислений, а форма вывода

Для большинства задач с вычислениями правильный ответ — таблица значений. Остальные варианты разберём ниже.

Если вам нужен просто список с подписями (значение и представление), смотрите в сторону СписокЗначений: у него два «столбца» из коробки.

Когда столбцы вообще не нужны

Бывает, что двумерная структура появляется по привычке. Если вы храните пары «ключ — значение», достаточно Соответствие: Соответствие.Вставить("Бумага А4", 10), а читать можно по ключу, без поиска по индексу. Если нужен просто список уникальных значений, хватит массива и проверки через Найти() перед добавлением.

Столбцы нужны, когда у каждого элемента несколько характеристик одновременно и с ними предстоит работать как с набором: сортировать, группировать, выводить в таблицу на форме. Для остальных задач таблица значений только усложнит код.

Практичное правило: если в коде появилось два параллельных массива с одинаковым числом элементов («наименования» и «количества»), пора переходить на таблицу значений. Параллельные массивы расходятся при первой же правке: удалили элемент в одном, забыли во втором, и данные поехали.

Первый способ: создаём таблицу значений и добавляем колонки

Это основной путь. Таблица значений создаётся пустой, колонки описываются явно, потом идёт заполнение строк.

Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Номенклатура");
Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", , , Новый КвалификаторыЧисла(15, 3)));
Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", , , Новый КвалификаторыЧисла(15, 2)));

Строка = Таблица.Добавить();
Строка.Номенклатура = "Бумага А4";
Строка.Количество = 10;
Строка.Сумма = 1250;

Метод Колонки.Добавить() принимает четыре параметра: имя, тип, заголовок и ширину. Обязательно только имя. Остальные задают, когда таблица потом выводится на форму.

Имя колонки и тип

Имя колонки должно быть допустимым идентификатором: без пробелов и спецсимволов, не начинается с цифры. Заголовок можно писать любой, в нём пробелы разрешены.

Тип лучше указывать сразу. Без типа в колонку попадёт что угодно, а сортировка и свёртка по смешанным значениям работают непредсказуемо. Строки и даты описывают через Новый ОписаниеТипов("Строка") и Новый ОписаниеТипов("Дата"), ссылки — через Новый ОписаниеТипов("СправочникСсылка.Номенклатура").

Второй способ: выгрузить массив в столбец существующей таблицы

Частый случай: массив уже собран, например список сумм, и его нужно положить в колонку. Руками по строкам делать не надо.

Суммы = Новый Массив;
Суммы.Добавить(1250);
Суммы.Добавить(300);
Суммы.Добавить(75.5);

Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Номер");
Таблица.Колонки.Добавить("Сумма");

Для Счетчик = 1 По Суммы.Количество() Цикл
	Таблица.Добавить().Номер = Счетчик;
КонецЦикла;

Таблица.ЗагрузитьКолонку(Суммы, "Сумма");

Метод ЗагрузитьКолонку(Массив, Колонка) кладёт элементы по порядку, начиная с первой строки. Если элементов в массиве меньше, чем строк, остальные ячейки не затрагиваются. Если больше — лишние отбрасываются: новых строк метод не создаёт.

Обратная операция — ВыгрузитьКолонку("Сумма"). Она возвращает массив со значениями одной колонки. Так удобно передавать список в запрос как параметр для условия В (&Список).

Количество строк таблицы должно совпадать с размером массива. Сначала создайте строки, потом загружайте колонку. Иначе часть данных молча пропадёт.

Третий способ: добавить колонку в готовую таблицу и посчитать её

Таблица уже есть, например из результата запроса: Результат.Выгрузить(). Нужна ещё одна колонка с расчётом.

Таблица.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", , , Новый КвалификаторыЧисла(15, 2)));

Для Каждого Строка Из Таблица Цикл
	Если Строка.Количество <> 0 Тогда
		Строка.Цена = Строка.Сумма / Строка.Количество;
	КонецЕсли;
КонецЦикла;

Новая колонка встаёт в конец. Если порядок важен для вывода на форму, используйте Колонки.Вставить(Индекс, Имя, Тип, Заголовок): колонка встанет на указанную позицию, а остальные сдвинутся.

Проверка, что колонки ещё нет

Повторное добавление колонки с тем же именем вызывает исключение. Если таблица приходит из внешнего источника, проверяйте заранее:

Если Таблица.Колонки.Найти("Цена") = Неопределено Тогда
	Таблица.Колонки.Добавить("Цена");
КонецЕсли;

Удаляется колонка командой Таблица.Колонки.Удалить("Цена"). Данные в ней пропадут вместе с колонкой.

Колонка из результата запроса

Таблицу значений чаще всего получают из запроса. Колонки в ней уже есть, по одной на каждое выбранное поле.

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|	Номенклатура.Наименование КАК Наименование,
|	Номенклатура.Артикул КАК Артикул
|ИЗ
|	Справочник.Номенклатура КАК Номенклатура";
Таблица = Запрос.Выполнить().Выгрузить();

Таблица.Колонки.Добавить("Метка", Новый ОписаниеТипов("Строка"));
Таблица.ЗаполнитьЗначения("не проверено", "Метка");

Метод ЗаполнитьЗначения(Значение, Колонка) ставит одно и то же значение во всех строках колонки. Для служебных пометок и флагов это быстрее цикла.

Копия структуры без данных

Иногда нужна таблица с теми же колонками, но пустая, например чтобы собрать в неё отфильтрованные строки:

Отбор = Таблица.СкопироватьКолонки();
Для Каждого Строка Из Таблица Цикл
	Если Строка.Метка = "не проверено" Тогда
		НоваяСтрока = Отбор.Добавить();
		ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
	КонецЕсли;
КонецЦикла;

СкопироватьКолонки() переносит имена, типы и заголовки. Строки не копируются. Для копии вместе с данными вызывайте Скопировать(); там же можно сразу выбрать нужные колонки второй строкой параметров.

Перебор колонок

Если структура таблицы заранее неизвестна, например пришла из внешнего файла, колонки обходят циклом и читают имя каждой:

Для Каждого Колонка Из Таблица.Колонки Цикл
	Сообщить(Колонка.Имя + " (" + Колонка.Заголовок + ")");
КонецЦикла;

Так же удобно собирать таблицу «на лету»: прочитали заголовки из первой строки файла, по ним создали колонки, дальше заполняем строки.

Четвёртый способ: массив массивов и массив структур

Таблица значений избыточна, когда данных на пару десятков строк и они нужны одной процедуре. Тогда делают массив, элементы которого тоже массивы: внешний — строки, внутренний — столбцы.

Данные = Новый Массив;

Строка = Новый Массив;
Строка.Добавить("Бумага А4");
Строка.Добавить(10);
Данные.Добавить(Строка);

Строка = Новый Массив;
Строка.Добавить("Картридж");
Строка.Добавить(2);
Данные.Добавить(Строка);

// Добавляем «столбец» — третий элемент в каждую строку
Для Каждого Строка Из Данные Цикл
	Строка.Добавить(Строка[1] * 100);
КонецЦикла;

Каждая строка — отдельный массив, поэтому в цикле достаточно дописать элемент в конец. Столбец «Количество» тут лежит по индексу 1, и помнить это придётся самому.

Читаемее вариант со структурами:

Данные = Новый Массив;

Элемент = Новый Структура("Номенклатура, Количество", "Бумага А4", 10);
Данные.Добавить(Элемент);

Для Каждого Элемент Из Данные Цикл
	Элемент.Вставить("Сумма", Элемент.Количество * 125);
КонецЦикла;

Метод Структура.Вставить() добавляет новое свойство или меняет существующее. Это и есть «добавить столбец»: поле появляется у каждого элемента. Минус — массив структур не умеет сортироваться и сворачиваться, придётся писать цикл самому.

Пятый вариант: столбец в табличном документе

Если вы формируете печатную форму или отчёт, речь о ТабличныйДокумент. Здесь «столбец» — это колонка ячеек, у которой есть ширина и содержимое. Вставить колонку в середину нельзя, обычный путь — дописать справа или присоединить готовую область.

ТабДок = Новый ТабличныйДокумент;
ТабДок.Область(1, 1).Текст = "Номенклатура";
ТабДок.Область(1, 2).Текст = "Количество";
ТабДок.Область(2, 1).Текст = "Бумага А4";
ТабДок.Область(2, 2).Текст = 10;

// Новый столбец справа от существующих
ТабДок.Область(1, 3).Текст = "Сумма";
ТабДок.Область(2, 3).Текст = 1250;
ТабДок.Область(1, 3, 2, 3).ШиринаКолонки = 18;

Область(Строка, Колонка) берёт одну ячейку, Область(СтрокаНачало, КолонкаНачало, СтрокаКонец, КолонкаКонец) — диапазон. Свойство ШиринаКолонки задают у диапазона из нужных столбцов.

Для макетов обычно работают иначе: в макете есть область с шапкой и область со строкой, документ собирают через Вывести(), а горизонтальное расширение делают методом Присоединить(), который ставит область справа от последней выведенной.

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

Скорость: что делать, когда строк много

На сотне строк разницы между способами нет. На десятках тысяч начинается.

  • 📌 Колонки добавляйте один раз до заполнения, а не в цикле по строкам.
  • 📌 Для расчёта по всей таблице пользуйтесь свёрткой Свернуть("Номенклатура", "Сумма") вместо ручного суммирования циклом.
  • 📌 Если колонку можно получить на стороне запроса (ВЫБРАТЬ ... КАК Цена), делайте это там. Запрос посчитает быстрее, чем цикл на клиенте.
  • 📌 Не обращайтесь к Таблица.Колонки.Найти() внутри цикла по строкам. Результат сохраните в переменную.
  • 📌 Для поиска по значению колонки создайте индекс: Таблица.Индексы.Добавить("Номенклатура"). Тогда НайтиСтроки() перестанет перебирать всю таблицу.

Ещё одна ловушка касается типов чисел. Колонка без квалификатора принимает любое число, но при выводе в форму 1С покажет его с настройками по умолчанию. Для денег задавайте 15 знаков и 2 после запятой, для количества 15 и 3. Тогда значения не уедут в экспоненциальную запись и не округлятся на выводе.

Сортировка тоже зависит от колонки. Таблица.Сортировать("Сумма Убыв, Номенклатура") упорядочит строки по убыванию суммы, а при равенстве суммы по имени. Если в колонке лежат значения разных типов, порядок получится странным: числа, строки и даты сравниваются по правилам платформы, а не по здравому смыслу.

Передавая таблицу с клиента на сервер, учтите: она сериализуется целиком. Лишние колонки тоже едут по сети, поэтому ненужные удаляйте до вызова.

Типичные ошибки при добавлении столбцов

Четыре сообщения, которые встречаются чаще остальных.

Диагностика: выберите симптом

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

Можно ли добавить колонку в обычный массив?
Нет. Массив одномерный. Либо переходите на таблицу значений, либо делаете массив массивов.
Как узнать, сколько колонок в таблице значений?
Через Таблица.Колонки.Количество(). Имена колонок получают перебором коллекции Для Каждого Колонка Из Таблица.Колонки Цикл, у каждой колонки есть свойство Имя.
Как поменять тип колонки уже заполненной таблицы?
Напрямую нельзя. Добавьте новую колонку нужного типа, перенесите значения циклом, старую удалите через Колонки.Удалить().
Можно ли выгрузить колонку таблицы значений обратно в массив?
Да, Таблица.ВыгрузитьКолонку("Сумма") возвращает массив значений этой колонки в порядке строк.
Чем ТаблицаЗначений отличается от ТабличногоДокумента?
Таблица значений хранит данные для вычислений. Табличный документ хранит оформленный результат: ячейки, шрифты, границы. Считают в первой, показывают и печатают во втором.