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