При работе с таблицами значений в платформе 1С:Предприятие разработчики часто сталкиваются с необходимостью динамического формирования колонок. Особенно популярным сценарием является вывод данных в виде кросс-таблицы, где колонками выступают конкретные даты (например, дни месяца при планировании или составлении графиков). В этой статье мы подробно разберем, почему возникает популярная ошибка «Неверное имя колонки», как правильно создавать такие колонки программно, и рассмотрим наиболее эффективные методы их заполнения данными из запроса.
Начнем с анализа типичной ошибки, с которой столкнулся автор темы. В его исходном коде была предпринята попытка добавить колонку следующим образом:
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ТабСотр.Колонки.Добавить(ВыборкаДетальныеЗаписи.поле1, Новый ОписаниеТипов("Дата"));
КонецЦикла;
Этот код приводит к аварийному завершению работы программы с ошибкой «Неверное имя колонки». Выясним причину такого поведения платформы. В методе Добавить() коллекции колонок таблицы значений первый параметр отвечает за внутреннее Имя колонки. К этому имени предъявляются жесткие требования, аналогичные правилам именования переменных (идентификаторов) в языке 1С:
В случае автора в переменной ВыборкаДетальныеЗаписи.поле1 содержалось либо строковое представление даты (например, "01.09.2026"), либо непосредственно значение типа Дата, которое при приведении к строке преобразуется в формат со специальными знаками препинания и пробелами (например, "01.09.2026 0:00:00"). Точки, пробелы и двоеточия недопустимы в идентификаторах, что и привело к ошибке платформы.
Для реализации задуманного алгоритма нам необходимо четко разделять два свойства колонки: Имя (используется разработчиком для обращения к колонке в коде) и Заголовок (отображается пользователю на форме). Рассмотрим подробнее, как решить эту задачу по шагам.
Шаг 1: Сформируем корректное имя колонки. Преобразуем дату в строку без спецсимволов и добавим текстовый префикс, чтобы имя гарантированно начиналось с буквы:
ИмяКолонки = "Дата_" + Формат(ВыборкаДетальныеЗаписи.поле1, "ДФ=yyyyMMdd");
// Если дата 06.08.2026, то имя будет "Дата_20260806" - это валидный идентификатор
Шаг 2: Сформируем понятный для пользователя заголовок. Здесь мы можем использовать любые символы, включая точки и пробелы:
ЗаголовокКолонки = Формат(ВыборкаДетальныеЗаписи.поле1, "ДЛФ=D");
// Пользователь увидит красивое представление: "06.08.2026"
Шаг 3: Добавим колонку в таблицу значений, указав имя, тип данных и заголовок:
ТабСотр.Колонки.Добавить(ИмяКолонки, Новый ОписаниеТипов("Дата"), ЗаголовокКолонки);
По умолчанию конструкция Новый ОписаниеТипов("Дата") выделяет память под хранение и даты, и времени одновременно. Если мы заранее знаем, что в колонках будут храниться только даты (без учета времени, то есть время всегда равно 00:00:00), хорошей практикой является использование объекта КвалификаторыДаты. Это помогает оптимизировать использование памяти и предотвращает потенциальные ошибки при последующем сравнении дат.
Давайте посмотрим на пример реализации такого подхода:
КвалификаторДаты = Новый КвалификаторыДаты(ЧастиДаты.Дата);
ОписаниеТипаДата = Новый ОписаниеТипов("Дата", , , КвалификаторДаты);
// Теперь используем оптимизированное описание типа при создании колонки:
ТабСотр.Колонки.Добавить(ИмяКолонки, ОписаниеТипаДата, ЗаголовокКолонки);
После успешного создания колонок нам необходимо заполнить таблицу строк данными. На форуме была предложена рабочая схема обхода выборки, однако в ней содержалась критическая опечатка, которую вовремя исправили участники обсуждения.
Разберем ошибку обращения к свойству таблицы вместо конкретной строки:
// НЕПРАВИЛЬНО: Попытка присвоить значение всей таблице
НоваяСтрока = ТабСотр.Добавить();
ТабСотр.ТвояКолонкаСДатой = ВыборкаДетальныеЗаписи.поле1;
В этом случае платформа выдаст ошибку, так как у самого объекта ТаблицаЗначений нет свойства с именем вашей колонки. Значение нужно присваивать конкретной строке, которую мы только что добавили. Правильный вариант выглядит следующим образом:
// ПРАВИЛЬНО: Присвоение значения конкретной строке
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
НоваяСтрока = ТабСотр.Добавить();
НоваяСтрока.ТвояКолонкаСДатой = ВыборкаДетальныеЗаписи.поле1;
КонецЦикла;
Если имя колонки было создано нами динамически (например, "Дата_20260806"), то прямое обращение через точку в коде использовать нельзя. В таких ситуациях мы обращаемся к свойству строки через квадратные скобки по строковому имени колонки:
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
НоваяСтрока = ТабСотр.Добавить();
ИмяКолонки = "Дата_" + Формат(ВыборкаДетальныеЗаписи.поле1, "ДФ=yyyyMMdd");
НоваяСтрока[ИмяКолонки] = ВыборкаДетальныеЗаписи.поле1;
КонецЦикла;
Если имена полей в вашей выборке запроса (или структуры) частично или полностью совпадают с именами колонок таблицы значений, отличным решением будет использование встроенной функции ЗаполнитьЗначенияСвойств. Это делает код чистым, лаконичным и избавляет от необходимости писать ручные присвоения для каждого поля.
Проанализируем пример использования этого метода:
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
НоваяСтрока = ТабСотр.Добавить();
// Платформа автоматически сопоставит имена полей выборки и колонок строки и перенесет данные
ЗаполнитьЗначенияСвойств(НоваяСтрока, ВыборкаДетальныеЗаписи);
КонецЦикла;
В завершение рассмотрим альтернативный подход, который значительно превосходит построчный обход выборки в цикле по производительности. Если вам не требуется сложная логика трансформации данных на клиенте или сервере в процессе обхода, вы можете выгрузить весь результат запроса в таблицу значений одной командой:
// Результат запроса выгружается напрямую в Таблицу Значений
ТабСотр = Запрос.Выполнить().Выгрузить();
При использовании метода Выгрузить() платформа 1С на уровне ядра мгновенно создает таблицу значений, автоматически генерирует все необходимые колонки, корректно сопоставляет типы данных из схемы запроса и заполняет строки. Этот способ работает в разы быстрее ручного цикла Пока Выборка.Следующий(), особенно на больших массивах данных.