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