Выделение всех строк сразу: от Ctrl+A до массива ВыделенныеСтроки

· 9 мин

Содержание

Чтобы выделить все строки в 1С, щёлкните по любой строке списка или табличной части и нажмите Ctrl+A. Программно то же самое делают через свойство ВыделенныеСтроки элемента формы: очищают его и добавляют идентификаторы всех строк в цикле.

Частое заблуждение — искать в языке метод вроде «ВыделитьВсе» или «НайтиВсе». Таких методов у таблиц и массивов нет. Выделение — это массив идентификаторов в элементе формы, а поиск группы строк делает НайтиСтроки. Ниже — оба уровня: что делает пользователь мышью и клавиатурой и как то же самое решает программист в управляемой форме платформы 8.3.

Как выделить все строки мышью и клавиатурой

Работает одинаково в списках справочников и документов, в табличных частях и в журналах. Интерфейс «Такси», платформа 8.3.

ДействиеЧто выделяется
Ctrl+Aвсе строки таблицы, где стоит курсор
щелчок, затем Shift+щелчокдиапазон между двумя строками
Ctrl+щелчокдобавить или убрать одну строку из выделения
Shift+↓ / Shift+↑расширить выделение на строку вниз или вверх
щелчок без клавишсбросить выделение до одной строки

Что можно сделать с выделенными строками в типовых конфигурациях (БП 3.0, ЗУП 3.1, УТ 11):

  • ✅ Del в списке — пометить на удаление все выделенные объекты разом, программа спросит подтверждение.
  • ✅ кнопка Провести в списке документов — провести все выделенные документы.
  • ✅ Ещё → Изменить выделенные — групповая смена реквизита, например вида номенклатуры или ставки НДС у сотни карточек.
  • ✅ Ещё → Вывести список — выгрузить строки в табличный документ, а оттуда сохранить в Excel.

В табличном документе отчёта Ctrl+A выделяет все ячейки. Если выделить ячейки с числами, типовые отчёты показывают их сумму в шапке формы — удобно для быстрой сверки без калькулятора.

Почему Ctrl+A не срабатывает

  • 🔸 Курсор стоит внутри ячейки в режиме редактирования. Тогда Ctrl+A выделит текст в поле, а не строки. Нажмите Esc и повторите.
  • 🔸 У таблицы на форме включён режим одиночного выделения. Пользователь его не поменяет, это настройка разработчика (см. следующий раздел).
  • 🔸 На таблице включён отбор. Выделяются только видимые строки, скрытые отбором в выделение не попадают.

Режим выделения и массив ВыделенныеСтроки в табличной части

Для программиста выделение в управляемой форме — это свойство элемента ТаблицаФормы. Ключевых свойств два:

  • 🔹 РежимВыделения — РежимВыделенияТаблицы.Множественный или РежимВыделенияТаблицы.Одиночный. В одиночном режиме выделить несколько строк нельзя ни мышью, ни кодом.
  • 🔹 ВыделенныеСтроки — массив выделенных строк. Для табличной части и таблицы значений на форме в нём лежат идентификаторы строк (число), а не сами строки.

Режим проще задать в конфигураторе, в палитре свойств элемента таблицы. Если нужно переключать на лету:

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	Элементы.Товары.РежимВыделения = РежимВыделенияТаблицы.Множественный;
КонецПроцедуры

Кнопка «Выделить все строки» в табличной части

Добавьте команду формы и вынесите её на командную панель таблицы. Обработчик:

&НаКлиенте
Процедура ВыделитьВсеСтроки(Команда)
	
	Выделенные = Элементы.Товары.ВыделенныеСтроки;
	Выделенные.Очистить();
	
	Для Каждого СтрокаТЧ Из Объект.Товары Цикл
		Выделенные.Добавить(СтрокаТЧ.ПолучитьИдентификатор());
	КонецЦикла;
	
КонецПроцедуры

Снять выделение — одна строка: Элементы.Товары.ВыделенныеСтроки.Очистить();. Текущая строка при этом останется, её задаёт отдельное свойство ТекущаяСтрока.

