Как правильно заполнить данные документа из регистра сведений и исправить ошибку несоответствия типов

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

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

Разбор типичной ошибки в методе СрезПоследних

Проанализируем фрагмент кода, который часто становится причиной затруднений:


&НаСервере
Процедура ЗаполнитьДанныеКифАмбулатНаСервере()
    Отбор = новый Структура("Период", Объект.ДатаПервичногоПосещения);
    Срез = РегистрыСведений.Обращения.СрезПоследних(Объект.ДатаПервичногоПосещения, Отбор);
    Объект.ПорядковыйНомерПосещения = Срез.ПорядковыйНомерПосещения;
КонецПроцедуры

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

Во-первых, использование стандартного реквизита Период в структуре отбора (второй параметр метода СрезПоследних) недопустимо. Метод СрезПоследних(Период, Отбор) работает по следующим правилам:

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

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

Во-вторых, метод СрезПоследних возвращает не объект записи, а ТаблицуЗначений. Даже если условиям отбора соответствует всего одна запись, результат всё равно будет таблицей. Поэтому прямое обращение через точку Срез.ПорядковыйНомерПосещения не сработает — у таблицы нет такого свойства, оно есть только у строк этой таблицы.

Решение проблемы с использованием метода менеджера регистра

Для исправления вышеуказанного кода нам необходимо исключить поле Период из структуры отбора и добавить проверку на наличие данных в результирующей таблице. Проанализируем исправленный вариант:


&НаСервере
Процедура ЗаполнитьДанныеКифАмбулатНаСервере()
    // Если в регистре нет измерений, отбор можно не создавать
    // Если есть (например, ФизЛицо), добавляем его в структуру
    Отбор = Новый Структура;
    // Отбор.Вставить("Пациент", Объект.Пациент); // Пример использования

    // Получаем таблицу значений (срез на указанную дату)
    ТаблицаСреза = РегистрыСведений.Обращения.СрезПоследних(Объект.ДатаПервичногоПосещения, Отбор);

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

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

Рекомендуемый способ: Использование запроса к виртуальной таблице

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

Разберем по шагам создание запроса для получения данных из регистра:


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

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

Преимущества данного подхода:

Важный нюанс: Использование объекта Граница

Иногда возникает ситуация, когда запись в регистр и документ создаются в одну и ту же секунду. При обычном использовании даты в качестве параметра СрезПоследних, система может «не увидеть» запись, сделанную ровно в это же время. Чтобы гарантированно включить записи за текущую секунду, проанализируем использование объекта Граница.


// Вместо простой даты используем Границу
МоментВремени = Новый Граница(Объект.ДатаПервичногоПосещения, ВидГраницы.Включая);
Запрос.УстановитьПараметр("Период", МоментВремени);

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

Оптимизация структуры данных

Иногда у начинающих разработчиков возникает идея отказаться от периодичности регистра и создать собственное измерение «Дата». Рассмотрим, почему это неудачное решение:

  1. Сложность получения данных: Вместо одного вызова СрезПоследних вам придется писать сложный запрос с группировками и поиском МАКСИМУМ(Дата).
  2. Потеря производительности: Виртуальные таблицы СрезПоследних в 1С оптимизированы на уровне СУБД для максимально быстрого поиска актуальных значений. Ручные запросы к физической таблице будут работать медленнее.
  3. Нарушение стандартов: Платформа 1С спроектирована так, чтобы история изменений хранилась именно в периодических регистрах.

Таким образом, правильным подходом будет использование периодического регистра сведений, обращение к нему через запрос к виртуальной таблице СрезПоследних с передачей даты в качестве первого параметра, и обязательная проверка результата на наличие записей перед заполнением реквизитов документа.

← На главную