При повседневной работе в 1C:Бухгалтерия пользователи нередко сталкиваются с ситуацией, когда документы по определенному контрагенту перестают открываться. Платформа аварийно прерывает операцию с системным сообщением: «Значение не является значением объектного типа (Выбрать)». При этом аналогичные документы других контрагентов функционируют в штатном режиме. Разберем по шагам, почему возникает данный сбой, как локализовать проблемное место в коде и какими инструментами восстановить целостность информационной базы.
Проанализируем механику работы типовых конфигураций. При открытии формы документа Реализация (акты, накладные) срабатывают процедуры инициализации контактной информации участников сделки: контрагента, грузополучателя, грузоотправителя, а также их адресов доставки. Если мы обратимся к стеку вызовов ошибки, то увидим обращение к общему модулю:
{ОбщийМодуль.УправлениеКонтактнойИнформациейБП.Модуль(423)}: Значение не является значением объектного типа (Выбрать)
Сбой происходит на строке вызова метода выборки данных:
Выборка = ИсторияАдреса.Выбрать;
Выясним причину такого поведения платформы. Метод Выбрать() применяется к результатам запроса или выборкам данных. Переменная ИсторияАдреса ожидает получить объектный тип, однако вместо него функция чтения реквизитов возвращает значение Неопределено. Это происходит в тех случаях, когда:
Грузополучатель, БанковскийСчет, ДоговорКонтрагента) хранится «битая» ссылка вида <Объект не найден...>. Объект был удален непосредственно из базы, но ссылки на него в документе остались.КонтактнаяИнформация контрагента — реквизит Вид ссылается на несуществующий элемент справочника ВидыКонтактнойИнформации.Рассмотрим, как правильно локализовать сбойную ссылку. Для этого запустим конфигуратор, установим точку останова в функции чтения реквизитов или включим режим остановки по ошибке через меню Отладка -> Остановка по ошибке.
Если база работает в клиент-серверном режиме (SQL), убедимся, что служба сервера 1С запущена с параметром -debug, иначе точки останова в серверных общих модулях срабатывать не будут.
Посмотрим на типовую функцию получения данных в общем модуле ОбщегоНазначения:
Функция ЗначенияРеквизитовОбъекта(Ссылка, Знач Реквизиты) Экспорт
Если ТипЗнч(Реквизиты) = Тип("Строка") Тогда
Если ПустаяСтрока(Реквизиты) Тогда
Возврат Новый Структура;
КонецЕсли;
Реквизиты = СтрРазделить(Реквизиты, ",", Ложь);
КонецЕсли;
СтруктураРеквизитов = Новый Структура;
Если ТипЗнч(Реквизиты) = Тип("Структура") Или ТипЗнч(Реквизиты) = Тип("ФиксированнаяСтруктура") Тогда
СтруктураРеквизитов = Реквизиты;
ИначеЕсли ТипЗнч(Реквизиты) = Тип("Массив") Или ТипЗнч(Реквизиты) = Тип("ФиксированныйМассив") Тогда
Для Каждого Реквизит Из Реквизиты Цикл
СтруктураРеквизитов.Вставить(СтрЗаменить(Реквизит, ".", ""), Реквизит);
КонецЦикла;
КонецЕсли;
ТекстПолей = "";
Для Каждого КлючИЗначение Из СтруктураРеквизитов Цикл
ИмяПоля = ?(ЗначениеЗаполнено(КлючИЗначение.Значение), СокрЛП(КлючИЗначение.Значение), СокрЛП(КлючИЗначение.Ключ));
Псевдоним = СокрЛП(КлючИЗначение.Ключ);
ТекстПолей = ТекстПолей + ?(ПустаяСтрока(ТекстПолей), "", ",") + " | " + ИмяПоля + " КАК " + Псевдоним;
КонецЦикла;
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Запрос.Текст =
"ВЫБРАТЬ |" + ТекстПолей + " |ИЗ | " + Ссылка.Метаданные.ПолноеИмя + " КАК ПсевдонимЗаданнойТаблицы |ГДЕ | ПсевдонимЗаданнойТаблицы.Ссылка = &Ссылка |";
Выборка = Запрос.Выполнить().Выбрать();
Выборка.Следующий();
Результат = Новый Структура;
Для Каждого КлючИЗначение Из СтруктураРеквизитов Цикл
Результат.Вставить(КлючИЗначение.Ключ);
КонецЦикла;
ЗаполнитьЗначенияСвойств(Результат, Выборка);
Возврат Результат;
КонецФункции
В момент остановки проанализируем значение параметра Ссылка. Если в параметре отображается <Объект не найден...>, то попытка обратиться к Ссылка.Метаданные возвращает ошибку или пустой результат, из-за чего модуль управления контактной информацией получает Неопределено вместо реальной выборки адреса.
Разберем наиболее надежный и штатный способ восстановления целостности данных. Стандартный запуск процедуры с параметрами по умолчанию часто не дает результата, так как для ссылочных ошибок по умолчанию установлен режим «Ничего не делать».
Выполним процедуру правильно:
.dt или бэкап средствами СУБД).Рассмотрим вариант, когда тестирование всей базы занимает слишком много времени или нет возможности монопольного захвата базы. Исправить битый реквизит в конкретном документе можно в режиме предприятия:
Если доступ к документу заблокирован, разберем, как программно прочитать и перезаписать проблемный объект с помощью внешней обработки или консоли кода без вызова клиентских процедур формы:
ДокументСсылка = Документы.РеализацияТоваровУслуг.НайтиПоНомеру("НомерДокумента", ТекущаяДата());
ДокОбъект = ДокументСсылка.ПолучитьОбъект();
// Проверим целостность реквизита Грузополучатель
Если ДокОбъект.Грузополучатель.ПолучитьОбъект() = Неопределено Тогда
// Заменим битую ссылку на основного контрагента
ДокОбъект.Грузополучатель = ДокОбъект.Контрагент;
КонецЕсли;
// Проверим реквизит ДоговорКонтрагента
Если ДокОбъект.ДоговорКонтрагента.ПолучитьОбъект() = Неопределено Тогда
ДокОбъект.ДоговорКонтрагента = Справочники.ДоговорыКонтрагентов.ПустаяСсылка();
КонецЕсли;
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
После устранения поврежденной ссылки структура реквизитов объекта восстанавливается, функция ЗначенияРеквизитовОбъекта возвращает корректные типы данных, и документ реализации открывается без ошибок.