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