При переносе данных между конфигурациями (например, из «1С:Документооборот 1.3» в «1С:Документооборот 2.1») разработчики часто сталкиваются с необходимостью выгрузить элементы справочников выборочно — за определенный период или по конкретным условиям. В процессе настройки правил в конфигурации «1С:Конвертация данных 2.1» (КД) могут возникнуть неочевидные логические ошибки и сбои контекста выполнения кода. В этой статье мы подробно разберем, как правильно реализовать выгрузку данных по параметрам, исправить логические нестыковки в условиях и устранить частую ошибку Значение не является значением объектного типа.
Рассмотрим стандартную ситуацию. Разработчику необходимо выгрузить элементы справочника ИсходящиеДокументы за определенный период, например, за январь 2019 года. Для этого в правилах обмена создаются два параметра: ДатаНач (01.01.2019) и ДатаКон (31.01.2019). Начинающие специалисты часто пишут код фильтрации в обработчике «Перед выгрузкой» следующим образом:
Если Объект.ДатаРегистрации <= Параметры.ДатаНач И Объект.ДатаРегистрации >= Параметры.ДатаКон Тогда
Отказ = ИСТИНА;
КонецЕсли;
Проанализируем этот код. В данном условии используется логический оператор И. Для того чтобы сработал отказ от выгрузки (Отказ = ИСТИНА), дата регистрации документа должна быть одновременно меньше или равна начальной дате (01.01.2019) И больше или равна конечной дате (31.01.2019). Физически ни одна дата не может отвечать этому условию одновременно. В результате условие никогда не выполняется, и система выгружает абсолютно все документы без фильтрации.
Для исправления этой логической ошибки нам необходимо использовать оператор ИЛИ либо применить отрицание. Рассмотрим правильные варианты написания кода:
Вариант 1. Использование логического оператора ИЛИ:
Если Объект.ДатаРегистрации < Параметры.ДатаНач ИЛИ Объект.ДатаРегистрации > Параметры.ДатаКон Тогда
Отказ = ИСТИНА;
КонецЕсли;
Этот вариант наиболее прост для понимания: если дата документа выходит за рамки нашего диапазона (меньше начала либо больше окончания), мы отказываемся от его выгрузки.
Вариант 2. Отрицание вхождения в диапазон:
Если НЕ (Объект.ДатаРегистрации >= Параметры.ДатаНач И Объект.ДатаРегистрации <= Параметры.ДатаКон) Тогда
Отказ = ИСТИНА;
КонецЕсли;
Здесь мы явно задаем диапазон отбора, а оператор НЕ отсекает всё, что в него не попадает.
Использование обработчика «Перед выгрузкой» в правилах выгрузки данных (ПВД) со стандартной выборкой — очень неэффективное решение для баз с большим объемом данных, таких как «1С:Документооборот».
Выясним причину низкой скорости работы. При стандартном способе выборки платформа «1С:Предприятие» сначала считывает из базы данных абсолютно все документы справочника, создает для каждого из них объект в оперативной памяти и только после этого запускает код обработчика «Перед выгрузкой». Если в вашей базе сотни тысяч документов, а выгрузить нужно всего сто за один месяц, система все равно прогонит через память терабайты информации. Это приведет к колоссальному падению скорости обмена и риску получить ошибку Недостаточно памяти.
Для оптимизации процесса мы рекомендуем перевести ПВД в режим «Произвольный алгоритм» и выбирать документы запросом на уровне СУБД. Пошагово разберем, как это сделать:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ИсходящиеДокументы.Ссылка КАК Ссылка
|ИЗ
| Справочник.ИсходящиеДокументы КАК ИсходящиеДокументы
|ГДЕ
| ИсходящиеДокументы.ДатаРегистрации МЕЖДУ &ДатаНач И &ДатаКон";
Запрос.УстановитьПараметр("ДатаНач", Параметры.ДатаНач);
// Важно использовать КонецДня для конечной даты, чтобы захватить документы, созданные в последний день периода
Запрос.УстановитьПараметр("ДатаКон", КонецДня(Параметры.ДатаКон));
ВыборкаДанных = Запрос.Выполнить().Выгрузить();
При таком подходе база данных вернет только строго подходящие под период документы, а скорость выполнения выгрузки возрастет в десятки раз.
Вторая частая проблема возникает при попытке наложить фильтр по дополнительным реквизитам справочника. Например, нам нужно отсечь недействительные элементы:
Если Объект.Недействителен = ИСТИНА Тогда
Отказ = ИСТИНА;
КонецЕсли;
При выполнении этого кода система может выдать критическую ошибку: Значение не является значением объектного типа (Недействителен). Выясним, почему это происходит и как исправить ситуацию.
В КД 2.1 крайне важно понимать, в каком именно обработчике выполняется код:
Объект.Источник (при этом переменной Объект в этом контексте не существует либо она равна Неопределено).Если вы скопировали код из ПВД в ПКО (например, в обработчик «Перед выгрузкой» ПКО), то обращение к Объект.Недействителен вызовет указанную ошибку, так как система попытается прочитать свойство у пустого значения. Правильный код для ПКО должен выглядеть следующим образом:
Если Источник.Недействителен Тогда
Отказ = ИСТИНА;
КонецЕсли;
Если справочник является иерархическим (содержит папки и элементы), то при выгрузке система обрабатывает в том числе и группы (папки). У групп справочника в метаданных может отсутствовать реквизит Недействителен (он назначен только для элементов). Попытка прочитать этот реквизит у папки вызовет ошибку объектного типа.
Решением является предварительная проверка на то, является ли объект группой:
// Пример для ПКО с проверкой на группу
Если Источник.ЭтоГруппа Тогда
// Если папки выгружать не нужно, раскомментируйте строку ниже:
// Отказ = ИСТИНА;
ИначеЕсли Источник.Недействителен Тогда
Отказ = ИСТИНА;
КонецЕсли;
В некоторых случаях в обработчик ПКО может передаваться незаполненная ссылка или объект, который был удален из базы данных (так называемая «битая ссылка»). Обращение к реквизитам такого объекта напрямую через точку вызывает ошибку. Чтобы обезопасить код, рекомендуется выполнять предварительную проверку на заполненность:
Если НЕ ЗначениеЗаполнено(Источник) Тогда
Отказ = ИСТИНА;
ИначеЕсли Источник.Недействителен Тогда
Отказ = ИСТИНА;
КонецЕсли;
Применяя данные подходы и учитывая специфику контекстов КД 2.1, мы сможем создавать быстрые, надежные и отказоустойчивые правила обмена данными между любыми конфигурациями 1С.