При разработке и сопровождении информационных систем на платформе 1С:Предприятие 8.3 программистам часто приходится сталкиваться с необходимостью работы с предопределенными элементами. Предопределенные элементы — это особые сущности в прикладных объектах конфигурации (таких как справочники, планы счетов), которые задаются разработчиком непосредственно в конфигураторе. Их ключевое преимущество заключается в обеспечении надежного доступа из программного кода по уникальному имени, которое, в отличие от наименования или кода, не может быть изменено пользователем. Это гарантирует стабильное обращение к нужным данным, исключая необходимость ненадежного поиска по изменяемым реквизитам. Давайте подробно разберем, как мы можем программно создавать, привязывать, редактировать и проверять предопределенные элементы.
Важно понимать, что мы не можем создать предопределенный элемент "с нуля" программно таким образом, чтобы он появился в конфигураторе. Предопределенное имя элемента должно быть заранее задано разработчиком в метаданных конфигурации. Наша задача в программном коде — это "привязать" существующий элемент данных в информационной базе к предопределенному элементу, заданному в конфигураторе, или, при необходимости, создать новый элемент данных и присвоить ему это предопределенное имя. Для этих целей используется стандартный реквизит объекта ИмяПредопределенныхДанных.
ИмяПредопределенныхДанных точное имя предопределенного элемента, которое было задано в конфигураторе. Критически важно: присваиваемое имя должно уже существовать в списке предопределенных элементов, определенных в конфигураторе. Попытка присвоить несуществующее имя приведет к ошибке "Предопределенный элемент не существует".Рассмотрим пример программного создания и привязки предопределенного элемента для справочника "ВидыНоменклатуры", если в конфигураторе для него определено предопределенное имя "Материалы":
// В конфигураторе для справочника "ВидыНоменклатуры"
// задан предопределенный элемент с ИменемПредопределенныхДанных = "Материалы"
&НаСервере
Функция ПолучитьИлиСоздатьПредопределенныйВидНоменклатуры()
Перем СсылкаНаВидНоменклатуры;
ИмяПредопределенного = "Материалы";
ВидНоменклатурыНайден = Ложь;
// 1. Попытаемся получить ссылку на предопределенный элемент через его имя
// Этот способ сработает, если элемент уже существует в ИБ и привязан к предопределенному имени
Попытка
СсылкаНаВидНоменклатуры = Справочники.ВидыНоменклатуры[ИмяПредопределенного];
Если СсылкаНаВидНоменклатуры <> Неопределено Тогда
ВидНоменклатурыНайден = Истина;
КонецЕсли;
Исключение
// Если предопределенный элемент еще не создан в ИБ, будет исключение
// (например, "Предопределенный элемент с именем 'Материалы' не найден.")
КонецПопытки;
Если Не ВидНоменклатурыНайден Тогда
// 2. Попытаемся найти элемент в базе данных по ИмениПредопределенныхДанных
// Метод НайтиПоИмениПредопределенныхДанных() возвращает ссылку или Неопределено
СсылкаНаВидНоменклатуры = Справочники.ВидыНоменклатуры.НайтиПоИмениПредопределенныхДанных(ИмяПредопределенного);
Если СсылкаНаВидНоменклатуры <> Неопределено Тогда
ВидНоменклатурыНайден = Истина;
Сообщить("Предопределенный элемент '" + ИмяПредопределенного + "' найден по имени предопределенных данных.");
Иначе
// 3. Если элемент не найден по предопределенному имени, создаем его
Сообщить("Предопределенный элемент '" + ИмяПредопределенного + "' не найден, создаем новый.");
НовыйЭлементОбъект = Справочники.ВидыНоменклатуры.СоздатьЭлемент();
НовыйЭлементОбъект.Наименование = "Материалы"; // Обычно наименование совпадает с предопределенным именем
НовыйЭлементОбъект.ИмяПредопределенныхДанных = ИмяПредопределенного; // Привязываем к предопределенному имени
Попытка
НовыйЭлементОбъект.Записать();
СсылкаНаВидНоменклатуры = НовыйЭлементОбъект.Ссылка;
ВидНоменклатурыНайден = Истина;
Сообщить("Предопределенный элемент '" + ИмяПредопределенного + "' успешно создан и привязан.");
Исключение
Сообщить("Ошибка при создании и привязке предопределенного элемента '" + ИмяПредопределенного + "': " + ОписаниеОшибки());
СсылкаНаВидНоменклатуры = Неопределено;
КонецПопытки;
КонецЕсли;
КонецЕсли;
Возврат СсылкаНаВидНоменклатуры;
КонецФункции
// Пример вызова
// СсылкаНаМатериалы = ПолучитьИлиСоздатьПредопределенныйВидНоменклатуры();
// Если СсылкаНаМатериалы <> Неопределено Тогда
// Сообщить("Работаем с предопределенным видом номенклатуры: " + СсылкаНаМатериалы);
// Иначе
// Сообщить("Не удалось получить или создать предопределенный вид номенклатуры.");
// КонецЕсли;
Содержимое предопределенных элементов (например, наименование, код, значения реквизитов) можно программно изменять точно так же, как и у любых обычных элементов справочника. Для этого мы сначала должны получить объект предопределенного элемента, внести необходимые изменения в его реквизиты и затем записать объект.
Рассмотрим пример, как мы можем изменить наименование предопределенного элемента "Материалы":
&НаСервере
Процедура ОтредактироватьПредопределенныйВидНоменклатуры()
ИмяПредопределенного = "Материалы";
// 1. Получаем объект предопределенного элемента
// Мы можем использовать метод НайтиПоИмениПредопределенныхДанных
// или прямое обращение по имени, если элемент гарантированно существует
ОбъектВидНоменклатуры = Справочники.ВидыНоменклатуры.НайтиПоИмениПредопределенныхДанных(ИмяПредопределенного).ПолучитьОбъект();
Если ОбъектВидНоменклатуры <> Неопределено Тогда
Сообщить("Текущее наименование предопределенного элемента '" + ИмяПредопределенного + "': " + ОбъектВидНоменклатуры.Наименование);
// 2. Вносим изменения в реквизиты
ОбъектВидНоменклатуры.Наименование = "Сырье и материалы";
// Здесь можно изменить и другие реквизиты, например:
// ОбъектВидНоменклатуры.Код = "000000001";
// ОбъектВидНоменклатуры.НекийРеквизит = "Новое значение";
// 3. Записываем объект
Попытка
ОбъектВидНоменклатуры.Записать();
Сообщить("Наименование предопределенного элемента '" + ИмяПредопределенного + "' успешно изменено на: " + ОбъектВидНоменклатуры.Наименование);
Исключение
Сообщить("Ошибка при редактировании предопределенного элемента: " + ОписаниеОшибки());
КонецПопытки;
Иначе
Сообщить("Предопределенный элемент '" + ИмяПредопределенного + "' не найден для редактирования.");
КонецЕсли;
КонецПроцедуры
// Пример вызова
// ОтредактироватьПредопределенныйВидНоменклатуры();
Перед тем как пытаться использовать или редактировать предопределенный элемент, часто возникает необходимость проверить, существует ли он вообще в информационной базе и привязан ли он корректно. Рассмотрим несколько подходов к этой проверке.
ПредопределенноеЗначение()Для получения ссылок на предопределенные элементы в коде можно использовать глобальную функцию ПредопределенноеЗначение(). Она позволяет получить ссылку на предопределенный элемент по его полному имени. Если предопределенный элемент не существует в базе данных, эта функция вызовет исключение, поэтому ее использование требует обертывания в блок Попытка...Исключение.
// Пример использования ПредопределенноеЗначение()
// Допустим, мы проверяем наличие предопределенного элемента Справочника "Валюты" с именем "Рубль"
&НаСервере
Функция ПроверитьНаличиеПредопределеннойВалюты()
Перем СсылкаНаВалюту;
ИмяПредопределенного = "Справочник.Валюты.Рубль";
Попытка
СсылкаНаВалюту = ПредопределенноеЗначение(ИмяПредопределенного);
Сообщить("Ссылка на предопределенный элемент '" + ИмяПредопределенного + "': " + СсылкаНаВалюту);
Возврат Истина;
Исключение
Сообщить("Ошибка: Предопределенный элемент '" + ИмяПредопределенного + "' отсутствует в информационной базе или недоступен. " + ОписаниеОшибки());
Возврат Ложь;
КонецПопытки;
КонецФункции
// Пример вызова
// Если ПроверитьНаличиеПредопределеннойВалюты() Тогда
// Сообщить("Предопределенная валюта 'Рубль' существует.");
// Иначе
// Сообщить("Предопределенная валюта 'Рубль' отсутствует.");
// КонецЕсли;
В конфигурациях, которые используют Библиотеку стандартных подсистем (БСП) версии 2.1.4 и выше, для проверки наличия предопределенного элемента рекомендуется использовать функцию ПредопределенныйЭлемент из общих модулей ОбщегоНазначения или ОбщегоНазначенияКлиент. Эта функция возвращает значение Неопределено, если предопределенный элемент отсутствует в информационной базе, что является более удобным способом проверки, так как не требует использования блока Попытка...Исключение. При этом серверный вызов происходит только при первом обращении, а результат автоматически кешируется для оптимизации производительности.
// Пример использования функции БСП ПредопределенныйЭлемент
// Предполагается, что БСП подключена и доступны общие модули, например "ОбщегоНазначения".
&НаСервере
Функция ПроверитьНаличиеПредопределеннойВалютыБСП()
Перем СсылкаНаВалютуБСП;
ИмяПредопределенного = "Справочник.Валюты.Рубль";
// Функция возвращает ссылку на предопределенный элемент или Неопределено
СсылкаНаВалютуБСП = ОбщегоНазначения.ПредопределенныйЭлемент(ИмяПредопределенного);
Если СсылкаНаВалютуБСП <> Неопределено Тогда
Сообщить("Ссылка на предопределенный элемент '" + ИмяПредопределенного + "' (БСП): " + СсылкаНаВалютуБСП);
Возврат Истина;
Иначе
Сообщить("Предопределенный элемент '" + ИмяПредопределенного + "' отсутствует в информационной базе (БСП).");
Возврат Ложь;
КонецЕсли;
КонецФункции
// Пример вызова
// Если ПроверитьНаличиеПредопределеннойВалютыБСП() Тогда
// Сообщить("Предопределенная валюта 'Рубль' существует (проверено БСП).");
// Иначе
// Сообщить("Предопределенная валюта 'Рубль' отсутствует (проверено БСП).");
// КонецЕсли;
С помощью метода метаданных ПолучитьИменаПредопределенных() мы можем получить список всех предопределенных имен, заданных в конфигураторе для конкретного объекта конфигурации (например, справочника). Это позволяет проверить, задано ли вообще такое имя в конфигурации.
// Пример получения списка предопределенных имен для справочника "Валюты"
&НаСервере
Процедура ПоказатьИменаПредопределенныхВалют()
// Получим список всех предопределенных имен для справочника "Валюты"
МассивИмен = Метаданные.Справочники.Валюты.ПолучитьИменаПредопределенных();
Если МассивИмен.Количество() > 0 Тогда
Сообщить("Список предопределенных имен для справочника 'Валюты', заданных в конфигурации:");
Для Каждого ИмяПредопределенного Из МассивИмен Цикл
Сообщить("- " + ИмяПредопределенного);
КонецЦикла;
Иначе
Сообщить("Для справочника 'Валюты' предопределенные элементы в конфигурации не заданы.");
КонецЕсли;
КонецПроцедуры
// Пример вызова
// ПоказатьИменаПредопределенныхВалют();
Иногда возникает необходимость "отвязать" элемент данных от предопределенного имени, сделав его обычным элементом справочника. Для этого достаточно присвоить реквизиту ИмяПредопределенныхДанных пустую строку и записать объект. После этой операции элемент потеряет свою "предопределенность", хотя сама запись в базе данных останется.
&НаСервере
Процедура ОтвязатьПредопределенныйВидНоменклатуры()
ИмяПредопределенного = "Материалы"; // Имя, которое мы хотим отвязать
ОбъектВидНоменклатуры = Справочники.ВидыНоменклатуры.НайтиПоИмениПредопределенныхДанных(ИмяПредопределенного).ПолучитьОбъект();
Если ОбъектВидНоменклатуры <> Неопределено Тогда
Сообщить("Текущее ИмяПредопределенныхДанных элемента: " + ОбъектВидНоменклатуры.ИмяПредопределенныхДанных);
// Присваиваем пустую строку реквизиту ИмяПредопределенныхДанных
ОбъектВидНоменклатуры.ИмяПредопределенныхДанных = "";
Попытка
ОбъектВидНоменклатуры.Записать();
Сообщить("Элемент '" + ОбъектВидНоменклатуры.Наименование + "' успешно отвязан от предопределенного имени.");
Исключение
Сообщить("Ошибка при отвязке элемента: " + ОписаниеОшибки());
КонецПопытки;
Иначе
Сообщить("Предопределенный элемент '" + ИмяПредопределенного + "' не найден для отвязки.");
КонецЕсли;
КонецПроцедуры
// Пример вызова
// ОтвязатьПредопределенныйВидНоменклатуры();
Платформа 1С:Предприятие предоставляет механизмы для автоматического обновления предопределенных элементов, особенно при обновлении конфигураций. У объектов конфигурации, которые могут иметь предопределенные элементы, есть свойство ОбновлениеПредопределенныхДанных. Оно определяет, как платформа будет создавать и обновлять предопределенные элементы в информационной базе. Возможные значения:
Авто (значение по умолчанию): Платформа автоматически создает недостающие предопределенные элементы при обновлении конфигурации.ОбновлятьАвтоматически: Аналогично Авто, но явно указывает на автоматическое обновление.НеОбновлятьАвтоматически: Платформа не будет автоматически создавать или обновлять предопределенные элементы. В этом случае ответственность за их наличие и актуальность ложится на разработчика/администратора.В большинстве случаев рекомендуется оставлять значение Авто, так как это обеспечивает надежное автоматическое создание элементов.
Библиотека стандартных подсистем (БСП) предоставляет ряд полезных функций для более глубокой работы с предопределенными данными, особенно в контексте обслуживания информационной базы:
ПроверитьОтсутствующиеПредопределенныеЭлементы в общем модуле КонтрольВеденияУчетаСлужебный позволяет выявить недостающие предопределенные элементы в базе данных.ВосстановитьПредопределенныеЭлементы в общем модуле СтандартныеПодсистемыСервер, которая создает недостающие предопределенные элементы с новыми ссылками. Это особенно актуально после отключения подчиненного узла распределенной информационной базы от главного, когда предопределенные элементы могли не синхронизироваться.Мы рекомендуем активно использовать функционал БСП для управления предопределенными данными, поскольку это способствует стабильности и автоматизации многих рутинных операций. Для изучения других возможностей библиотеки пригодится справочник по методам БСП с примерами использования.
При работе с предопределенными элементами важно учитывать несколько ключевых аспектов:
ИмяПредопределенныхДанных изменить нельзя.ИмяПредопределенныхДанных очищается, и элемент становится обычным.Работа с предопределенными элементами является неотъемлемой частью разработки на платформе 1С:Предприятие. Понимание принципов их создания, редактирования, проверки и использования в различных сценариях, а также знание возможностей, предоставляемых БСП, позволяет нам создавать более надежные, поддерживаемые и функциональные решения. При техническом обслуживании систем и их автоматизированном обновлении применяется программа для архивации и тестирования баз 1С, работающая в фоновом режиме.