Как корректно настроить отбор по полю "Проведен" в ПостроителеЗапроса для СпискаДокументов и избежать ошибки "Неверный тип значения"?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей
← На главную

При работе с платформой 1С:Предприятие, в частности с обычными формами и механизмом ПостроительЗапроса, мы часто сталкиваемся с необходимостью получить данные из динамического списка (СписокДокументов) с учетом интерактивно установленных пользователем отборов и интервалов. При этом возникает задача отфильтровать эти данные по определенным критериям, например, получить только проведенные документы.

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


Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ДокументСписок);
Построитель.ЗаполнитьНастройки();

ПолеПроведен = Построитель.ДоступныеПоля.Найти("Проведен");
ПолеПроведен.Отбор = Истина;

ОтборПроведен = Построитель.Отбор.Добавить("Проведен");
ОтборПроведен.Использование = Истина;
ОтборПроведен.ВидСравнения = ВидСравнения.Равно;
ОтборПроведен.Значение = Истина; // Здесь возникает ошибка "Неверный тип значения"

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

В этом коде мы создаем объект ПостроительЗапроса и в качестве источника данных передаем ему СписокДокументов, который является элементом формы (в данном случае, списком реализаций в УТ 10.3 на обычных формах). Мы пытаемся добавить отбор по полю "Проведен", установив его значение равным Истина. Однако, при попытке присвоения значения ОтборПроведен.Значение = Истина, система выдает ошибку "Неверный тип значения". Давайте разберем, почему это происходит и как мы можем решить эту проблему.

Выясняем причину ошибки "Неверный тип значения"

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

Мы можем убедиться в этом, проверив свойства поля в отладчике. Если мы посмотрим на Построитель.ДоступныеПоля.Найти("Проведен"), то, скорее всего, увидим, что свойство ТипЗначения для этого поля равно Неопределенный. Когда мы пытаемся присвоить булевое значение Истина полю, тип которого система считает неопределенным, возникает ошибка, так как платформа не знает, как выполнить сравнение или преобразование типов.

Решение проблемы: Обеспечиваем корректное определение типа поля "Проведен"

Для устранения ошибки нам необходимо убедиться, что ПостроительЗапроса точно "знает", что поле "Проведен" имеет булевый тип. Существует несколько подходов, в зависимости от того, как мы управляем источником данных для построителя.

Вариант 1: Использование ТаблицыЗначений с явно определенными типами как источника данных

Этот подход является наиболее надежным, если мы можем выгрузить данные из СписокДокументов в промежуточную ТаблицуЗначений. Он позволяет нам полностью контролировать определение типов для всех колонок, которые будут использоваться в построителе запроса. Затем уже эту ТаблицуЗначений мы используем в качестве источника для ПостроителяЗапроса.

Мы должны создать ТаблицуЗначений и для каждой колонки, включая "Проведен", явно указать ее тип. Рассмотрим, как это можно сделать:


// Шаг 1: Создаем новую ТаблицуЗначений с явно определенными типами колонок.
ТЗИсточникДанных = Новый ТаблицаЗначений;

// Определяем тип для колонки "Проведен" как Булево.
МассивТиповБулево = Новый Массив;
МассивТиповБулево.Добавить(Тип("Булево"));
ДопустимыеТипыБулево = Новый ОписаниеТипов(МассивТиповБулево);
ТЗИсточникДанных.Колонки.Добавить("Проведен", ДопустимыеТипыБулево);

// Добавляем другие необходимые колонки, которые присутствуют в ДокументСписок
// и по которым могут быть отборы или которые нужны в результате.
// Например, для списка реализаций это могут быть: Ссылка, Дата, Номер и т.д.
ТЗИсточникДанных.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("ДокументСсылка.РеализацияТоваровУслуг"));
ТЗИсточникДанных.Колонки.Добавить("Дата", Новый ОписаниеТипов("Дата"));
ТЗИсточникДанных.Колонки.Добавить("Номер", Новый ОписаниеТипов("Строка"));
// Добавьте все остальные колонки, которые вам нужны из ДокументСписок

// Шаг 2: Заполняем нашу новую ТаблицуЗначений данными из исходного ДокументСписок.
// При этом мы учитываем уже установленные интерактивные отборы и интервалы в ДокументСписок.
// Это гарантирует, что мы работаем с теми же данными, что и пользователь на форме.
Для Каждого СтрокаСписка Из ДокументСписок Цикл
    НоваяСтрокаТЗ = ТЗИсточникДанных.Добавить();
    НоваяСтрокаТЗ.Проведен = СтрокаСписка.Проведен;
    НоваяСтрокаТЗ.Ссылка = СтрокаСписка.Ссылка;
    НоваяСтрокаТЗ.Дата = СтрокаСписка.Дата;
    НоваяСтрокаТЗ.Номер = СтрокаСписка.Номер;
    // Заполните остальные колонки
КонецЦикла;

// Шаг 3: Используем эту ТаблицуЗначений как источник данных для ПостроителяЗапроса.
Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТЗИсточникДанных);
Построитель.ЗаполнитьНастройки();

// Теперь мы можем без проблем установить отбор по полю "Проведен".
ОтборПроведен = Построитель.Отбор.Добавить("Проведен");
ОтборПроведен.Использование = Истина;
ОтборПроведен.ВидСравнения = ВидСравнения.Равно;
ОтборПроведен.Значение = Истина; // Ошибка "Неверный тип значения" больше не возникает

// Выполняем запрос и получаем результат.
Построитель.Выполнить();
РезультатТЗ = Построитель.Результат.Выгрузить();

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

