При программном выполнении запросов или извлечении текста запроса из схемы компоновки данных (СКД) разработчики часто сталкиваются с ситуацией, когда в отладчике напротив всех полей объекта ВыборкаИзРезультатаЗапроса отображается статус «Ошибка чтения значения», а сам отчет возвращает пустой результат. Рассмотрим причины такого поведения платформы 1С:Предприятие и разберем по шагам, как правильно работать с выборкой и настраивать параметры периодов в СКД.
Проанализируем механику работы с выборкой результатов запроса. Когда мы получаем выборку с помощью метода Выбрать(), курсор находится перед первой записью. До тех пор, пока не выполнен переход к конкретной строке, объект выборки не содержит активных данных текущей записи.
Попытка просмотреть значения полей в табло отладчика или вычислить выражение до вызова метода Следующий() неизбежно приводит к сообщению «Ошибка чтения значения». Аналогичная ошибка возникает, если результат запроса абсолютно пуст и метод Следующий() возвращает Ложь.
Посмотрим на классический ошибочный подход, при котором данные пытаются прочитать сразу после инициализации выборки:
// Неправильный подход: обращение к полям до позиционирования
Выборка = Запрос.Выполнить().Выбрать();
// В отладчике для Выборка.Номенклатура будет "Ошибка чтения значения"
Разберем правильный алгоритм обхода выборки с проверкой на наличие строк:
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Только внутри цикла поля доступны для чтения
ТекущаяНоменклатура = Выборка.Номенклатура;
ТекущаяСумма = Выборка.Сумма;
КонецЦикла;
Иначе
Сообщить("Запрос не вернул данных для обработки.");
КонецЕсли;
Если выборка обходится через Следующий(), но данных все равно нет, выясним причину формирования пустого результата. Часто при ручном выполнении текста запроса, извлеченного из МакетКомпоновкиДанных, в тексте появляются сгенерированные платформой параметры вида &П, &П2 вместо ожидаемых &НачалоПериода и &КонецПериода.
Это происходит из-за механизма автозаполнения параметров виртуальных таблиц СКД (например, РегистрНакопления.Продажи.Обороты). При этом параметры периода могут принимать пустые значения по следующим причинам:
СтандартныйПериод свойство ДатаОкончания возвращает начало дня (время 00:00:00). Если не применить приведение к концу дня, все движения за последнюю дату периода исключаются из выборки.НачалоПериода и КонецПериода, вычисляемые через выражения от составного параметра периода, но для них не включено ограничение доступности, платформа может не рассчитать их автоматически. В итоге в запрос передаются пустые даты (01.01.0001 00:00:00), что дает нулевой оборот.Разберем по шагам, как правильно настроить передачу периода в схеме компоновки данных:
ПериодОтчета) с типом данных СтандартныйПериод. Оставим его доступным для пользователя в настройках отчета.НачалоПериода и КонецПериода установим флаг «Ограничение доступности», чтобы исключить конфликт пользовательского ввода.НачалоПериода: &ПериодОтчета.ДатаНачалаКонецПериода: КонецПериода(&ПериодОтчета.ДатаОкончания, "ДЕНЬ")
ВЫБРАТЬ
ПродажиОбороты.Номенклатура КАК Номенклатура,
ПродажиОбороты.КоличествоОборот КАК Количество,
ПродажиОбороты.СуммаОборот КАК Сумма
ИЗ
РегистрНакопления.Продажи.Обороты({(&НачалоПериода)}, {(&КонецПериода)}, , ) КАК ПродажиОбороты
Рассмотрим более надежный способ получения данных из СКД в программном коде. Вместо ручного извлечения SQL-текста из макета компоновки данных и самостоятельной передачи параметров в объект Запрос, рекомендуется использовать стандартный конвейер компоновки данных. Это гарантирует корректное применение всех параметров, условий, группировок и выражений без возникновения побочных системных параметров &П.
Посмотрим на программный пример выгрузки данных СКД в коллекцию значений:
// 1. Инициализируем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(
ЭтотОбъект.СхемаКомпоновкиДанных,
ПараметрыОтчета.НастройкиОтчета,
ДанныеРасшифровки
);
// 2. Инициализируем процессор компоновки данных
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
// 3. Выводим результат компоновки в ТаблицуЗначений
ТаблицаРезультат = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// 4. Работаем с готовой таблицей данных
Для Каждого СтрокаДанных Из ТаблицаРезультат Цикл
ТекущаяНоменклатура = СтрокаДанных.Номенклатура;
ТекущаяСумма = СтрокаДанных.Сумма;
КонецЦикла;
Такой подход исключает ошибки при чтении выборки, обеспечивает корректную обработку периодов и гарантирует полную совместимость с механизмами СКД в любых конфигурациях 1С.