Не так давно к автору обратились со следующей проблемой. На форму была выведена таблица, связанная с табличной частью документа. Разработчики заботливо добавили кнопки со стрелками вверх-вниз для перемещения по строкам таблицы. Все бы хорошо, но в отдельных ситуациях вся эта конструкция переставала работать: либо текущая строка просто не изменялась, либо возникали ошибки "про индекс" и "что-то там неопределено". Выяснилось, что разработчик не совсем грамотно обращается к строкам таблицы, что в общем случае и вызывает ошибочные ситуации.
Стоит признать, что в общем случае правильно спозицинироваться на следующей-предыдущей строке действительно не так просто.
Начнем рассмотрение с того, что разберемся, как табличная часть отображается на форме.
Реквизит формы (располагается в правом окне редактирования формы в конфигураторе) - представляет собой отображение табличной части объекта (например, документа). Тип значения - ДанныеФормыКоллекция. Коллекция содержит элементы коллекции, то есть отображения строк табличной части.
Каждый элемент коллекции кроме реквизитов связанной табличной части содержит Номер строки [диапазон 1..Количество строк].
К каждой строке (элементу коллекции) можно обратиться по индексу [диапазон 0..Количество строк -1]. Способы обращения: указать индекс в скобках [<Индекс>] или использовать метод Получить(<Индекс>).
Но у каждой строки есть отдельный параметр, не являющийся свойством, то есть его значение невозможно получить напрямую "через точку" - это идентификатор. Уникальный номер строки (тип число). Данный номер не изменяется ни при каких изменениях в составе строк табличной части.
Например, очередной строке после ввода был присвоен идентификатор 5. Предыдущие 4 строки могли быть удалены, номер данной строки изменился на первую. Но идентификатор строки остался без изменений.
Получить значение идентификатора любой из строк можно используя метод ПолучитьИдентификатор()
Например, идентификатор для 3й строки:
ТабличнаяЧасть[2].ПолучитьИдентификатор()
Для реквизитов формы типа ДанныеФормыКоллекция, полученных из табличных частей объектных данных (документов, справочников и т.д.), доступно дополнительное свойство ИсходныйНомерСтроки, позволяющее получить номер соответствующей строки реального объекта. Впрочем свойство доступно всегда, но когда реквизит не связан с реальной табличной частью, свойство ничего не возвращает.
Отдельно отметим, что создание в порядке исследования дополнительного реквизита с именем "ИсходныйНомерСтроки" для реквизита типа ДанныеФормыКоллекция привело к ошибке и последующему принудительному закрытию конфигуратора.
На всякий случай заметим, что реквизит формы типа ДанныеФормыКоллекция не содержит никаких данных о том, как таблица отображается на форме. Например, невозможно определить, какая строка в настоящей момент является текущей. В том числе реквизит формы будет одинаково функционален даже если таблица вообще не добавлена в элементы формы (никакой из элементов формы не содержит путь к данным этого реквизита).
Элемент формы Таблица, связанный с реквизитом Таблица (Путь к данным = Объект.ТабличнаяЧасть) - левая часть окна редактирования формы.
Здесь практически все наоборот.
Из элемента формы невозможно получить данные, содержащиеся в таблице, за исключением данных текущей (активной) строки.
Но есть возможность получить информацию о текущей(активной) строке - точнее, ее идентификаторе.
Кроме того, можно получить массив идентификаторов выделенных строк при множественном выделении.
Как же правильно связать эти данные, на примере той же задачи со стрелками для изменения текущей строки?
Рассмотрим, например, действия по кнопке "Вниз"
- Получаем идентификатор текущей строки из элемента типа таблица
- По полученному идентификатору находим строку коллекции (реквизит табличной части) через НайтиПоИдетификатору() и получаем ее номер.
- К полученному номеру добавляем единицу, определяя номер следующей строки. Обращаемся к строке по идентификатору. Как не парадоксально, но индекс следующей строки будет равен номеру, полученному на предыдущем этапе, так как индекс = номер строки -1.
- Получаем идентификатор строки, рассчитанной как следующая. Именно этот идентификатор присваиваем свойству элемента текущая строка элемента формы таблица.
При этом следует учитывать "переполнение". То есть обрабатывать попытку "спуститься ниже последней строки". Здесь возможно 2 варианта действий:
- Ничего не изменять и остаться на последней строке
- Переместиться на первую строку.
Рассмотрим пример процедуры модуля формы, отрабатывающей действие команды "Вниз". Исполняется на клиенте. Стратегия поведения при достижении последней строки определяется реквизитом формы (возможно, и переменной) Вокруг.
&НаКлиенте
Процедура Вниз(Команда)
ТекущаяСтрока = Элементы.ТабличнаяЧасть.ТекущаяСтрока;
НомерСтрокиТЧ = Объект.ТабличнаяЧасть.НайтиПоИдентификатору(ТекущаяСтрока).НомерСтроки;
Если НомерСтрокиТЧ = Объект.ТабличнаяЧасть.Количество() Тогда
Если Вокруг Тогда //Опция Вокруг - переходим на последнюю строку, если нет - остаемся на первой
Элементы.ТабличнаяЧасть.ТекущаяСтрока = Объект.ТабличнаяЧасть[0].ПолучитьИдентификатор();
КонецЕсли;
Иначе
Элементы.ТабличнаяЧасть.ТекущаяСтрока = Объект.ТабличнаяЧасть[НомерСтрокиТЧ].ПолучитьИдентификатор();
КонецЕсли;
КонецПроцедуры
Предлагаю обработку, которая позволяет детальнее исследовать поведение номеров строк(индексов) и идентификаторов при изменении таблицы: добавлении/удалении строк и изменении их порядка. Для более глубокого понимания работы процедур изменения текущей строки можно воспользоваться отладчиком. Поскольку все процедуры исполняются на клиенте, отключенная отладка на сервере не станет препятствием к изучению.
Форма обработки содержит таблицу, в которой помимо строковых значений дополнительно отображается идентификатор строки.
Команды обработки позволяют:
- Добавить новую строку (стандартная команда)
- Вставить строку перед или после текущей
- Сгенерировать наборы из Н строк, содержащие произвольные уникальные идентификаторы
- Удалить текущую строку (стандартная и дополнительная команда). Дополнительная команда демонстрирует пример "правильного" удаления.
- Двигаться по строкам вверх-вниз
- Сортировать строки по убыванию и возрастанию
Разрабатывалось и тестировалось на 23-м релизе 8.3.23.2157. Поскольку "новые" методы здесь не используются, можно с уверенностью сказать, что обработка будет функционировать под любым релизом платформы на управляемых формах.
Проверено на следующих конфигурациях и релизах:
- 1С:Библиотека стандартных подсистем, редакция 3.1, релизы 3.1.9.453