Версия для печати темы (https://pro1c.org.ua/index.php?s=ffecbe233c333390ab774da24b9ea4d9&showtopic=42246)

Нажмите сюда для просмотра этой темы в обычном формате

Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 _ Программирование обычных форм 1С 8.2 и не интерфейсной логики _ РИБ: Ошибка при выполнении обработчика - 'ПриЗаписи'

Автор: Constantus 28.11.17, 14:01

Приветствую, форумчане!
"Управление торговлей 10.3", (Моби-С 5.5). "ABBYY Ukraine", 2003-2014 (2.3.20.1)

Ошибка возникает только со справочниками. Для справочников сделал (списал) код, который позволяет регистрировать изменения "История изменений", типа если пользователь что-то изменил, то можно узнать что и когда...

Изменения фиксируются в РегистреСведений "историяРеквизитов"

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

Перем НаборЗаписейИсторияОбъектов;

Процедура ПередЗаписью(Отказ)

    //...................................................................
    НаборЗаписейИсторияОбъектов = РегистрыСведений.ИсторияРеквизитов.СоздатьНаборЗаписей();
    
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Код");
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Наименование");
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Родитель");
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Владелец");
    
    Для А = 0 По ЭтотОбъект.Метаданные().Реквизиты.Количество() - 1 Цикл
        ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, ЭтотОбъект.Метаданные().Реквизиты[А].Имя);
    КонецЦикла;
    
КонецПроцедуры

Процедура ПриЗаписи(Отказ)
    Если НаборЗаписейИсторияОбъектов.Количество() <> 0 Тогда
        
        Для Каждого Запись Из НаборЗаписейИсторияОбъектов Цикл
            Запись.Объект = Ссылка;
        КонецЦикла;
        
        НаборЗаписейИсторияОбъектов.Записать(Ложь);
        
    КонецЕсли;
КонецПроцедуры


Процедура ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, ИмяРеквизита)
    
    Если ЭтотОбъект[ИмяРеквизита] <> Ссылка[ИмяРеквизита] Тогда
        НоваяЗапись = НаборЗаписейИсторияОбъектов.Добавить();
        НоваяЗапись.Период = ТекущаяДата();
        НоваяЗапись.Реквизит = ИмяРеквизита;
        НоваяЗапись.ИмяКомпьютера = ИмяКомпьютера();
        НоваяЗапись.Пользователь = ПараметрыСеанса.ТекущийПользователь;
        НоваяЗапись.СтароеЗначение = Ссылка[ИмяРеквизита];
        НоваяЗапись.НовоеЗначение = ЭтотОбъект[ИмяРеквизита];
    КонецЕсли;
    
КонецПроцедуры



На Центральной базе изменения фиксируются нормально. А вот после окончания обмена на филиальной базе выходит сообщение:

Ошибка при вызове метода контекста (ПрочитатьИзменения): Ошибка при выполнении обработчика - 'ПриЗаписи':
{Справочник.Пользователи.МодульОбъекта(83)}: Значение не является значением объектного типа (Количество)


Что произошло и как это можно решить, чтобы обмен проходил нормально?

Автор: MATEVI 28.11.17, 15:12

А в "перед записью" ваших справочников есть код?

Процедура ПередЗаписью(Отказ)
    
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;
    
КонецПроцедуры



Автор: Constantus 28.11.17, 15:16

MATEVI @ Сегодня, 18:12 * ,

Вот полный код "ПередЗаписью Модуля объекта справочника Пользователи:

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

          НаборЗаписейИсторияОбъектов = РегистрыСведений.ИсторияРеквизитов.СоздатьНаборЗаписей();
    
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Код");
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Наименование");
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Родитель");
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Владелец");
    
    Для А = 0 По ЭтотОбъект.Метаданные().Реквизиты.Количество() - 1 Цикл
        ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, ЭтотОбъект.Метаданные().Реквизиты[А].Имя);
    КонецЦикла;
        

    
КонецПроцедуры


Автор: MATEVI 28.11.17, 15:26

Ну тогда очень похоже что при обмене перед записью срабатывает этот код

   
Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;


И ваша переменная - неопределена
НаборЗаписейИсторияОбъектов=Неопределено


и следующий код ПриЗаписи
Если НаборЗаписейИсторияОбъектов.Количество() <> 0 Тогда

выдает эту ошибку

Автор: Constantus 28.11.17, 15:38

MATEVI @ Сегодня, 18:26 * ,

Логично. Т.е. при приеме данных 1с пытается выполнить действие перед записью, но понимает, что это обмен и больше не выполняет этот код.
Соответственно Набор записей регистра не создается, а в коде "При записи" этот набор нужен, а его нет...

Вопрос, как тогда исправить код? Т.е. куда все проставить? Может:

НаборЗаписейИсторияОбъектов = РегистрыСведений.ИсторияРеквизитов.СоздатьНаборЗаписей();
    
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Код");
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Наименование");
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Родитель");
    ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, "Владелец");
    
    Для А = 0 По ЭтотОбъект.Метаданные().Реквизиты.Количество() - 1 Цикл
        ОбработатьИзменениеРеквизита(НаборЗаписейИсторияОбъектов, ЭтотОбъект.Метаданные().Реквизиты[А].Имя);
    КонецЦикла;


поставить перед:

 Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;


Или есть более правильный подход?

Автор: MATEVI 28.11.17, 15:58

Constantus,
Логичней и правильней было бы воспользоваться механизмом "Версионирования", которое должно быть вроде в УТ.

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

Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7
https://pro1c.org.ua