Как снять предопределенность или удалить элемент справочника в 1С при ошибке "Поле объекта не обнаружено"?

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

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

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

Понимаем природу предопределенных элементов в 1С

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

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

Разбираем причину ошибки "Поле объекта не обнаружено (ИмяПредопределенныхДанных)"

Первое, что мы должны рассмотреть, когда сталкиваемся с ошибкой "Поле объекта не обнаружено (ИмяПредопределенныхДанных)", это контекст, в котором выполняется наш код, и тип объекта, с которым мы работаем:

  1. Ссылка или Объект? Свойство ИмяПредопределенныхДанных доступно только для объекта справочника, а не для его ссылки. Если мы пытаемся обратиться к этому свойству через ссылку (например, МояСсылка.ИмяПредопределенныхДанных), система выдаст ошибку, поскольку ссылка не содержит данных самого объекта. Всегда следует получать объект перед тем, как пытаться изменить его свойства:

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

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

Ключевое решение: Проверяем и настраиваем режим совместимости

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

Что такое режим совместимости и почему он важен?

Платформа 1С:Предприятие постоянно развивается, и новые версии приносят изменения в работу с данными, включая предопределенные элементы. Режим совместимости позволяет нам запускать конфигурацию на более новой версии платформы, сохраняя при этом поведение, характерное для более старой версии. Например, конфигурация, разработанная для 8.2, может запускаться на 8.3 в режиме совместимости с 8.2. Однако такое «эмулированное» поведение может ограничивать доступ к новым возможностям платформы или изменять способы работы со старыми. В частности, доступность и механизмы работы со свойством ИмяПредопределенныхДанных могли изменяться между версиями платформы.

Как проверить и изменить режим совместимости:

  1. Откроем конфигурацию: Запустите 1С:Предприятие в режиме Конфигуратора.

  2. Перейдем к свойствам конфигурации: В дереве конфигурации выделите самый верхний узел — "Конфигурация" (корневой элемент). Откройте его свойства (обычно это можно сделать через контекстное меню "Свойства" или комбинацией Alt+Enter).

  3. Найдем свойство "Режим совместимости": В окне свойств конфигурации найдите поле "Режим совместимости".

  4. Проанализируем текущее значение: Если у вас установлена более новая версия платформы (например, 8.3.20), но режим совместимости установлен на более старую (например, "Версия 8.2.16"), это может быть причиной проблемы. Изменение режима совместимости на "Не использовать" или на более высокую версию платформы, соответствующую текущей версии платформы, на которой вы работаете, может восстановить корректный доступ к свойству ИмяПредопределенныхДанных.

  5. Применим изменения: После изменения режима совместимости обязательно сохраните конфигурацию (Ctrl+S) и обновите конфигурацию базы данных (F7).

Важно отметить, что изменение режима совместимости может повлечь за собой другие изменения в работе конфигурации, поэтому всегда рекомендуется делать резервные копии информационной базы перед такими действиями и тщательно тестировать функционал после изменений.

Программный подход к снятию предопределенности и удалению

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

Рассмотрим по шагам, как это сделать:

  1. Получаем объект справочника: Нам нужна не ссылка, а сам объект, чтобы иметь возможность изменять его свойства.

    
    // Предположим, у нас есть ссылка на элемент, который нужно изменить
    // Например, если мы работаем в обработке и выбрали текущую строку в таблице:
    // тс = ЭлементыФормы.СправочникСписок.ТекущаяСтрока;
    // СсылкаНаЭлемент = тс.Ссылка;
    
    // Или если мы знаем код или наименование элемента:
    СсылкаНаЭлемент = Справочники.МойСправочник.НайтиПоКоду("000000001");
    // Или
    // СсылкаНаЭлемент = Справочники.МойСправочник.НайтиПоНаименованию("Мой предопределенный элемент");
    
    Если СсылкаНаЭлемент <> Неопределено Тогда
        ОбъектСправочника = СсылкаНаЭлемент.ПолучитьОбъект();
        Если ОбъектСправочника <> Неопределено Тогда
            // Дальнейшие действия
        Иначе
            Сообщить("Не удалось получить объект по ссылке.");
        КонецЕсли;
    Иначе
        Сообщить("Элемент справочника не найден.");
    КонецЕсли;
    
  2. Очищаем свойство ИмяПредопределенныхДанных: Это ключевой шаг для снятия признака предопределенности.

    
    // Продолжение предыдущего блока кода, внутри Если ОбъектСправочника <> Неопределено Тогда
    ОбъектСправочника.ИмяПредопределенныхДанных = "";
    
  3. Записываем изменения: После изменения свойства объект необходимо записать в базу данных.

    
    // Продолжение предыдущего блока кода
    Попытка
        ОбъектСправочника.Записать();
        Сообщить("Признак предопределенности успешно снят для элемента: " + ОбъектСправочника.Наименование);
    Исключение
        Сообщить("Ошибка при записи объекта: " + ОписаниеОшибки());
    КонецПопытки;
    
  4. Помечаем на удаление (если требуется): Теперь, когда элемент не предопределен, мы можем пометить его на удаление стандартным способом.

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

    Обратите внимание, что физическое удаление помеченных объектов происходит с помощью регламентной операции "Удаление помеченных объектов".

