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