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