Колонки таблицы значений 1С 8.3: доступ по имени, индексу и в цикле
Содержание
Чтобы обратиться к колонке таблицы значений в 1С, берут строку и пишут имя колонки через точку: Стр.Сумма. Если имя приходит в переменной, используют скобки Стр["Сумма"], если известен только номер — Стр[2] или Стр.Получить(2). Сама колонка как объект (имя, тип, заголовок) живёт в коллекции ТЗ.Колонки.
Выбор способа простой. Точка — когда имя известно при написании кода. Скобки со строкой — когда имя вычисляется. Индекс — для универсальных обработок, которые не знают структуру таблицы заранее. Всё ниже относится к встроенному языку платформы 8.3 и одинаково работает в любой конфигурации.
Пять способов обратиться к колонке: сравнение
Значение ячейки таблицы значений всегда читается через строку (СтрокаТаблицыЗначений). Колонка задаёт, какое поле строки нужно. Вот все рабочие варианты на одной таблице.
| Способ | Пример | Когда применять | Подводный камень |
|---|---|---|---|
| Через точку | Стр.Сумма | Имя известно заранее | Опечатка видна только при выполнении |
| По имени в скобках | Стр["Сумма"] | Имя в переменной | Строку легко ошибочно собрать |
| По индексу | Стр[2] | Перебор всех колонок | Индекс съезжает при вставке колонки |
| Метод строки | Стр.Получить(2) | Код в стиле коллекций | Принимает только число |
| Через объект колонки | Стр[Кол.Имя] | Цикл по ТЗ.Колонки | Лишнее чтение имени на каждой итерации |
Пример таблицы, на которой проверены все фрагменты статьи:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
ТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
Стр = ТЗ.Добавить();
Стр.Номенклатура = "Бумага А4";
Стр.Количество = 10;
Стр.Сумма = 3500;
Индексы колонок здесь такие: Номенклатура — 0, Количество — 1, Сумма — 2. Нумерация всегда с нуля.
Обращение к колонке по имени: точка и квадратные скобки
Через точку
Самый читаемый вариант. Работает и на чтение, и на запись:
Стр.Сумма = Стр.Количество * 350;
Сообщить(Стр.Номенклатура);
Конкретную строку можно взять по её номеру в таблице: ТЗ[0].Сумма или ТЗ.Получить(0).Сумма. Оба варианта равнозначны.
По имени в квадратных скобках
Скобки принимают строку с именем колонки. Синтаксис нужен, когда имя хранится в переменной или приходит параметром:
ИмяПоля = "Сумма";
Стр[ИмяПоля] = Стр[ИмяПоля] * 1.2;
Регистр букв в имени не важен: Стр["сумма"] и Стр.СУММА дадут одну и ту же колонку. Пробелы и точки в имени недопустимы, поэтому строку вида "Сумма с НДС" скобки не примут — колонку с таким именем просто нельзя создать.
Если имя колонки берётся из настроек пользователя или из внешнего файла, сначала проверьте его через ТЗ.Колонки.Найти(ИмяПоля). Иначе неверное имя уронит обработку посередине.
Работа с колонками по индексу
Индекс колонки — её номер в коллекции ТЗ.Колонки, начиная с нуля. Строка таблицы принимает этот номер в квадратных скобках:
Стр[0] = "Скрепки"; // Номенклатура
Стр[1] = 5; // Количество
Стр[2] = Стр[1] * 40; // Сумма = 200
Узнать индекс колонки по её имени:
Кол = ТЗ.Колонки.Найти("Сумма");
Индекс = ТЗ.Колонки.Индекс(Кол); // 2
Последний индекс равен ТЗ.Колонки.Количество() - 1. Обращение к номеру за этой границей вызывает ошибку выполнения, поэтому в универсальном коде границу берут из коллекции, а не пишут числом.
Индекс зависит от порядка колонок. Если кто-то добавит колонку методом Вставить(0, …) или переставит её через Сдвинуть(), все жёстко прописанные номера начнут указывать не туда. В прикладном коде с известной структурой обращайтесь по имени, а не по номеру.
Индекс оправдан в двух случаях: универсальный перебор неизвестной таблицы и горячие циклы на сотнях тысяч строк, где номер вычислен один раз до цикла.
Методы строки Получить() и Установить()
У строки таблицы значений есть пара методов для доступа по индексу:
- 🔹
Получить(Индекс)— возвращает значение колонки с этим номером; - 🔹
Установить(Индекс, Значение)— записывает значение в колонку.
Стр = ТЗ[0];
Количество = Стр.Получить(1);
Стр.Установить(2, Количество * 350);
По результату это то же самое, что Стр[1] и Стр[2] = …. Методы удобны, когда код пишется в общем стиле работы с коллекциями или передаётся в процедуру, где явный вызов читается понятнее скобок.
Два частых заблуждения:
- Метода
УстановитьЗначение()у строки таблицы значений нет. Правильное имя —Установить(). Получить()иУстановить()принимают только число. Имя колонки строкой туда не передаётся — для имени используйтеСтр["Сумма"].
Не путайте с ТЗ.Получить(Индекс): этот метод самой таблицы возвращает строку, а не значение колонки.
Коллекция Колонки: создать, найти, переименовать, удалить
ТЗ.Колонки — коллекция объектов КолонкаТаблицыЗначений. У каждой колонки четыре свойства: Имя, ТипЗначения, Заголовок, Ширина.
| Задача | Код |
|---|---|
| Добавить в конец | ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число")) |
| Вставить на позицию | ТЗ.Колонки.Вставить(1, "Артикул") |
| Найти по имени | Кол = ТЗ.Колонки.Найти("Цена") |
| Число колонок | ТЗ.Колонки.Количество() |
| Переименовать | Кол.Имя = "ЦенаБезНДС" |
| Переставить | ТЗ.Колонки.Сдвинуть(Кол, -1) |
| Удалить | ТЗ.Колонки.Удалить(Кол) |
Объект колонки можно получить и напрямую по имени: ТЗ.Колонки.Цена. Но если колонки нет, такая запись упадёт с ошибкой, а Найти() спокойно вернёт Неопределено. Поэтому для проверки существования подходит только Найти():
Если ТЗ.Колонки.Найти("Цена") = Неопределено Тогда
ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
КонецЕсли;
Колонки можно добавлять и удалять, когда в таблице уже есть строки. Новая колонка в существующих строках заполнится значением по умолчанию для своего типа, у числа это 0.
Зачем задавать тип колонки
Тип в Добавить() необязателен, но лучше его указать:
- 📌 без типа
Итог()и сортировка ведут себя непредсказуемо на смешанных значениях; - 📌 если таблицу передают в запрос параметром и выбирают из неё во временную таблицу (
ИЗ &ТЗ КАК Т), колонка без типа вызывает ошибку; - 📌 типизированная колонка сама приводит значение: в колонку
Числострока не запишется как строка.
Проверить, что у двух таблиц одинаковые колонки
Перед ЗаполнитьЗначенияСвойств() или переносом строк из одной таблицы в другую полезно убедиться, что нужные колонки есть в приёмнике. Сравнение идёт по именам через Найти():
Недостающие = Новый Массив;
Для Каждого Кол Из Источник.Колонки Цикл
Если Приемник.Колонки.Найти(Кол.Имя) = Неопределено Тогда
Недостающие.Добавить(Кол.Имя);
КонецЕсли;
КонецЦикла;
Если Недостающие.Количество() > 0 Тогда
Сообщить("Нет колонок: " + СтрСоединить(Недостающие, ", "));
КонецЕсли;
Недостающие колонки можно сразу добавить в приёмник с тем же типом: Приемник.Колонки.Добавить(Кол.Имя, Кол.ТипЗначения, Кол.Заголовок). Так собирают сводную таблицу из нескольких источников с разной структурой.
Заголовок и имя — не одно и то же
Имя используется в коде, Заголовок — в интерфейсе: его видит пользователь в табличном поле и при выводе в табличный документ. Имя — идентификатор без пробелов, заголовок может быть любой строкой: "Сумма с НДС, руб.". Если заголовок не задан, платформа показывает имя колонки. Обращаться к колонке по заголовку нельзя: ни точка, ни скобки, ни Найти() его не учитывают.
Перебор колонок и строк в цикле
Классическая задача — пройти все ячейки таблицы, не зная её структуры. Внешний цикл по строкам, внутренний по колонкам:
Для Каждого Стр Из ТЗ Цикл
Для Каждого Кол Из ТЗ.Колонки Цикл
Сообщить(СтрШаблон("%1 = %2", Кол.Имя, Стр[Кол.Имя]));
КонецЦикла;
КонецЦикла;
То же по индексам — быстрее на больших таблицах, потому что не ищется имя:
ЧислоКолонок = ТЗ.Колонки.Количество();
Для Каждого Стр Из ТЗ Цикл
Для Индекс = 0 По ЧислоКолонок - 1 Цикл
Значение = Стр[Индекс];
КонецЦикла;
КонецЦикла;
Удаление колонок в цикле
Удалять колонки внутри Для Каждого по той же коллекции нельзя: элементы сдвигаются, и цикл пропускает соседние. Идите с конца, не пересчитывая границу от меняющейся коллекции:
Всего = ТЗ.Колонки.Количество();
Для Сч = 1 По Всего Цикл
Кол = ТЗ.Колонки[Всего - Сч];
Если СтрНачинаетсяС(Кол.Имя, "Служ") Тогда
ТЗ.Колонки.Удалить(Кол);
КонецЕсли;
КонецЦикла;
Цикл берёт колонки с индекса Всего - 1 до 0. Удаление очередной колонки не задевает те, что левее, поэтому ни одна не пропадает из проверки.
Колонки, имя которых известно только при выполнении
Динамические колонки появляются в отчётах «по месяцам», в загрузке из Excel и в выгрузке результата запроса. Имя колонки собирается строкой, а обращение идёт через скобки.
Колонки по периодам
Для Месяц = 1 По 12 Цикл
ИмяКолонки = "Месяц" + Формат(Месяц, "ЧЦ=2; ЧВН=; ЧГ=0");
ТЗ.Колонки.Добавить(ИмяКолонки, Новый ОписаниеТипов("Число"), Формат(Месяц, "ЧГ=0"));
КонецЦикла;
Стр[ИмяКолонки] = 1500; // запишет в "Месяц12"
Формат ЧВН= дополняет номер ведущим нулём: получаются Месяц01…Месяц12, и колонки сортируются по имени правильно. Третий параметр — заголовок, который увидит пользователь.
Колонки из результата запроса
После Результат.Выгрузить() имена колонок совпадают с псевдонимами полей запроса (КАК Сумма). Поле без псевдонима получает имя, которое платформа сформирует сама, и угадывать его неудобно. Давайте псевдоним каждому полю, к которому будете обращаться.
Массовое заполнение колонок из структуры
Если значения пришли структурой с теми же ключами, не нужно писать по строке на каждую колонку:
Данные = Новый Структура("Номенклатура, Количество, Сумма", "Тонер", 2, 4800);
ЗаполнитьЗначенияСвойств(ТЗ.Добавить(), Данные);
Ключи, которых нет среди колонок, просто игнорируются.
Работа с колонкой целиком
Часто нужна не одна ячейка, а вся колонка. Для этого у таблицы есть методы, которые принимают имя колонки строкой — цикл писать не нужно.
| Задача | Метод |
|---|---|
| Все значения колонки в массив | Массив = ТЗ.ВыгрузитьКолонку("Сумма") |
| Записать массив в колонку | ТЗ.ЗагрузитьКолонку(Массив, "Сумма") |
| Сумма по колонке | ТЗ.Итог("Сумма") |
| Одинаковое значение во все строки | ТЗ.ЗаполнитьЗначения(0, "Сумма") |
| Найти строки по значениям колонок | ТЗ.НайтиСтроки(Новый Структура("Номенклатура", "Тонер")) |
| Группировка с суммированием | ТЗ.Свернуть("Номенклатура", "Количество, Сумма") |
| Сортировка | ТЗ.Сортировать("Сумма Убыв") |
| Копия только нужных колонок | ТЗ.Скопировать(, "Номенклатура, Сумма") |
| Пустая таблица той же структуры | ТЗ.СкопироватьКолонки() |
Три приёма, которые сильно ускоряют код:
- Уникальные значения колонки.
Копия = ТЗ.Скопировать(, "Номенклатура"); Копия.Свернуть("Номенклатура");— затемКопия.ВыгрузитьКолонку(0). Исходная таблица не меняется. - Индекс по колонке поиска. Перед многократным
НайтиСтроки()добавьтеТЗ.Индексы.Добавить("Номенклатура"). На больших таблицах поиск перестаёт перебирать все строки. - Пересчёт колонки массивом. Выгрузить колонку, пересчитать массив, загрузить обратно через
ЗагрузитьКолонку(). Количество элементов массива должно совпадать с числом строк таблицы.
Свернуть() меняет саму таблицу: колонки, не попавшие ни в группировки, ни в суммы, удаляются. Если исходные данные ещё понадобятся, сворачивайте копию.
Таблица значений существует только на сервере и в толстом клиенте. В модуле формы на клиенте её нет: реквизит формы типа «Таблица значений» там представлен коллекцией данных формы. Чтобы работать с колонками через Колонки и методы выше, переведите реквизит в значение на сервере: РеквизитФормыВЗначение("Товары"), а после изменений — ЗначениеВРеквизитФормы(ТЗ, "Товары").
Ошибки при обращении к колонкам
Почти все сбои сводятся к тому, что колонки нет, имя собрано неверно или индекс вышел за границу.
ТЗ.Колонки.Найти("Сумма").Количество() - 1, а не из числа в коде.Кол.ТипЗначения и приведите значение явно.Число при создании.Ещё одна тихая ошибка — склейка числа со строкой при сборке имени. "Месяц" + Месяц на значении 1000 и больше даст неразрывный пробел-разделитель групп, и имя станет недопустимым. Числа в имена колонок всегда переводите через Формат(…, "ЧГ=0").