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