Почему не записываются данные в реквизит справочника в 1С 7.7?

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

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

В чем заключается ошибка при использовании метода ТекущийЭлемент()

Проанализируем фрагмент исходного кода, в котором возникает проблема:


Если Спр.НайтиПоКоду(КартриджКлиента.Код, 0) = 1 Тогда
    НайдКарт = Спр.ТекущийЭлемент();
    НайдКарт.ИсторияРабот = ДокИстория.ТекущийДокумент();
    Спр.Записать();
КонецЕсли;

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

Если же попытаться выполнить метод НайдКарт.Записать(), платформа сгенерирует ошибку «Не выбран элемент!», поскольку переменная НайдКарт хранит ссылку, а не рабочий экземпляр объекта справочника.

Правильный способ записи реквизита справочника

Разберем по шагам корректный алгоритм. Для изменения реквизита необходимо обращаться к свойствам самого позиционированного объекта (переменной, созданной через СоздатьОбъект), после чего вызывать его метод Записать():


Процедура ВыполненныеРаботы()
    ДокИстория = СоздатьОбъект("Документ.ИсторияРаботПоКартриджу");
    Спр = СоздатьОбъект("Справочник.КартриджиКлиента");

    Если ПустоеЗначение(КартриджКлиента.ИсторияРабот) = 1 Тогда
        Сообщить("Картридж у нас не был");
        
        ДокИстория.Новый();
        ДокИстория.Записать();

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

Важные технические нюансы работы со справочниками в 1С 7.7

  1. Прямое позиционирование: Если ссылка на элемент справочника уже известна (например, передана из реквизита формы КартриджКлиента), вместо метода НайтиПоКоду() надежнее использовать Спр.НайтиЭлемент(КартриджКлиента). Это защитит алгоритм от сбоев при наличии незначащих пробелов или одинаковых кодов в разных ветках подчинения.
  2. Особенности поиска в подчиненных справочниках: При использовании метода НайтиПоКоду(Код, 0) поиск ведется строго в рамках текущего установленного владельца. Если перед поиском владелец не был задан через Спр.ИспользоватьВладельца(Владелец), метод может вернуть 0. Для поиска по всей таблице без учета владельца второй параметр должен быть равен 1 (если это разрешено в свойствах справочника).
  3. Периодические реквизиты: Если реквизит является периодическим, присвоение Спр.Реквизит = Значение запишет его на текущую рабочую дату. Если необходимо явно зафиксировать дату изменения периодического реквизита, используют метод Спр.УстановитьРеквизит("ИсторияРабот", ДокИстория.ТекущийДокумент(), ДатаЗаписи), который не требует последующего вызова Спр.Записать().
  4. Транзакционная целостность: При создании документа и одновременной записи ссылки на него в справочник рекомендуется использовать транзакцию (НачатьТранзакцию() / ЗафиксироватьТранзакцию()). Это предотвратит появление пустых «зависших» документов в случае, если запись справочника будет заблокирована другим сеансом.
← На главную