Как правильно сравнить значения реквизита табличной части с результатом запроса в 1С?

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

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

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

Анализ типовых ошибок: почему возникают сбои при записи

Рассмотрим типичный пример кода, в котором возникает ошибка выполнения:


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

При выполнении такого кода платформа выдает ошибку: «Значение не является значением объектного типа (Источник)». Проанализируем ключевые причины неполадки:

  1. Обращение к элементу формы ТекущаяСтрока при сохранении объекта: В момент записи документа (в обработчиках событий ПередЗаписью или ПриЗаписи) фокус ввода с табличной части может быть снят. В результате свойство ЭлементыФормы.ТЧ.ТекущаяСтрока возвращает Неопределено. Попытка обратиться к реквизиту Источник у незаполненного значения приводит к аварийному завершению работы программы. кроме того, проведение или запись документа может вызываться программно из формы списка или других модулей, где элементов формы вовсе нет.
  2. Некорректное сравнение типов данных: Переменная Результат содержит объект типа РезультатЗапроса, а не конкретную ссылку на документ. Прямое сравнение ссылки из табличной части ТекущаяСтрока.Источник и объекта РезультатЗапроса через оператор <> всегда вернет неверный результат. Для работы с результатами запроса необходимо использовать выборку (Результат.Выбрать()) или проверять результат на пустоту.
  3. Опасный вызов метода Записать() внутри обработки записи: Попытка вызвать ЭтотОбъект.Записать() внутри процедуры ПриЗаписи или ПередЗаписью недопустима, так как вызывает рекурсивную попытку записи и приводит к ошибке транзакции. Для отмены операции в 1С предусмотрен специальный булевый параметр Отказ = Истина;.

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

Разберем шаг за шагом правильную архитектуру решения этой задачи. Проверку необходимо производить над данными объекта, а не элементами интерфейса. Чтобы проверить все строки табличной части за один запрос к базе данных, используется передача массива ссылок в параметрах запроса с условием В (&Массив).

  1. Получаем все значения из колонки табличной части с помощью метода ВыгрузитьКолонку(). Результатом вызова является обычный Массив.
  2. Передаем полученный массив ссылок в параметр запроса.
  3. В тексте запроса накладываем фильтр ГДЕ Ссылка В (&Источники) и нужные условия (проведен, утвержден).
  4. Проверяем результат с помощью метода РезультатЗапроса.Пустой().

Готовый пример кода проверки при записи

Проанализируем пример кода, который правильно выполнять в модуле формы или в модуле объекта (событие ПередЗаписью):


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

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

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

Альтернативные методы поиска и проверки данных в 1С

В случаях, когда проверка выполняется локально на клиенте или серверных данных без необходимости обращения к СУБД, можно использовать встроенные методы работы с коллекциями 1С:

  1. Поиск в массиве (Массив.Найти()):

    Если у вас есть конкретная ссылка и массив значений, можно быстро проверить наличие значения. Метод возвращает индекс найденного элемента или Неопределено, если совпадение не найдено.

    
    Индекс = МассивИсточников.Найти(ИскомаяСмета);
    Если Индекс <> Неопределено Тогда
        // Значение найдено в массиве
    КонецЕсли;
    
  2. Поиск в таблице значений (ТаблицаЗначений.НайтиСтроки()):

    Если данные хранятся в Таблице Значений, поиск по колонке выполняется методом НайтиСтроки(), в который передается структура отбора. Метод возвращает массив найденных строк.

    
    Отбор = Новый Структура("Источник", ИскомаяСмета);
    НайденныеСтроки = ТЗИсточники.НайтиСтроки(Отбор);
    Если НайденныеСтроки.Количество() > 0 Тогда
        // Строки с совпадающим источником найдены
    КонецЕсли;
    

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

← На главную