Почему возникает ошибка «Несоответствие типов (Параметр номер 1)» при вызове метода Получить регистра сведений?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Анализ исходного кода и выяснение причины ошибки

Посмотрим на исходный код функции получения стоимости, который привел к ошибке:


&НаСервере 
Функция ПолучитьСтоимость(Услуга) 
    СтруктураОтбора = Новый Структура; 
    СтруктураОтбора.Вставить("Услуга", Услуга); 
    РезультатОтбора = РегистрыСведений.СтоимостьУслуги.Получить(СтруктураОтбора); 
    Возврат РезультатОтбора.Стоимость; 
КонецФункции 

Выясним причину сбоя. В платформе 1С метод менеджера регистра сведений Получить() имеет два различных варианта синтаксиса в зависимости от того, является ли регистр периодическим или непериодическим:

  1. Для непериодического регистра сведений: Получить(<Отбор>) — единственным параметром передается структура отбора по измерениям.
  2. Для периодического регистра сведений: Получить(<Период>, <Отбор>) — первым параметром обязательно передается дата или момент времени (тип Дата или МоментВремени), а вторым параметром — структура отбора.

Если регистр сведений в метаданных настроен как периодический (например, с периодичностью «В пределах секунды»), платформа ожидает первым параметром дату. Когда в метод первым параметром передается Структура, возникает исключение «Несоответствие типов (Параметр номер 1)».

Особенности работы метода Получить() для периодических регистров

Даже если первым параметром передать дату документа, метод Получить(<Период>, <Отбор>) выполняет поиск записи на точное совпадение даты и времени секунда в секунду. Если на указанную точную дату запись не вводилась, метод вернет структуру, содержащую пустые значения по умолчанию. Для периодических регистров сведений цен и тарифов данный метод практически никогда не применяется.

Скрытые ошибки в коде формы

Проанализируем сопутствующие критические ошибки, которые могут нарушить работу конфигурации:

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

Вариант решения 1: Использование метода ПолучитьПоследнее()

Для периодических регистров сведений платформой предусмотрен метод ПолучитьПоследнее(), который возвращает срез актуальных значений на переданную дату или на текущий момент времени. Также оптимизируем клиент-серверное взаимодействие, применив директиву &НаСервереБезКонтекста:


&НаСервереБезКонтекста
Функция ПолучитьСтоимость(Услуга, ДатаДокумента) 
    Отбор = Новый Структура("Услуга", Услуга); 
    ЗначенияРесурсов = РегистрыСведений.СтоимостьУслуги.ПолучитьПоследнее(ДатаДокумента, Отбор); 
    Возврат ЗначенияРесурсов.Стоимость; 
КонецФункции 

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

Вариант решения 2: Использование запроса к виртуальной таблице (рекомендуемый способ)

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


&НаСервереБезКонтекста
Функция ПолучитьСтоимостьУслугиЧерезЗапрос(Услуга, ДатаДокумента)
    
    Если Не ЗначениеЗаполнено(Услуга) Тогда
        Возврат 0;
    КонецЕсли;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	СтоимостьУслугиСрезПоследних.Стоимость КАК Стоимость
        |ИЗ
        |	РегистрСведений.СтоимостьУслуги.СрезПоследних(&Период, Услуга = &Услуга) КАК СтоимостьУслугиСрезПоследних";
        
    Запрос.УстановитьПараметр("Период", ДатаДокумента);
    Запрос.УстановитьПараметр("Услуга", Услуга);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        Возврат Выборка.Стоимость;
    КонецЕсли;
    
    Возврат 0;
    
КонецФункции

Использование запроса обеспечивает стабильную работу при изменении структуры измерений регистра и исключает появление ошибок несоответствия типов параметров.

← На главную