Как обработать выделенные строки

По идентификатору строку получают методом НайтиПоИдентификатору. Пример: поставить скидку 5% на все выделенные позиции.

&НаКлиенте
Процедура СкидкаНаВыделенные(Команда)
	
	Для Каждого Ид Из Элементы.Товары.ВыделенныеСтроки Цикл
		СтрокаТЧ = Объект.Товары.НайтиПоИдентификатору(Ид);
		Если СтрокаТЧ = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		СтрокаТЧ.ПроцентСкидки = 5;
	КонецЦикла;
	
КонецПроцедуры

Имена Товары и ПроцентСкидки замените на реквизиты своей формы. Пересчёт сумм после изменения процента — отдельная процедура, её вызывают так же, как при ручном вводе.

Выделение в динамическом списке формы

В форме списка справочника или документа таблица выводит динамический список. Здесь Элементы.Список.ВыделенныеСтроки содержит не идентификаторы, а ключи строк. Для списка с основной таблицей это ссылки: СправочникСсылка.Номенклатура, ДокументСсылка.РеализацияТоваровУслуг и т. п.

Отличия от табличной части:

  • 🔸 Строк в памяти клиента нет: список подчитывает их порциями при прокрутке. Перебрать «все строки» циклом на клиенте нельзя.
  • 🔸 Если пользователь включил группировку, в массиве могут оказаться строки группировок. Их тип — СтрокаГруппировкиДинамическогоСписка, такие элементы пропускайте.
  • 🔸 Выделить конкретную запись кодом можно: Элементы.Список.ВыделенныеСтроки.Добавить(Ссылка). Но «выделить всё» программно для списка на десятки тысяч записей бессмысленно — проще сразу обработать данные запросом.

Типовой обработчик команды формы списка: собрать ссылки на клиенте и одним вызовом отдать на сервер.

&НаКлиенте
Процедура ОбработатьВыделенные(Команда)
	
	Ссылки = Новый Массив;
	Для Каждого Ключ Из Элементы.Список.ВыделенныеСтроки Цикл
		Если ТипЗнч(Ключ) = Тип("СтрокаГруппировкиДинамическогоСписка") Тогда
			Продолжить;
		КонецЕсли;
		Ссылки.Добавить(Ключ);
	КонецЦикла;
	
	Если Ссылки.Количество() = 0 Тогда
		ПоказатьПредупреждение(, "Выделите строки в списке.");
		Возврат;
	КонецЕсли;
	
	ОбработатьНаСервере(Ссылки);
	Элементы.Список.Обновить();
	
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ОбработатьНаСервере(Ссылки)
	Для Каждого Ссылка Из Ссылки Цикл
		Объект = Ссылка.ПолучитьОбъект();
		// изменение реквизитов объекта
		Объект.Записать();
	КонецЦикла;
КонецПроцедуры

Команда с параметром — выделение без кода формы

Если команда живёт в общих командах или в командах объекта, код формы не нужен. В свойствах команды задайте тип параметра (ссылку на нужный объект) и РежимИспользованияПараметра = Множественный. Тогда в ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды) придёт массив ссылок на все выделенные строки списка. Так устроены многие команды из меню Создать на основании и Печать в типовых.

Найти и выделить все подходящие строки: НайтиСтроки и ОтборСтрок

Задача «выделить все строки, где номенклатура такая-то» решается в два шага: найти строки, затем занести их идентификаторы в выделение.

НайтиСтроки принимает структуру отбора и возвращает массив строк, у которых все перечисленные поля совпадают. Метод есть у таблицы значений, у табличной части объекта и у коллекции данных формы, то есть у Объект.Товары на клиенте.

