Почему результат запроса в 1С пустой или не возвращает данные для расчета?

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

При разработке механизмов автоматического расчета в 1С программисты часто сталкиваются с ситуацией, когда запрос, написанный в консоли запросов, работает корректно, но в коде процедуры результат оказывается «пустым» или приводит к ошибкам. Рассмотрим детально, почему так происходит, на примере работы с виртуальными таблицами регистров бухгалтерии и обработкой полученных данных.

Различие между колонкой таблицы значений и числовым значением

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


РезультатЗапроса = Запрос.Выполнить().Выгрузить();
МенеджерЗаписи.Перерасход = РезультатЗапроса.КоличествоОборотДт / Запись.Пробег * 100;

В данном случае РезультатЗапроса — это объект типа ТаблицаЗначений. Когда мы пишем РезультатЗапроса.КоличествоОборотДт, система обращается не к конкретному числу, а к объекту КолонкаТаблицыЗначений. Попытка выполнить арифметическую операцию с колонкой (объектом) вместо числа не приведет к результату или вызовет ошибку в зависимости от контекста. Для получения суммы по всей колонке необходимо использовать метод Итог() или обращаться к конкретной строке таблицы.

Как правильно рассчитать итог по результату запроса

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


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

Если РезультатЗапроса.Количество() > 0 Тогда
    // Используем метод Итог для получения суммы по колонке
    СуммаОборота = РезультатЗапроса.Итог("КоличествоОборотДт");
    
    // Обязательная проверка на деление на ноль
    Если Запись.Пробег <> 0 Тогда
        МенеджерЗаписи.Перерасход = СуммаОборота / Запись.Пробег * 100;
    Иначе
        МенеджерЗаписи.Перерасход = 0;
    КонецЕсли;
КонецЕсли;

Особенности работы с виртуальными таблицами «Обороты»

Если код выше все равно не выводит результат, проблема может крыться в параметрах самого запроса. Проанализируем настройки виртуальной таблицы РегистрБухгалтерии.Хозрасчетный.Обороты.

1. Порядок и состав субконто

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

2. Признак количественного учета

Выясним причину, по которой КоличествоОборотДт может быть равно нулю. В плане счетов для конкретного счета (например, счета 10 «Материалы») должен быть установлен флаг Количественный. Если флаг не установлен, система не ведет учет количества, и в виртуальных таблицах это поле всегда будет пустым (NULL или 0), даже если суммы по дебету присутствуют.

3. Соответствие типов параметров

Проанализируем условие Субконто2 В ИЕРАРХИИ (&Склады). Если параметр &Склады заполняется из поля Запись.Машина, необходимо убедиться, что тип данных справочника «Машины» совпадает с типом данных, разрешенным для Субконто2 (обычно это справочник «Склады»). Если это разные справочники, условие В ИЕРАРХИИ всегда будет ложным, и запрос вернет пустую таблицу.

Ошибки архитектуры при записи в регистр

Посмотрим на процедуру ПриЗаписиНаСервере. Использование МенеджерЗаписи внутри обработчика записи того же самого объекта — это опасная практика. Разберем, почему:

  1. Рекурсия и блокировки: Вызов МенеджерЗаписи.Записать() внутри транзакции записи может привести к конфликту блокировок (Deadlock) или ошибке «Объект изменен другим пользователем», так как система пытается дважды модифицировать одни и те же данные в рамках одной транзакции.
  2. Лишние действия: Вместо создания нового менеджера записи, правильнее изменять свойства самого объекта Запись (или ТекущийОбъект), который уже находится в процессе записи.

Рекомендуется перенести логику расчета в событие ПередЗаписью, где можно напрямую присвоить значение полю: Для Каждого Строка Из НаборЗаписей Цикл Строка.Перерасход = ... КонецЦикла;

Оптимизация запроса и кода

Рассмотрим еще несколько важных моментов, которые помогут сделать код стабильнее:

Таким образом, для решения проблемы «пустого результата» необходимо не только проверить корректность обращения к объектам (ТЗ vs Число), но и убедиться в правильности настройки аналитики (субконто) и типов данных в параметрах запроса.

← На главную