Как программно изменять значения реквизитов в форме списка 1С 7.7 при начале редактирования строки?

Программист 1С v7.7
← На главную

При разработке в среде 1С:Предприятие 7.7 программисты часто сталкиваются со специфическим поведением форм списков в режиме «редактирование в списке». Попытка простого присвоения значения реквизиту или использование метода УстановитьАтрибут() внутри предопределенной процедуры ПриНачалеРедактированияСтроки() часто не приносит желаемого результата: значение либо не меняется, либо затирается платформой сразу после входа в режим редактирования.

В этой статье мы подробно проанализируем, почему стандартные методы не работают, разберем жизненный цикл событий при редактировании строки и рассмотрим несколько надежных способов программного изменения данных.

Почему прямое присвоение в ПриНачалеРедактированияСтроки не работает?

Разберем причину такого поведения платформы. В 1С 7.7 форма списка — это очень ограниченный инструмент по сравнению с формой диалога. Когда пользователь нажимает Enter или делает двойной клик по строке, платформа запускает следующий механизм:

  1. Вызывается процедура ПриНачалеРедактированияСтроки().
  2. Платформа создает внутренний буфер значений текущей строки.
  3. Управление передается в поле ввода.

Основная проблема заключается в том, что любые изменения переменных (реквизитов), сделанные в пункте 1, могут быть проигнорированы, так как платформа при активации режима редактирования перечитывает данные из своего внутреннего кэша или ожидает ввода от пользователя. Кроме того, существует критическое ограничение: присвоить значение реквизиту, который не размещен на форме (в колонках списка), невозможно. Если колонка с реквизитом ТипКолонки отсутствует в табличной части формы, команда ТипКолонки = "Значение" будет просто проигнорирована.

Способ 1: Прямое изменение через создание объекта и отмена стандартного редактирования

Рассмотрим наиболее надежный метод, который позволяет обойти ограничения буферизации платформы. Суть метода заключается в том, чтобы перехватить начало редактирования, программно изменить данные в базе данных через СоздатьОбъект и запретить стандартное редактирование ячейки, чтобы форма обновилась уже с новыми данными.

Проанализируем пример кода для этого решения:


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

В данном случае мы используем СтатусВозврата(0), что предотвращает «проваливание» в ячейку. Данные обновляются в базе напрямую, и список отображает актуальное состояние.

Способ 2: Жизненный цикл событий и работа с «невидимыми» колонками

Нужно четко различать три похожих по названию события в форме списка. Проанализируем их назначение:

  1. ПриВводеСтроки(): Вызывается первой при создании нового элемента. Позволяет только запретить ввод через СтатусВозврата(0). В этот момент ТекущийЭлемент() еще не спозиционирован на новом объекте.
  2. ПриРедактированииНовойСтроки(): Срабатывает только для новых (еще не записанных) элементов. Именно здесь следует устанавливать значения по умолчанию для новых строк.
  3. ПриНачалеРедактированияСтроки(): Срабатывает только для уже существующих в базе элементов.

Важный нюанс: Чтобы программное присвоение Реквизит = Значение сработало внутри ПриРедактированииНовойСтроки(), этот реквизит обязательно должен быть выведен на форму в виде колонки. Если вы не хотите показывать этот реквизит пользователю, установите для колонки свойство Видимость(0) или сделайте её ширину равной 0. Без наличия колонки на форме присвоение не отработает.

Способ 3: Использование события ПриНачалеВыбораЗначения

Если ваша задача — подставить конкретное значение при нажатии на ячейку, рассмотрим более элегантный вариант. Вместо редактирования текста можно использовать кнопку выбора в колонке.

  1. В свойствах колонки установите флажок «Имеет кнопку выбора».
  2. В свойствах колонки установите флажок «Запретить редактирование» (чтобы пользователь не мог писать текст руками).
  3. Используйте следующий код:

Процедура ПриНачалеВыбораЗначения(ИдентЭлемДиалога, ФлагСтандОбр)
    Если ИдентЭлемДиалога = "ТипКолонки" Тогда
        // Отключаем стандартный выбор (например, справочника)
        ФлагСтандОбр = 0;
        
        ВыбЗнач = "";
        Если СписокДляВыбора.ВыбратьЗначение(ВыбЗнач) = 1 Тогда
            // Прямое присвоение в активную строку
            ТипКолонки = ВыбЗнач;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Этот метод работает стабильнее, так как ПриНачалеВыбораЗначения срабатывает в контексте уже активного поля ввода.

Рекомендация по продвинутой разработке (1С++)

Если возможности стандартного списка 1С 7.7 кажутся вам слишком скудными, проанализируем профессиональное решение. Использование внешней компоненты 1С++ позволяет заменить стандартную таблицу на объект ТабличноеПоле. В нем события редактирования реализованы гораздо логичнее, есть возможность программно менять значения в любой ячейке без «танцев с бубном», а также раскрашивать строки и управлять фокусом ввода на совершенно другом уровне.

Резюме: Если вам нужно простое присвоение — убедитесь, что колонка видима. Если нужно сложное заполнение — используйте СоздатьОбъект с последующим СтатусВозврата(0) в процедуре ПриНачалеРедактированияСтроки.

← На главную