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