&НаКлиенте
Процедура ВыделитьПоТовару(Номенклатура)
	
	Отбор = Новый Структура("Номенклатура", Номенклатура);
	Найденные = Объект.Товары.НайтиСтроки(Отбор);
	
	Выделенные = Элементы.Товары.ВыделенныеСтроки;
	Выделенные.Очистить();
	Для Каждого СтрокаТЧ Из Найденные Цикл
		Выделенные.Добавить(СтрокаТЧ.ПолучитьИдентификатор());
	КонецЦикла;
	
	Если Найденные.Количество() > 0 Тогда
		Элементы.Товары.ТекущаяСтрока = Найденные[0].ПолучитьИдентификатор();
	КонецЕсли;
	
КонецПроцедуры

Ограничение НайтиСтроки: только точное равенство. Условия «больше», «содержит», «пусто или ноль» придётся проверять в цикле вручную.

Скрыть всё лишнее вместо выделения

Иногда пользователю удобнее видеть только нужные строки, а не искать подсвеченные среди сотни. Для этого у таблицы формы есть ОтборСтрок:

Элементы.Товары.ОтборСтрок = Новый ФиксированнаяСтруктура("Номенклатура", Номенклатура);
// вернуть все строки:
Элементы.Товары.ОтборСтрок = Неопределено;

Отбор меняет только отображение. Цикл Для Каждого СтрокаТЧ Из Объект.Товары по-прежнему пройдёт по всем строкам, включая скрытые. Если обработка должна касаться только видимых, перебирайте ВыделенныеСтроки или повторите условие отбора в цикле.

Где нужно выделить или обработать все строки?

Все элементы массива, списка значений и таблицы значений

Вне формы понятия «выделение» нет. Есть задача получить все подходящие элементы коллекции. Инструменты разные:

КоллекцияЧем найти все подходящиеЧто вернёт
Массивцикл с условием; Найти() ищет только первое вхождениеиндекс или Неопределено
СписокЗначенийцикл; для отметки всех — ЗаполнитьПометки(Истина)меняет пометки на месте
ТаблицаЗначенийНайтиСтроки(Структура)массив строк
ТаблицаЗначенийСкопировать(Структура)новая таблица только с подходящими строками
любая колонкаВыгрузитьКолонку("Имя")массив значений колонки

Все вхождения значения в массив:

Индексы = Новый Массив;
Для Сч = 0 По Массив.ВГраница() Цикл
	Если Массив[Сч] = Искомое Тогда
		Индексы.Добавить(Сч);
	КонецЕсли;
КонецЦикла;

Если у массива 0 элементов, ВГраница() вернёт -1, и цикл не выполнится ни разу — отдельная проверка не нужна.

Связка таблицы значений с запросом — частый приём: выгрузить колонку ссылок и передать её параметром.

Ссылки = ТаблицаТоваров.ВыгрузитьКолонку("Номенклатура");

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|	Номенклатура.Ссылка,
|	Номенклатура.Артикул
|ИЗ
|	Справочник.Номенклатура КАК Номенклатура
|ГДЕ
|	Номенклатура.Ссылка В (&Ссылки)";
Запрос.УстановитьПараметр("Ссылки", Ссылки);
Результат = Запрос.Выполнить().Выгрузить();

Дубли в массиве ссылок запросу не мешают: условие В их схлопнет.

Колонка «Пометка» вместо выделения

Выделение хрупкое: один щелчок без Ctrl — и пользователь потерял полсотни отмеченных строк. Для обработок, где человек долго отбирает позиции, добавьте в таблицу булеву колонку Пометка с флажком и две команды: «Отметить все» и «Снять отметки».

&НаКлиенте
Процедура ОтметитьВсе(Команда)
	Для Каждого СтрокаТЧ Из Объект.Товары Цикл
		СтрокаТЧ.Пометка = Истина;
	КонецЦикла;
КонецПроцедуры

Флажки сохраняются в данных формы, их видно и после перерисовки, а отобрать отмеченные можно тем же НайтиСтроки(Новый Структура("Пометка", Истина)).

Массовые операции над выделенными строками: скорость и ловушки

Выделить тысячу строк просто. Обработать их так, чтобы форма не зависла, — отдельная задача.

