При работе с регистрами бухгалтерии в 1С начинающие разработчики часто сталкиваются с ошибкой вызова метода Выбрать(). Исключение выглядит следующим образом:
Ошибка при вызове метода контекста (Выбрать): по причине: Недопустимое значение параметра (параметр номер '3')
В этой статье мы подробно проанализируем причины возникновения этой проблемы, разберем недочеты в исходном коде и рассмотрим правильные варианты выборки данных — как через метод Выбрать(), так и с помощью запросов СУБД.
Рассмотрим фрагмент кода, вызвавшего ошибку у автора темы:
СчетВыборка = ПланыСчетов.ЕПСБУ.НайтиПоКоду("106.31");
Счет106 = СчетВыборка.ПолучитьОбъект().Код;
СчетОтбора = Новый Структура ("Счет", Счет106);
Выборка = РегистрыБухгалтерии.ЕПСБУ.Выбрать(Дата("20180101"),Дата("20181231"),СчетОтбора);
Пока Выборка.Следующий() Цикл
ДТ = Выборка.Регистратор;
Сообщить(ДТ.Ссылка.Дата);
КонецЦикла;
Выясним причины, по которым платформой 1С было выброшено исключение при вызове метода Выбрать() в третьем параметре (структуре отбора):
СчетВыборка.ПолучитьОбъект().Код. В результате в переменную Счет106 попала обычная строка "106.31". В структуре отбора для регистра бухгалтерии платформа ожидает ссылку на элемент плана счетов (тип ПланыСчетовСсылка.ЕПСБУ), а не его строковый код.Счет в регистре просто нет. Вместо него используются измерения СчетДт и СчетКт. Поле Счет присутствует только в регистрах без корреспонденции.Помимо критических ошибок, приведших к сбою, проанализируем еще несколько недочетов, влияющих на производительность и корректность обработки данных:
ПолучитьОбъект(): Метод ПланыСчетов.ЕПСБУ.НайтиПоКоду() сразу возвращает ссылку. Вызов метода ПолучитьОбъект() считывает весь объект из базы данных в оперативную память сервера, что является лишней нагрузкой при чтении данных..Ссылка: Поле Выборка.Регистратор уже содержит ссылку на документ (ДокументСсылка). Обращение ДТ.Ссылка.Дата заставляет платформу выполнять лишнюю операцию адресации. Достаточно использовать Выборка.Регистратор.Дата.Дата("20181231") создает дату с нулевым временем: 31.12.2018 00:00:00. Проводки, сделанные в течение дня 31 декабря, не попадут в выборку. Для охвата всего дня следует использовать функцию КонецДня().С учетом всех исправлений сформируем корректную структуру отбора. Нам необходимо передать в отбор ссылку на счет и указать правильное имя измерения (СчетДт или СчетКт).
Рассмотрим вариант получения проводок по дебету счета:
// 1. Получаем ссылку на счет
Счет106 = ПланыСчетов.ЕПСБУ.НайтиПоКоду("106.31");
// 2. Формируем структуру отбора по измерению СчетДт
ОтборДт = Новый Структура("СчетДт", Счет106);
// 3. Выполняем выборку с умом указанной конечной даты
Выборка = РегистрыБухгалтерии.ЕПСБУ.Выбрать(
Дата("20180101"),
КонецДня(Дата("20181231")),
ОтборДт
);
// 4. Обходим результаты
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Регистратор.Дата);
КонецЦикла;
Обратите внимание: Если требуется выбрать все проводки, где счет участвует и по дебету, и по кредиту, сделать это в один проход метода Выбрать() невозможно. Придется выполнить две выборки (по СчетДт и по СчетКт) либо использовать запрос.
В стандартах разработки 1С использование метода Выбрать() для регистров накопления и бухгалтерии не рекомендуется при решении практических задач. Запросы показывают значительно лучшую производительность и гибкость.
Рассмотрим разницу:
Выбрать() считывает из базы данных все поля записей регистра на клиент или сервер приложений.ИЛИ.Разберем пример реализации задачи через объект Запрос:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЕПСБУ.Регистратор.Дата КАК ДатаРегистратора
|ИЗ
| РегистрБухгалтерии.ЕПСБУ КАК ЕПСБУ
|ГДЕ
| ЕПСБУ.Период МЕЖДУ &ДатаНач И &ДатаКон
| И (ЕПСБУ.СчетДт = &Счет ИЛИ ЕПСБУ.СчетКт = &Счет)";
Запрос.УстановитьПараметр("ДатаНач", Дата("20180101"));
Запрос.УстановитьПараметр("ДатаКон", КонецДня(Дата("20181231")));
Запрос.УстановитьПараметр("Счет", ПланыСчетов.ЕПСБУ.НайтиПоКоду("106.31"));
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.ДатаРегистратора);
КонецЦикла;
Таким образом, использование запросов полностью решает проблему фильтрации данных по нескольким условиям, снижает нагрузку на сеть и базу данных, а также предотвращает ошибки типов данных при передаче параметров отбора.