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