Иногда при работе с базами данных 1С (например, в конфигурации «Бухгалтерия государственного учреждения 2.0») пользователи сталкиваются с нестандартным поведением системы. Проанализируем ситуацию: мы пытаемся поставить пометку на удаление на элемент подчиненного справочника (например, «Спецификации номенклатуры»), но платформа блокирует действие и выдает сообщение вида: «Значение поля "Номенклатура" не заполнено или заполнено неверно [ОшибкаХранимыхДанных]». Рассмотрим подробнее, почему возникает этот конфликт и как мы можем от него избавиться.
Для начала разберем по шагам логику работы платформы 1С. Ошибка возникает из-за того, что при попытке поставить пометку на удаление интерактивно (через интерфейс) платформа 1С фактически выполняет действие записи объекта в базу данных. В момент записи система меняет системное свойство ПометкаУдаления на значение Истина.
Как только инициируется запись, платформа запускает системный контроль заполнения всех обязательных реквизитов. В случае со справочником «Спецификации номенклатуры» он является подчиненным справочнику «Номенклатура». Наличие владельца (самой номенклатуры) строго обязательно на уровне структуры метаданных. Поскольку поле владельца оказалось пустым — например, из-за сбоя при обмене данными, некорректной программной загрузки или сбоя транзакции — система блокирует сохранение объекта в базу. Платформе неважно, что наша конечная цель — просто удалить этот объект; она не позволяет сохранить «битую» запись.
Часто в подобных случаях администраторы или пользователи пытаются прибегнуть к радикальным мерам и жмут сочетание клавиш для интерактивного непосредственного удаления — Shift + Del. Посмотрим, почему этот метод не помогает.
Интерактивное непосредственное удаление объекта минует корзину (пометку на удаление), однако в современных конфигурациях на управляемых формах (к которым относится БГУ 2.0) право ИнтерактивноеУдаление обычно снято абсолютно для всех ролей, включая администраторов с полными правами. Это сделано специально для защиты ссылочной целостности базы данных. Более того, даже если бы у нас программно были включены такие права, встроенные обработчики форм могли бы заблокировать операцию еще до ее начала из-за невалидной (битой) ссылки и отсутствующего владельца.
Посмотрим на примеры программного решения задачи, которые гарантированно избавят нас от битого элемента справочника.
Способ 1. Непосредственное удаление через код
Самый быстрый способ — это физическое удаление объекта из базы данных с помощью метода Удалить(). В отличие от установки пометки на удаление, этот метод осуществляет непосредственное удаление записи, не выполняя стандартную процедуру записи измененного объекта. А значит, мы успешно обходим системные проверки на заполненность обязательных полей.
Для выполнения этого кода можно использовать любую внешнюю обработку для выполнения произвольного кода. Напишем следующий фрагмент:
// Получаем объект из проблемной ссылки
ОбъектУдаления = ТвояБитаяСсылка.ПолучитьОбъект();
Если ОбъектУдаления <> Неопределено Тогда
// Выполняем непосредственное удаление минуя проверки записи
ОбъектУдаления.Удалить();
КонецЕсли;
Способ 2. Установка пометки через режим обмена данными
Если непосредственное удаление по каким-то причинам недопустимо (например, мы хотим сохранить след удаления или дождаться стандартного регламентного удаления помеченных объектов), мы можем записать объект, отключив проверки платформы. Используем для этого классический прием работы с «битыми» данными — свойство ОбменДанными.Загрузка.
Установка этого флага говорит платформе, что объект записывается в режиме обмена узлов распределенной информационной базы. Это автоматически отключает большинство проверок платформы на заполненность и игнорирует бизнес-логику (отключает проверки в обработчиках событий ПередЗаписью и ПриЗаписи).
Рассмотрим, как выглядит такой код:
ОбъектДляУдаления = ТвояБитаяСсылка.ПолучитьОбъект();
// Устанавливаем флаг пометки на удаление
ОбъектДляУдаления.УстановитьПометкуУдаления(Истина);
// Отключаем проверки перед записью
ОбъектДляУдаления.ОбменДанными.Загрузка = Истина;
// Безопасно сохраняем объект
ОбъектДляУдаления.Записать();
Что делать, если у нас нет навыков программирования и мы не умеем выполнять код в конфигураторе или режиме предприятия? Разберем по шагам, как исправить подобную ошибку через стандартный пользовательский интерфейс 1С.
Для этого мы воспользуемся встроенной универсальной обработкой системы.
Спецификации номенклатуры) и с помощью отбора (ссылки) найдем наш битый (проблемный) элемент.Владелец (или Номенклатура) и принудительно укажем в качестве нового значения любую существующую в базе позицию номенклатуры.После того как у нашего битого объекта искусственно появится владелец, он перестанет считаться невалидным. Ошибка системного контроля уйдет, и мы сможем штатно пометить его на удаление привычным способом (через кнопку или клавишу Del), а затем навсегда удалить из базы через стандартную процедуру Удаление помеченных объектов.