В процессе разработки и сопровождения конфигураций на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с загадочным поведением интерфейса: стандартные кнопки перемещения строк в табличной части (синие стрелочки "Вверх" и "Вниз") внезапно становятся недоступными (серыми). При этом права у пользователя есть, флаги ИзменятьСоставСтрок и ИзменятьПорядокСтрок установлены, а очистка настроек помогает лишь на короткое время. Рассмотрим подробно, почему это происходит и как решить задачу как стандартными, так и программными методами.
Прежде чем приступать к написанию кода, проанализируем ситуацию. Платформа 1С автоматически управляет доступностью стандартных команд на основе множества факторов. Если кнопки стали неактивны, значит, нарушено одно из условий логики платформы.
ПереместитьВверх и ПереместитьВниз работают только в том случае, если строки отображаются в их "естественном" порядке (по индексу в коллекции). Как только включена сортировка по полю, порядок строк перестает быть физическим, и перемещение становится логически невозможным.ТолькоПросмотр установлено в Ложь, кнопки могут заблокироваться, если таблица находится внутри группы (или нескольких вложенных групп), у которой включен флаг ТолькоПросмотр. Свойства родителя наследуются элементами управления, что визуально отключает команды изменения состава и порядка строк.Если стандартные механизмы не удается вернуть в рабочее состояние (например, из-за специфических требований бизнес-логики по фильтрации строк), оптимальным решением будет создание кастомных команд. Рассмотрим, как реализовать алгоритм перемещения строк программно, сохранив при этом корректную работу с выделенными строками и индексами.
Для реализации нам потребуется создать две команды формы (например, СтрелкаВверх и СтрелкаВниз), разместить их на командной панели таблицы и назначить им обработчики на клиенте.
Посмотрим на пример кода для смещения строк вниз. Важным нюансом здесь является обработка массива выделенных строк и их предварительная сортировка, чтобы индексы не "поплыли" во время перемещения.
&НаКлиенте
Процедура СтрелкаВниз(Команда)
// Получаем массив идентификаторов выделенных строк
МассивСтрок = Элементы.Товары.ВыделенныеСтроки;
СписокНомеровСтрокКПеремещению = Новый СписокЗначений;
// Сначала соберем реальные номера строк, чтобы понимать их позицию
Для Каждого ИД ИЗ МассивСтрок Цикл
СтрокаТЧ = Объект.Товары.НайтиПоИдентификатору(ИД);
// Проверяем, не является ли строка последней
Если СтрокаТЧ.НомерСтроки = Объект.Товары.Количество() Тогда
Возврат; // Если достигнут низ, прекращаем операцию для всей группы
Иначе
СписокНомеровСтрокКПеремещению.Добавить(СтрокаТЧ.НомерСтроки);
КонецЕсли;
КонецЦикла;
// Сортируем по убыванию!
// Это критично: при движении вниз нужно сначала двигать нижние строки,
// чтобы они не мешали верхним.
СписокНомеровСтрокКПеремещению.СортироватьПоЗначению(НаправлениеСортировки.Убыв);
Для Каждого СтрокаСписка ИЗ СписокНомеровСтрокКПеремещению Цикл
// Метод Сдвинуть использует индекс (номер строки - 1)
Объект.Товары.Сдвинуть(СтрокаСписка.Значение - 1, 1);
КонецЦикла;
ЭтаФорма.Модифицированность = Истина;
КонецПроцедуры
Аналогичным образом реализуем движение вверх. Здесь логика сортировки списка будет обратной.
&НаКлиенте
Процедура СтрелкаНаверх(Команда)
МассивСтрок = Элементы.Товары.ВыделенныеСтроки;
СписокНомеровСтрокКПеремещению = Новый СписокЗначений;
Для Каждого ИД ИЗ МассивСтрок Цикл
СтрокаТЧ = Объект.Товары.НайтиПоИдентификатору(ИД);
// Если хотя бы одна строка уже в самом верху (НомерСтроки = 1), прерываем
Если СтрокаТЧ.НомерСтроки = 1 Тогда
Возврат;
Иначе
СписокНомеровСтрокКПеремещению.Добавить(СтрокаТЧ.НомерСтроки);
КонецЕсли;
КонецЦикла;
// Сортируем по возрастанию: сначала двигаем самую верхнюю из выделенных
СписокНомеровСтрокКПеремещению.СортироватьПоЗначению(НаправлениеСортировки.Возр);
Для Каждого СтрокаСписка ИЗ СписокНомеровСтрокКПеремещению Цикл
Объект.Товары.Сдвинуть(СтрокаСписка.Значение - 1, -1);
КонецЦикла;
ЭтаФорма.Модифицированность = Истина;
КонецПроцедуры
Чтобы кнопки всегда вели себя предсказуемо, стоит обратить внимание на метод ОбновитьОтображениеДанных(). Иногда после программного изменения коллекции строк (например, загрузки из Excel или распределения сумм) визуальное состояние кнопок "залипает". Вызов ЭтаФорма.ОбновитьОтображениеДанных() принудительно заставляет платформу пересчитать доступность всех связанных элементов управления.
Также проанализируем использование функциональных опций. Если возможность редактирования порядка строк в документе зависит от какой-либо настройки константы, платформа может отключать команды на уровне ядра. Проверьте, не привязана ли видимость или доступность командной панели к функциональной опции, которая может быть выключена для текущего пользователя.
В заключение отметим, что если вы решили использовать кастомные кнопки, не забудьте отключить стандартные кнопки перемещения в свойствах командной панели таблицы (снимите галочку "Автозаполнение" или удалите конкретные кнопки из состава), чтобы не путать пользователя дублирующимися элементами, один из которых может быть недоступен.