Как исправить ошибку «Типы сравниваемых переменных различные» при проведении документа в 1С

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

При написании логики списания и проверки остатков в модуле проведения документа разработчики часто сталкиваются со сбоем выполнения программы: «Типы сравниваемых переменных различные». Ошибка обычно возникает в строке проверки условия, например: ЕСЛИ КоличествоОстаток < ТекСтрокаТовары.Количество Тогда.

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

Выясняем причину возникновения ошибки

Разберем ситуацию, которая приводит к сбою. Допустим, в цикле или после выполнения запроса создается выборка данных:


ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

ЕСЛИ ВыборкаДетальныеЗаписи.Следующий() ТОГДА
    Движение.Сумма = ТекСтрокаТовары.Количество * ВыборкаДетальныеЗаписи.ЦенаЗаЕд;
КонецЕсли;

КоличествоОстаток = ВыборкаДетальныеЗаписи.КоличествоОстаток;

ЕСЛИ КоличествоОстаток < ТекСтрокаТовары.Количество Тогда
    Отказ = Истина;
КонецЕсли;

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

  1. Метод РезультатЗапроса.Выбрать() возвращает объект выборки.
  2. Условие ВыборкаДетальныеЗаписи.Следующий() проверяет наличие записей. Так как остатка нет, метод возвращает Ложь, и тело блока Если пропускается.
  3. Далее программа пытается прочитать свойство ВыборкаДетальныеЗаписи.КоличествоОстаток. Поскольку позиционирование на корректную запись не произошло, платформа возвращает значение типа Неопределено.
  4. Переменной КоличествоОстаток присваивается значение Неопределено.
  5. На этапе выполнения условия КоличествоОстаток < ТекСтрокаТовары.Количество платформа пытается сравнить значение типа Неопределено со значением типа Число. В 1С операции сравнения на больше/меньше для разных типов данных не поддерживаются и вызывают фатальную ошибку.

Способ 1. Быстрое исправление логики работы с выборкой

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

Рассмотрим вариант с явной инициализацией переменной:


КоличествоОстаток = 0;

ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

Если ВыборкаДетальныеЗаписи.Следующий() Тогда
    Движение.Сумма = ТекСтрокаТовары.Количество * ВыборкаДетальныеЗаписи.ЦенаЗаЕд;
    КоличествоОстаток = ВыборкаДетальныеЗаписи.КоличествоОстаток;
КонецЕсли;

Если КоличествоОстаток < ТекСтрокаТовары.Количество Тогда
    Отказ = Истина;
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = "Данного товара осталось " + КоличествоОстаток + " шт.";
    Сообщение.Сообщить();
КонецЕсли;

В данном примере, даже если запрос не вернет ни одной строки, переменная КоличествоОстаток останется равной 0 (тип Число). Сравнение 0 < ТекСтрокаТовары.Количество пройдет успешно и выведет пользователю сообщение о нехватке товара.

Способ 2. Оптимизация проведения и проверка отрицательных остатков

Выполнение запросов внутри цикла (Для Каждого Строка Из Таблица Цикл) является серьезной ошибкой производительности. При большом количестве строк в документе это снижает скорость проведения системы в десятки раз.

Проанализируем правильный подход с формированием движений и последующей проверкой сформировавшихся отрицательных остатков единым запросом.


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // 1. Подготовка табличной части документа через запрос
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Товары.Номенклатура КАК Номенклатура,
        |   СУММА(Товары.Количество) КАК Количество
        |ПОМЕСТИТЬ ВремТовары
        |ИЗ
        |   Документ.РеализацияТоваровУслуг.Товары КАК Товары
        |ГДЕ
        |   Товары.Ссылка = &Ссылка
        |СГРУППИРОВАТЬ ПО
        |   Товары.Номенклатура
        |;";
        
    Запрос.УстановитьПараметр("Ссылка", Ссылка);
    Запрос.Выполнить();
    
    // 2. Формирование движений
    Движения.ОстаткиТоваров.Очистить();
    
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Товары.Номенклатура КАК Номенклатура,
        |   Товары.Количество КАК Количество
        |ИЗ
        |   ВремТовары КАК Товары";
        
    ВыборкаТовары = Запрос.Выполнить().Выбрать();
    Пока ВыборкаТовары.Следующий() Цикл
        Движение = Движения.ОстаткиТоваров.ДобавитьРасход();
        Движение.Период = Дата;
        Движение.Номенклатура = ВыборкаТовары.Номенклатура;
        Движение.Количество = ВыборкаТовары.Количество;
    КонецЦикла;
    
    // 3. Запись движений в БД
    Движения.ОстаткиТоваров.Записывать = Истина;
    Движения.Записать();
    
    // 4. Проверка отрицательных остатков после записи
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Остатки.Номенклатура.Представление КАК НоменклатураПредставление,
        |   -Остатки.КоличествоОстаток КАК Дефицит
        |ИЗ
        |   РегистрНакопления.ОстаткиТоваров.Остатки(
        |       &ГраницаКонтроля,
        |       Номенклатура В (ВЫБРАТЬ ВремТовары.Номенклатура ИЗ ВремТовары)) КАК Остатки
        |ГДЕ
        |   Остатки.КоличествоОстаток < 0";
        
    ГраницаКонтроля = Новый Граница(МоментВремени(), ВидГраницы.Включая);
    Запрос.УстановитьПараметр("ГраницаКонтроля", ГраницаКонтроля);
    
    РезультатЗапроса = Запрос.Выполнить();
    
    // 5. Вывод сообщений об ошибках
    Если Не РезультатЗапроса.Пустой() Тогда
        Отказ = Истина;
        ВыборкаОшибки = РезультатЗапроса.Выбрать();
        Пока ВыборкаОшибки.Следующий() Цикл
            Сообщение = Новый СообщениеПользователю;
            Сообщение.Текст = "Товара " + ВыборкаОшибки.НоменклатураПредставление + 
                              " недостаточно в количестве " + ВыборкаОшибки.Дефицит + " шт.";
            Сообщение.Сообщить();
        КонецЦикла;
    КонецЕсли;

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

Рекомендации по предотвращению ошибок сравнения типов

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

← На главную