Вариант 2: Корректировка запроса ДинамическогоСписка на форме (если ДокументСписок является ДинамическимСписком)

Если ДокументСписок на форме является объектом типа ДинамическийСписок, то его поля уже должны иметь метаданные, включая типы. В идеале, стандартный реквизит "Проведен" документа должен автоматически быть распознан как булевый. Если этого не происходит, возможно, причина кроется в самом запросе ДинамическогоСписка. Мы можем проанализировать и скорректировать запрос ДинамическогоСписка таким образом, чтобы поле "Проведен" явно возвращалось как булево.

Предположим, что в запросе ДинамическогоСписка поле "Проведен" не выбирается напрямую как Документ.Проведен, а является частью более сложного выражения или вычисляемым полем, тип которого может быть потерян. В этом случае, убедимся, что в тексте запроса оно выбирается корректно, например:


// Пример фрагмента запроса ДинамическогоСписка
// ...
ВЫБРАТЬ
    ДокументРеализацияТоваровУслуг.Ссылка КАК Ссылка,
    ДокументРеализацияТоваровУслуг.Дата КАК Дата,
    ДокументРеализацияТоваровУслуг.Номер КАК Номер,
    ДокументРеализацияТоваровУслуг.Проведен КАК Проведен // Убедитесь, что поле выбирается напрямую
// ...
ИЗ
    Документ.РеализацияТоваровУслуг КАК ДокументРеализацияТоваровУслуг
// ...

Если поле "Проведен" является результатом какого-либо выражения, убедимся, что оно явно приводится к булевому типу:


// Пример для вычисляемого поля, если это необходимо
// ...
ВЫБРАТЬ
    // ...
    ВЫБОР
        КОГДА ДокументРеализацияТоваровУслуг.Проведен ТОГДА ИСТИНА
        ИНАЧЕ ЛОЖЬ
    КОНЕЦ КАК Проведен
// ...

После корректировки запроса ДинамическогоСписка, ПостроительЗапроса, использующий ОписаниеИсточникаДанных(ДокументСписок), должен будет корректно определить тип поля "Проведен", и ошибка "Неверный тип значения" исчезнет. Этот метод является предпочтительным, если мы хотим работать напрямую с ДокументСписок без промежуточных таблиц, так как он исправляет проблему на уровне источника данных.

Вариант 3: Попытка корректировки доступных полей ПостроителяЗапроса (менее надежный)

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

Если поле "Проведен" найдено в Построитель.ДоступныеПоля, но его ТипЗначения равен Неопределенный, мы можем попробовать переопределить это поле или добавить новое с явным указанием типа. Но стоит помнить, что платформа может по-разному реагировать на такие манипуляции в зависимости от версии.


Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ДокументСписок);
Построитель.ЗаполнитьНастройки();

ПолеПроведен = Построитель.ДоступныеПоля.Найти("Проведен");

Если ПолеПроведен = Неопределено Тогда
    // Если поля "Проведен" нет в доступных полях, добавляем его с явным типом.
    ПолеПроведен = Построитель.ДоступныеПоля.Добавить("Проведен", "Булево");
    ПолеПроведен.ПутьКДанным = "Проведен"; // Указываем, откуда брать данные
    ПолеПроведен.Представление = "Проведен";
    ПолеПроведен.ТипЗначения = Новый ОписаниеТипов("Булево");
Иначе
    // Если поле уже существует, но его ТипЗначения некорректен,
    // прямое изменение ТипЗначения может быть невозможно, если оно только для чтения.
    // В этом случае, возможно, придется либо использовать Вариант 1, либо
    // удалить существующее поле и добавить новое, что может повлиять на привязку данных.
    // В большинстве случаев, если ТипЗначения был Неопределенным, его изменение напрямую
    // через этот объект ПолеПостроителяЗапроса не даст желаемого результата.
    // Более надежно исправить тип на уровне источника данных.
КонецЕсли;

// После того как мы убедились в наличии и правильном типе поля "Проведен",
// можем установить отбор.
ПолеПроведен.Отбор = Истина;

ОтборПроведен = Построитель.Отбор.Добавить("Проведен");
ОтборПроведен.Использование = Истина;
ОтборПроведен.ВидСравнения = ВидСравнения.Равно;
ОтборПроведен.Значение = Истина; // Теперь должно работать

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

Этот вариант является менее предпочтительным и может потребовать дополнительного тестирования, так как архитектура ПостроителяЗапроса и его взаимодействия с ОписаниеИсточникаДанных может иметь особенности в разных версиях платформы.

Заключение

Мы выяснили, что ошибка "Неверный тип значения" при отборе по булевому полю "Проведен" в ПостроителеЗапроса возникает из-за некорректного определения типа этого поля в источнике данных. Самый надежный способ решения проблемы — это обеспечить, чтобы ПостроительЗапроса получал информацию о поле "Проведен" с явно заданным типом Булево.

  1. Если мы работаем с ТаблицейЗначений, мы явно указываем тип для колонки "Проведен" при ее создании, как показано в Варианте 1.
  2. Если мы работаем с ДинамическимСписком, убеждаемся, что в его базовом запросе поле "Проведен" выбирается корректно и имеет тип Булево, как описано в Варианте 2.

Применение этих подходов позволит нам избежать ошибки "Неверный тип значения" и успешно использовать ПостроительЗапроса для получения списка проведенных документов с учетом всех интерактивных отборов и интервалов, установленных на форме.

← На главную