Пример кода из сообщений, который демонстрирует комплексный подход:


// Предположим, что 'тс' - это текущая строка в таблице, содержащая ссылку на элемент
// Например, тс = ЭлементыФормы.СправочникСписок.ТекущаяСтрока;
Если тс <> Неопределено Тогда
    // Получаем объект справочника по ссылке
    тОбъект = тс.Ссылка.ПолучитьОбъект();

    // Если объект успешно получен
    Если тОбъект <> Неопределено Тогда
        // Можно изменить другие свойства, например, код или наименование, для уникальности
        // тОбъект.УстановитьНовыйКод; // Если требуется новый код
        // тОбъект.Наименование = тОбъект.Наименование + " " + ТекущаяДата(); // Для изменения наименования

        // Ключевой шаг: очищаем свойство ИмяПредопределенныхДанных
        тОбъект.ИмяПредопределенныхДанных = "";

        // Записываем изменения в базу данных
        Попытка
            тОбъект.Записать();
            Сообщить("" + ТекущаяДата() + " Исправили! Признак предопределенности снят для: " + тОбъект.Наименование);

            // Если элемент теперь нужно удалить, помечаем его на удаление
            // тОбъект.ПометкаУдаления = Истина;
            // тОбъект.Записать();
            // Сообщить("Элемент помечен на удаление: " + тОбъект.Наименование);

        Исключение
            Сообщить("Ошибка при записи объекта: " + ОписаниеОшибки());
        КонецПопытки;
    Иначе
        Сообщить("Не удалось получить объект по ссылке.");
    КонецЕсли;
Иначе
    Сообщить("Строка не выбрана.");
КонецЕсли;

Дополнительные рекомендации и подводные камни

При работе с предопределенными элементами и их удалением могут возникнуть дополнительные нюансы, которые мы должны учитывать:

  1. Права доступа: Для выполнения операций по изменению предопределенности или пометке на удаление предопределенных данных требуются соответствующие права. Убедитесь, что пользователь, под которым выполняется операция, обладает правами ИнтерактивнаяПометкаУдаленияПредопределенныхДанных, ИнтерактивноеУдалениеПредопределенныхДанных и другими необходимыми. Если этих прав нет, даже программный код может выдать ошибку доступа.

  2. "Тестирование и исправление ИБ": В некоторых случаях, особенно после изменения режима совместимости или при возникновении дубликатов предопределенных элементов, может потребоваться выполнить "Тестирование и исправление информационной базы". Функции, такие как "Проверка логической целостности", "Пересчет итогов", "Проверка уникальности записей о предопределенных элементах", могут помочь устранить внутренние несоответствия данных. Обратите внимание, что эту операцию всегда следует выполнять на резервной копии базы.

  3. Что происходит при удалении из конфигурации? Если предопределенный элемент удаляется из конфигурации (т.е. из метаданных), он не удаляется из базы данных. Вместо этого он становится обычным элементом, помеченным на удаление, и признак предопределенности с него снимается. Ссылки на него в других объектах могут сохраняться, пока эти объекты не будут перепроведены или очищены.

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

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

Заключение

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

← На главную