Удаление строк в 1С 8.3: табличный документ, табличные части, формы и СКД
Содержание
Строку в табличной части документа удаляют кнопкой Удалить над таблицей или клавишей Delete. В табличном документе (печатная форма, отчёт, файл MXL) строку выделяют по номеру слева и выбирают Удалить в контекстном меню. В коде — метод Удалить() у коллекции или УдалитьОбласть() у табличного документа, причём из коллекции удаляют обратным циклом.
Ниже всё, что нужно и пользователю, и программисту 1С: как удалять строки руками и скриптами, почему цикл «пропускает» строки, как убрать лишнее из отчёта СКД и что меняется в тонком и веб-клиенте. Механизм один для всех типовых конфигураций на платформе 8.3 — БП 3.0, ЗУП 3.1, УТ 11.
Как удалить строки в табличном документе и табличной части вручную
Сначала определите, что перед вами. От этого зависит способ.
| Где строка | Как выглядит | Как удалить |
|---|---|---|
| Табличная часть документа (товары, услуги, сотрудники) | Таблица с колонками внутри формы документа | Выделить строку → кнопка Удалить или Delete |
| Табличный документ | Сетка как в Excel, с номерами строк слева | Выделить строки по номерам → контекстное меню → Удалить |
| Список справочника или документов | Перечень объектов базы | Delete ставит пометку на удаление, сам объект остаётся |
Табличная часть документа
- Щёлкните по строке. Чтобы выделить несколько подряд, держите
Shift, вразбивку —Ctrl. - Нажмите
Deleteили кнопкуУдалитьв командной панели таблицы (часто спрятана в менюЕщё). - Запишите документ. Пока он не записан, закрытие без сохранения вернёт строки на место.
Удалить все строки разом можно командой Очистить, если она есть в меню Ещё этой таблицы. Если её нет — выделите первую строку, затем последнюю с Shift и нажмите Delete.
Табличный документ
Здесь клавиша Delete строку не удаляет, а только стирает содержимое ячеек. Пустая строка остаётся в макете и в печати.
Чтобы убрать строку целиком:
- Щёлкните по номеру строки в левой серой полосе — выделится вся строка. Для диапазона протяните мышью по номерам.
- Правой кнопкой по выделению →
Удалить. - Строки ниже сдвинутся вверх.
Удаление в сформированном отчёте не меняет данные в базе. Это правка картинки: после повторного формирования строки вернутся. Если строка в отчёте лишняя, её убирают отбором (см. раздел про СКД).
Программное удаление строк из коллекций
В коде 1С строки удаляют методом Удалить(). Он есть у табличной части объекта, у таблицы значений, у дерева значений (у коллекции строк) и у массива. Параметр — сама строка или её индекс.
// Удалить первую строку табличной части
ДокументОбъект.Товары.Удалить(0);
// Удалить конкретную строку
ДокументОбъект.Товары.Удалить(СтрокаТЧ);
// Удалить все строки
ДокументОбъект.Товары.Очистить();
Почему прямой цикл пропускает строки
Классическая ошибка — удалять внутри Для Каждого или прямого цикла по индексам. После удаления строки с индексом 2 следующая строка встаёт на её место, а цикл уже переходит к индексу 3. Одна строка остаётся непроверенной, а в конце цикл может выйти за границу коллекции.
Правильно — идти с конца, заранее запомнив количество строк:
ВсегоСтрок = ДокументОбъект.Товары.Количество();
Для Сч = 1 По ВсегоСтрок Цикл
Индекс = ВсегоСтрок - Сч;
СтрокаТЧ = ДокументОбъект.Товары[Индекс];
Если СтрокаТЧ.Количество = 0 Тогда
ДокументОбъект.Товары.Удалить(Индекс);
КонецЕсли;
КонецЦикла;
Проверим на пяти строках: первый проход берёт индекс 4, второй — 3, последний — 0. Удаление строки с конца не сдвигает строки, которые ещё предстоит проверить.
Удаление по условию через НайтиСтроки
Если условие — равенство значений, обратный цикл не нужен. НайтиСтроки() возвращает отдельный массив строк, и удаление из коллекции этот массив не портит:
Отбор = Новый Структура("Номенклатура", УдаляемаяНоменклатура);
НайденныеСтроки = ДокументОбъект.Товары.НайтиСтроки(Отбор);
Для Каждого СтрокаТЧ Из НайденныеСтроки Цикл
ДокументОбъект.Товары.Удалить(СтрокаТЧ);
КонецЦикла;
Для таблицы значений есть ещё короче путь: не удалять лишнее, а скопировать нужное. ТЗ.Скопировать(Отбор) вернёт новую таблицу только с подходящими строками.
Записи регистров
У набора записей регистра строки тоже удаляются методом Удалить(), но изменения попадут в базу только после Записать(). Чтобы стереть все записи по отбору, достаточно установить отбор и записать пустой набор:
Набор = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
Набор.Отбор.Валюта.Установить(Валюта);
Набор.Отбор.Период.Установить(ДатаКурса);
Набор.Записать(); // набор пуст — записи по отбору удалены
Так стирают реальные данные. Перед запуском на рабочей базе проверьте отбор на копии.
Как удалить строки из табличного документа программно
Сформированный табличный документ правят методом УдалитьОбласть(). Первый параметр — область, второй — направление сдвига оставшихся ячеек.
// Удалить строки с 5 по 7 и сдвинуть нижние вверх
Область = ТабДок.Область("R5:R7");
ТабДок.УдалитьОбласть(Область, ТипСмещенияТабличногоДокумента.ПоВертикали);
Без второго параметра платформа сама выбирает сдвиг, и результат не всегда очевиден. Указывайте его явно.
Удалить пустые строки отчёта
Задача из практики: выгрузили табличный документ, во второй колонке встречаются пустые строки, их нужно убрать перед сохранением в файл. Логика та же, что с коллекцией: идём снизу вверх.
Высота = ТабДок.ВысотаТаблицы;
Для Сч = 1 По Высота Цикл
НомерСтроки = Высота - Сч + 1;
АдресЯчейки = СтрШаблон("R%1C2", Формат(НомерСтроки, "ЧГ=0"));
Если ПустаяСтрока(ТабДок.Область(АдресЯчейки).Текст) Тогда
ТабДок.УдалитьОбласть(ТабДок.Область(СтрШаблон("R%1", Формат(НомерСтроки, "ЧГ=0"))),
ТипСмещенияТабличногоДокумента.ПоВертикали);
КонецЕсли;
КонецЦикла;
Формат(..., "ЧГ=0") убирает разделитель групп разрядов: без него номер 1000 превратится в «1 000», и адрес области станет неверным.
Объединённые ячейки. Если удаляемая строка входит в объединённую область, оформление соседних строк может «поехать». Проверьте результат на документе с шапкой и итогами, а не только на простой таблице.
Для макета, который выводится по шаблону, удалять строки после вывода обычно незачем. Проще не выводить ненужную область: условие Если ... Тогда ТабДок.Вывести(ОбластьСтроки) в цикле вывода.
Лишние строки в запросе и отчёте на СКД
В языке запросов 1С нет команды удаления данных. Запрос только читает. Поэтому «удалить строки» в запросе или СКД означает не выводить их.
В конструкторе запросов
- 🔹 Лишние записи отсекает условие на вкладке
Условия— оно попадёт в секциюГДЕ. - 🔹 Дубли убирает флажок
Без повторяющихсяна вкладкеДополнительно(ВЫБРАТЬ РАЗЛИЧНЫЕ) или группировка. - 🔹 Строки с нулевыми итогами после группировки отсекает условие в секции
ИМЕЮЩИЕ. - 🔹 Временную таблицу, которая больше не нужна в пакете, уничтожают запросом
УНИЧТОЖИТЬ ИмяТаблицы— это освобождает память на сервере, но в базе ничего не стирает.
Удалить таблицу или поле из самого запроса в конструкторе — это правка текста, а не данных: выделите элемент в списке и нажмите Удалить в командной панели над ним.
В отчёте на СКД
| Что лишнее | Где убрать |
|---|---|
| Строки по значению поля | Настройки → вкладка Отбор |
| Детальные записи под группировкой | В структуре настроек удалить элемент Детальные записи |
| Строка общих итогов | Другие настройки → параметр расположения общих итогов → Нет |
| Пустые или нулевые строки | Отбор Сумма → Заполнено или условие в запросе набора данных |
Пользователю типового отчёта в БП 3.0 или УТ 11 доступ к схеме не нужен. Кнопка Настройки в форме отчёта открывает отборы, и строки отсекаются там без программиста.
Если строки нужно убрать по сложному правилу, которое не выразить отбором, программист обрабатывает событие ПриКомпоновкеРезультата в модуле отчёта. Там можно вывести результат в таблицу значений через процессор вывода, удалить строки кодом из предыдущего раздела и уже потом сформировать табличный документ.
Удаление строк и элементов в управляемой форме
На управляемой форме табличная часть доступна как Объект.Товары — это коллекция данных формы. Метод Удалить() у неё работает и на клиенте, и на сервере.
Удалить выделенные строки
Свойство ВыделенныеСтроки у элемента таблицы возвращает не сами строки, а их идентификаторы. Строку по идентификатору находит НайтиПоИдентификатору(). Идентификаторы сначала копируем в отдельный массив — так цикл не зависит от выделения, которое меняется при удалении.
&НаКлиенте
Процедура УдалитьВыделенные(Команда)
Выделенные = Новый Массив;
Для Каждого Идентификатор Из Элементы.Товары.ВыделенныеСтроки Цикл
Выделенные.Добавить(Идентификатор);
КонецЦикла;
Для Каждого Идентификатор Из Выделенные Цикл
СтрокаТЧ = Объект.Товары.НайтиПоИдентификатору(Идентификатор);
Если СтрокаТЧ <> Неопределено Тогда
Объект.Товары.Удалить(СтрокаТЧ);
КонецЕсли;
КонецЦикла;
Модифицированность = Истина;
КонецПроцедуры
Текущую строку дают Элементы.Товары.ТекущиеДанные (данные) и Элементы.Товары.ТекущаяСтрока (идентификатор).
Запретить или проверить удаление
- 🔒 Полный запрет на добавление и удаление строк — свойство элемента таблицы
ИзменятьСоставСтрок=Ложь. - 🛑 Условный запрет — обработчик события
ПередУдалениему элемента таблицы: установитеОтказ = Истина, если строку трогать нельзя (например, она заполнена автоматически). - 🔁 Пересчёт итогов после удаления — в обработчике
ПослеУдаления.
Элементы списка, а не строки
В динамическом списке справочника или журнала строка — это объект базы. Delete в таком списке ставит пометку на удаление, а не стирает объект. Окончательно помеченные объекты удаляет обработка Удаление помеченных объектов: в БП 3.0 — Администрирование → Обслуживание. Перед удалением она проверяет, не ссылаются ли на объект другие данные.
В коде это два разных действия:
Объект = Ссылка.ПолучитьОбъект();
Объект.УстановитьПометкуУдаления(Истина); // мягко, обратимо
// Объект.Удалить(); // сразу и без проверки ссылок
Метод Удалить() у объекта не проверяет ссылки. Документы, где использовался удалённый элемент, получат «битые» ссылки вида <Объект не найден>. Если без прямого удаления не обойтись, сначала проверьте ссылки через НайтиПоСсылкам().
Права тоже разные. Для пометки достаточно права на изменение, для программного удаления нужно право Удаление, для удаления из списка руками — Интерактивное удаление. В типовых ролях последнее обычно выключено, и это правильно.
Ошибки при удалении строк и защита от сбоев
Массовое удаление в рабочей базе оборачивайте в транзакцию и перехват ошибок. Тогда сбой посередине не оставит половину данных удалённой:
НачатьТранзакцию();
Попытка
Для Каждого Ссылка Из СписокНаУдаление Цикл
Ссылка.ПолучитьОбъект().УстановитьПометкуУдаления(Истина);
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ЗаписьЖурналаРегистрации("Удаление строк", УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение;
КонецПопытки;
Перед любым массовым удалением сделайте копию базы и прогоните код на ней. Восстановить строки, удалённые из записанного объекта, можно только из резервной копии или из истории версий, если она включена.
Тонкий клиент и веб-клиент: где выполнять удаление
В тонком и веб-клиенте код формы делится на клиентский и серверный. От этого зависит, что и где можно удалять.
| Что удаляем | На клиенте | На сервере |
|---|---|---|
Строки Объект.Товары в форме | Да | Да |
| Строки таблицы значений | Нет, на клиенте её нет | Да |
| Объект справочника или документа | Нет | Да |
| Области табличного документа в поле формы | Да | Да |
Практические следствия:
- 🐢 Не вызывайте сервер на каждую строку. Удаление 500 строк по одной через
&НаСервере— это 500 обращений к серверу, в веб-клиенте это заметно медленнее. Передайте массив идентификаторов в одну серверную процедуру. - 🌐 В веб-клиенте часть сочетаний клавиш перехватывает браузер. Если горячая клавиша не срабатывает, используйте кнопку
Удалитьили контекстное меню таблицы. - 📄 Табличный документ в поле формы редактируется в веб-клиенте так же, как в тонком: выделение по номерам строк и
Удалитьв контекстном меню. - 🔄 После удаления на сервере форма получает данные заново. Текущая строка сбрасывается — если нужно вернуть курсор, запомните идентификатор соседней строки заранее.