Как программно изменить текущий элемент справочника прямо из формы списка?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С:Предприятие 7.7 часто возникает задача интерактивного изменения данных прямо в списке. Например, пользователю нужно быстро переключить флажок, установить «метку» или изменить статус документа, не открывая форму редактирования каждого элемента. Однако новички часто сталкиваются с тем, что стандартные методы позиционирования в форме списка не позволяют «просто так» взять и записать новое значение в текущую строку.

В этой статье мы разберем, почему возникает ошибка «Не выбран элемент!», как правильно получить объект для записи и какие нюансы стоит учитывать для корректного обновления интерфейса.

Анализ проблемы: почему ТекущийЭлемент нельзя просто перезаписать?

Рассмотрим ситуацию, с которой столкнулся автор темы. В форме списка справочника есть текстовое поле, имитирующее кнопку или иконку. При щелчке по нему должна срабатывать процедура ПриНачалеРедактированияСтроки, которая меняет значение реквизита Метка. Типичная ошибка выглядит так:


Процедура ПриНачалеРедактированияСтроки()
    Если Форма.ТекущаяКолонка = "ПиктМетка" Тогда
        ТекЭлемент = ТекущийЭлемент;
        ТекЭлемент.Метка = ?(ТекЭлемент.Метка = 0, 1, 0); // Ошибка здесь!
        ТекЭлемент.Записать();
    КонецЕсли;
КонецПроцедуры

Проанализируем причину неудачи. Функция ТекущийЭлемент() в контексте формы списка возвращает ссылку на элемент справочника, на котором в данный момент установлен курсор. В среде 1С 7.7 ссылка является объектом «только для чтения» в плане записи в базу данных. Для того чтобы изменить данные, нам необходимо создать объектный экземпляр справочника, найти в нем нужный элемент и только тогда производить запись.

Правильная реализация изменения элемента

Разберем по шагам правильный алгоритм действий. Чтобы изменить реквизит текущей строки, нам нужно выполнить следующую последовательность команд:

  1. Определить, на каком элементе стоит пользователь.
  2. Создать вспомогательный объект типа Справочник.ИмяСправочника.
  3. Найти этот элемент в базе данных по ссылке.
  4. Изменить нужное значение.
  5. Записать объект.
  6. Отменить стандартное редактирование строки, чтобы не открывалась форма элемента.

Вот как выглядит корректный код для решения задачи с переключением метки:


Процедура ПриНачалеРедактированияСтроки()
    // Проверяем, что клик произошел именно по нужной колонке
    Если Форма.ТекущаяКолонка = "ПиктМетка" Тогда
        
        // 1. Получаем ссылку на текущий элемент
        ТекСсылка = ТекущийЭлемент;
        
        // 2. Создаем объект справочника для манипуляций
        Спр = СоздатьОбъект("Справочник.Элементы");
        
        // 3. Позиционируем объект на нужной записи
        Если Спр.НайтиЭлемент(ТекСсылка) = 1 Тогда
            
            // 4. Меняем значение реквизита (инвертируем метку)
            Спр.Метка = ?(Спр.Метка = 0, 1, 0);
            
            // 5. Записываем изменения в базу данных
            Спр.Записать();
            
            // Важно: сообщаем форме, что данные изменились визуально
            Форма.Обновить(0);
        КонецЕсли;
        
        // 6. Прерываем стандартный процесс редактирования
        СтатусВозврата(0);
        Возврат;
        
    КонецЕсли;
КонецПроцедуры

Важные дополнения и нюансы

Рассмотрим подробнее несколько критических моментов, которые помогут сделать решение более надежным и быстрым.

1. Обновление формы. После выполнения метода Записать() данные в таблице SQL или файле DBF уже изменились, но пользователь может продолжать видеть старое значение в списке. Чтобы принудительно перерисовать строку, используем Форма.Обновить(0). Параметр 0 позволяет обновить форму без пересчета итогов, что работает быстрее.

2. Работа с периодическими реквизитами. Если реквизит, который вы меняете, является периодическим (например, цена или статус на дату), обычного присваивания Спр.Реквизит = Значение может быть недостаточно. В этом случае следует использовать метод УстановитьАтрибут или объект Периодический, предварительно указав дату через ИспользоватьДату().

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


Переменная СпрОбъект;

Процедура ПриОткрытии()
    СпрОбъект = СоздатьОбъект("Справочник.Элементы");
КонецПроцедуры

Процедура ПриНачалеРедактированияСтроки()
    // Теперь нам не нужно каждый раз инициализировать СпрОбъект
    // Достаточно просто найти в нем текущий элемент
    СпрОбъект.НайтиЭлемент(ТекущийЭлемент);
    // ... дальнейшая логика
КонецПроцедуры

4. Обработка блокировок. В многопользовательской среде может возникнуть ситуация, когда элемент, который вы пытаетесь изменить, уже открыт и редактируется другим пользователем. В этом случае метод Записать() выдаст ошибку. Проанализируем ситуацию и добавим защиту:


Попытка
    Спр.Записать();
Исключение
    Предупреждение("Не удалось изменить метку. Возможно, элемент заблокирован другим пользователем.");
КонецПопытки;

Сравнение с платформой 1С 8.x

Выясним, как изменился этот подход в современных версиях программы (8.3). В управляемых формах работа со списком построена иначе:

Подводя итог для 1С 7.7: помните, что форма списка — это лишь «отражение» базы данных. Для любых манипуляций с данными всегда создавайте отдельный объект справочника и явно позиционируйте его на нужной записи.

← На главную