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