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