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