Один вызов сервера вместо тысячи

Серверная процедура, вызванная внутри цикла на клиенте, — главная причина тормозов. Каждый вызов — это обмен с сервером, а в веб-клиенте и через интернет ещё и сетевая задержка. Соберите массив на клиенте и передайте его целиком одним вызовом, как в примере с динамическим списком. Используйте &НаСервереБезКонтекста, если данные формы серверу не нужны: тогда на сервер не уходит вся форма.

Удаление выделенных строк

Удалять строки прямо в цикле по ВыделенныеСтроки нельзя. При удалении строки платформа убирает её идентификатор из выделения, массив меняется на ходу, и часть строк пропускается. Сначала скопируйте идентификаторы, потом удаляйте:

&НаКлиенте
Процедура УдалитьВыделенные(Команда)
	
	Иды = Новый Массив;
	Для Каждого Ид Из Элементы.Товары.ВыделенныеСтроки Цикл
		Иды.Добавить(Ид);
	КонецЦикла;
	
	Для Каждого Ид Из Иды Цикл
		СтрокаТЧ = Объект.Товары.НайтиПоИдентификатору(Ид);
		Если СтрокаТЧ <> Неопределено Тогда
			Объект.Товары.Удалить(СтрокаТЧ);
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

С массивами та же история: удаляя элементы по индексу, идите с конца — Для Сч = 1 По Массив.Количество() Цикл, а индекс берите как Массив.Количество() - Сч. Тогда сдвиг оставшихся элементов не ломает перебор.

Запись сотен объектов

  • ⚠️ Запись каждого объекта — отдельная транзакция с проверками, подписками и движениями. Тысяча документов — это минуты, а не секунды. Предупредите пользователя или запускайте обработку фоновым заданием.
  • ⚠️ Оборачивать всю пачку в одну транзакцию рискованно: ошибка на 999-м объекте откатит все предыдущие, а таблицы будут заблокированы до конца. Обычно пишут по одному объекту с перехватом ошибки в Попытка … Исключение и собирают список неудачных.
  • ⚠️ Перепроведение выделенных документов в закрытом периоде меняет движения. Перед массовым перепроведением или изменением реквизитов сделайте резервную копию базы.

Чек: всё ли выделено

Пользователи часто уверены, что Ctrl+A в форме списка зацепил вообще все записи справочника. На деле в выделение попадает то, что проходит текущий отбор и поиск в списке. Покажите перед запуском обработки число строк:

Количество = Элементы.Список.ВыделенныеСтроки.Количество();
ТекстВопроса = СтрШаблон("Будет обработано строк: %1. Продолжить?", Формат(Количество, "ЧГ=0"));

Вопрос задают через ПоказатьВопрос с обработчиком оповещения — модальные окна в управляемых формах по умолчанию запрещены.

Частые вопросы

Сохраняется ли выделение после обновления списка?
В динамическом списке после Обновить() платформа старается сохранить выделение по ключам. Если запись исчезла из-за отбора, она выпадет из выделения. Для надёжности храните отмеченные ссылки в реквизите формы или используйте колонку с флажком.
Можно ли узнать выделенные строки в серверной процедуре?
Надёжнее собрать массив на клиенте и передать его параметром. Так сервер получает только ссылки или значения, а не всю форму, и код работает и при вызове без контекста.
Чем текущая строка отличается от выделенных?
Текущая строка одна — та, где стоит курсор, её данные дают Элементы.Товары.ТекущиеДанные. Выделенных может быть много. Команда, рассчитанная на одну строку, обычно берёт текущую.
Как выделить все строки, кроме нескольких?
Нажмите Ctrl+A, затем Ctrl+щелчком снимите выделение с лишних строк. В коде — заполните ВыделенныеСтроки в цикле и пропустите строки по условию.
Почему «Изменить выделенные» не видит часть реквизитов?
Групповое изменение показывает только реквизиты, которые разрешено менять массово и на которые у пользователя есть права. Остальные меняют в карточке или обработкой.