Как программно работать с дополнительными реквизитами документа в 1С:Предприятии?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Понимание архитектуры дополнительных реквизитов

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

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

  2. Хранение в табличной части: Значения дополнительных реквизитов хранятся непосредственно в самом объекте (документе, справочнике и т.д.) в специальной табличной части. Часто эта табличная часть называется ДополнительныеРеквизиты (как было упомянуто в сообщении 3).

  3. Компоненты дополнительного реквизита: Каждая строка этой табличной части содержит, как минимум, две важные колонки:

    • Свойство: Это не просто строка с наименованием реквизита! Это ссылка на элемент ПланаВидовХарактеристик ДополнительныеРеквизитыИСведения. Именно этот элемент описывает сам дополнительный реквизит: его наименование, тип значения, принадлежность к объекту и другие параметры. У этого элемента есть поле Имя, которое удобно использовать для программного обращения, поскольку оно гарантированно уникально и стабильно.

    • Значение: Это собственно значение дополнительного реквизита (например, строка, число, булево, ссылка на справочник). Тип этого значения определяется типом, указанным в соответствующем элементе Свойства.

  4. Управление БСП: Весь механизм дополнительных реквизитов реализуется подсистемами БСП (Библиотека стандартных подсистем). Это означает, что для удобной работы с ними программно существуют специальные функции в общих модулях БСП, таких как УправлениеСвойствами.

Включение и создание дополнительных реквизитов в пользовательском режиме

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

  1. Включение функциональной опции: Первым делом убедитесь, что в вашей базе включена функциональная опция "Использовать дополнительные реквизиты и сведения". Мы найдем ее в разделе "НСИ и администрирование" (или "Администрирование") – "Общие настройки" – "Свойства". Установите флажок для этой опции.

  2. Добавление дополнительного реквизита: После включения опции появится гиперссылка "Дополнительные реквизиты". Перейдем по ней. Здесь мы можем создать новый дополнительный реквизит.

    • Наименование: Присвоим реквизиту понятное наименование.

    • Тип значения: Выберем подходящий тип (например, "Строка", "Число", "Булево", "Дата", или даже "Дополнительное значение" для выбора из предопределенного списка).

    • Объект: Укажем, к какому объекту будет относиться этот реквизит (например, к документу "Заказ покупателя"). Мы также можем настроить его применение для всех элементов объекта или для определенной группы.

После сохранения эти реквизиты будут доступны для заполнения на форме соответствующего объекта в специальной группе (часто называемой "ГруппаДополнительныеРеквизиты").

Программное чтение значений дополнительных реквизитов

Для чтения значений дополнительных реквизитов мы можем использовать несколько подходов: прямой запрос к табличной части или функции БСП. Рассмотрим каждый из них.

Чтение с помощью запроса

Самый прямой и эффективный способ получить данные из табличной части ДополнительныеРеквизиты – это использовать запрос. Автор темы (Сообщение 2) уже предоставил отличный пример такого запроса, хотя изначально испытывал затруднения с правильной передачей параметра Свойство.

Давайте проанализируем этот запрос и разберем его по шагам.


Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
 | ЗаказПокупателяДополнительныеРеквизиты.Значение КАК Значение,
 | ЗаказПокупателяДополнительныеРеквизиты.ТекстоваяСтрока КАК ТекстоваяСтрока,
 | ЗаказПокупателяДополнительныеРеквизиты.Свойство КАК Свойство,
 | ЗаказПокупателяДополнительныеРеквизиты.Свойство.Наименование КАК НаименованиеСвойства
 ИЗ
 | Документ.ЗаказПокупателя.ДополнительныеРеквизиты КАК ЗаказПокупателяДополнительныеРеквизиты
 ГДЕ
 | ЗаказПокупателяДополнительныеРеквизиты.Ссылка = &Ссылка
// | И ЗаказПокупателяДополнительныеРеквизиты.Свойство = &Свойство";

В этом запросе мы:

  1. Выбираем необходимые поля:

    • ЗаказПокупателяДополнительныеРеквизиты.Значение: Это само значение дополнительного реквизита.
    • ЗаказПокупателяДополнительныеРеквизиты.ТекстоваяСтрока: Это поле может быть полезно для получения строкового представления значения, если основной тип значения не строка.
    • ЗаказПокупателяДополнительныеРеквизиты.Свойство: Это ссылка на элемент ПланаВидовХарактеристик ДополнительныеРеквизитыИСведения.
    • ЗаказПокупателяДополнительныеРеквизиты.Свойство.Наименование: Из ссылки на свойство мы можем получить его наименование, что удобно для идентификации.
  2. Указываем источник данных: Документ.ЗаказПокупателя.ДополнительныеРеквизиты – это имя табличной части документа, где хранятся наши данные.

  3. Фильтруем по ссылке: Мы обязательно указываем ГДЕ ЗаказПокупателяДополнительныеРеквизиты.Ссылка = &Ссылка, чтобы получить дополнительные реквизиты конкретного документа.

Далее нам необходимо установить параметры и выполнить запрос:


Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект); // Передаем ссылку на наш документ
ТЧ_запроса = Запрос.Выполнить().Выгрузить(); // Выгружаем результат в табличную часть

// Или можно пройти по выборке
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    НаименованиеДопРеквезита = Выборка.НаименованиеСвойства; // Получаем наименование свойства
    ЗначениеРеквезита = Выборка.Значение; // Получаем значение реквизита
    Сообщить("Свойство: " + НаименованиеДопРеквезита + ", Значение: " + ЗначениеРеквезита);
КонецЦикла;

Важный момент с параметром &Свойство: В исходном запросе автора закомментирована строка И ЗаказПокупателяДополнительныеРеквизиты.Свойство = &Свойство. Если бы мы захотели получить значение конкретного дополнительного реквизита, нам нужно было бы раскомментировать эту строку и передать в параметр &Свойство не строковое наименование, а ссылку на соответствующий элемент ПланаВидовХарактеристик ДополнительныеРеквизитыИСведения. Получить такую ссылку можно, например, по наименованию или по уникальному имени свойства.


// Пример получения ссылки на свойство по его Имени (рекомендуется)
ИмяСвойства = "МойГлавныйДопРеквизит"; // Это то самое 'Имя', которое мы задавали в пользовательском режиме
СсылкаНаСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию(ИмяСвойства); // Если Имя совпадает с Наименованием
// Или:
// СсылкаНаСвойство = УправлениеСвойствами.ПолучитьСвойствоПоИмени(ИмяСвойства, Метаданные.Документы.ЗаказПокупателя);

Если СсылкаНаСвойство <> Неопределено Тогда
    Запрос.Текст =
    "ВЫБРАТЬ
     | ЗаказПокупателяДополнительныеРеквизиты.Значение КАК Значение
     ИЗ
     | Документ.ЗаказПокупателя.ДополнительныеРеквизиты КАК ЗаказПокупателяДополнительныеРеквизиты
     ГДЕ
     | ЗаказПокупателяДополнительныеРеквизиты.Ссылка = &Ссылка
     | И ЗаказПокупателяДополнительныеРеквизиты.Свойство = &Свойство";

    Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);
    Запрос.УстановитьПараметр("Свойство", СсылкаНаСвойство);

    РезультатЗапроса = Запрос.Выполнить();
    Если РезультатЗапроса.Пустой() Тогда
        Сообщить("Значение дополнительного реквизита не найдено.");
    Иначе
        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий();
        ЗначениеКонкретногоРеквизита = Выборка.Значение;
        Сообщить("Значение конкретного реквизита '" + ИмяСвойства + "': " + ЗначениеКонкретногоРеквизита);
    КонецЕсли;
Иначе
    Сообщить("Свойство с именем '" + ИмяСвойства + "' не найдено.");
КонецЕсли;

Использование УправлениеСвойствами.ПолучитьСвойствоПоИмени() является более надежным способом, так как оно учитывает принадлежность свойства к конкретному объекту и его внутреннее имя, которое может отличаться от наименования.

Чтение с использованием функций БСП

БСП предоставляет набор удобных функций для работы с дополнительными реквизитами. Одну из таких функций мы найдем в общем модуле УправлениеСвойствами. Наиболее подходящей для получения значения конкретного свойства является функция ЗначениеСвойства().


// Предполагаем, что СсылкаНаОбъект - это ссылка на ваш документ (например, Документ.ЗаказПокупателя)
// ИмяСвойства - это уникальное имя дополнительного реквизита (например, "МойВажныйРеквизит")

// 1. Получим ссылку на сам объект свойства
// Используем функцию БСП для получения элемента ПланаВидовХарактеристик по его имени и типу владельца
ТипВладельцаСвойства = Метаданные.Документы.ЗаказПокупателя; // Например
ЭлементСвойства = УправлениеСвойствами.ПолучитьСвойствоПоИмени(ИмяСвойства, ТипВладельцаСвойства);

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

Этот подход более высокоуровневый и рекомендуем к использованию, так как он инкапсулирует логику работы с табличной частью и планом видов характеристик, делая код более читаемым и устойчивым к изменениям во внутренней структуре БСП.

Программная запись (изменение) значений дополнительных реквизитов

Для записи или изменения значений дополнительных реквизитов также используются функции БСП из общего модуля УправлениеСвойствами. Наиболее подходящей для этой задачи является функция ЗаписатьСвойстваУОбъекта(), упомянутая в Сообщении 11.

Давайте посмотрим, как использовать эту функцию.


// Предполагаем, что ОбъектДляИзменения - это объект документа, который мы хотим изменить
// (например, ДокументОбъект.ЗаказПокупателя)
// НовоеЗначениеРеквизита - это значение, которое мы хотим установить

// 1. Создадим структуру со свойствами и их значениями, которые хотим записать
СтруктураЗначений = Новый Структура;

ИмяСвойства1 = "МойВажныйРеквизит1";
НовоеЗначение1 = "Новое строковое значение";
СтруктураЗначений.Вставить(ИмяСвойства1, НовоеЗначение1);

ИмяСвойства2 = "МойБулевыйРеквизит";
НовоеЗначение2 = Истина;
СтруктураЗначений.Вставить(ИмяСвойства2, НовоеЗначение2);

// Если нам нужно удалить значение свойства, мы можем передать Неопределено
// ИмяСвойства3 = "РеквизитДляУдаления";
// СтруктураЗначений.Вставить(ИмяСвойства3, Неопределено);

// 2. Вызовем функцию БСП для записи свойств
// Параметры:
//   Объект - объект, для которого записываем свойства (например, ДокументОбъект.ЗаказПокупателя)
//   СтруктураЗначений - структура, где ключ - Имя свойства, значение - новое значение свойства
//   ЗаписыватьОбъект - булево, нужно ли записывать сам объект после изменения свойств (обычно Истина)
УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(ОбъектДляИзменения, СтруктураЗначений, Истина);

// После записи свойств, объект должен быть сохранен, если ЗаписыватьОбъект = Истина
// или если вы управляете записью вручную.
// Например, если ЗаписыватьОбъект = Ложь, то после вызова функции необходимо выполнить:
// ОбъектДляИзменения.Записать();

Функция ЗаписатьСвойстваУОбъекта() автоматически находит нужные элементы ПланаВидовХарактеристик по их именам, проверяет типы и записывает значения в табличную часть ДополнительныеРеквизиты объекта. Она является мощным инструментом для пакетного изменения свойств.

Программное удаление дополнительных реквизитов

Понятие "удаление дополнительного реквизита" может относиться к двум разным вещам:

  1. Удаление определения самого реквизита: Это означает удаление элемента из ПланаВидовХарактеристик.ДополнительныеРеквизитыИСведения. Это действие обычно выполняется в пользовательском режиме через список "Дополнительные реквизиты". При удалении определения реквизита система предложит удалить его из всех наборов, в которые он входит. Для окончательного удаления потребуется также очистить значения этого реквизита во всех объектах, где он был заполнен.

    Программно прямое удаление элемента из ПланаВидовХарактеристик не рекомендуется, так как это нарушает логику работы БСП и может привести к "битым" ссылкам и ошибкам. Обычно мы работаем с их значениями.

  2. Удаление значения дополнительного реквизита для конкретного объекта: Это означает очистку значения реквизита для определенного документа или справочника.

Как мы уже упоминали, для очистки значения дополнительного реквизита для конкретного объекта можно использовать функцию УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(), передав Неопределено в качестве значения.


// Предполагаем, что ОбъектДляИзменения - это объект документа
// ИмяСвойстваДляОчистки - это уникальное имя дополнительного реквизита, значение которого хотим удалить

СтруктураЗначенийДляОчистки = Новый Структура;
СтруктураЗначенийДляОчистки.Вставить(ИмяСвойстваДляОчистки, Неопределено);

// Записываем 'Неопределено' как значение, что для БСП означает удаление текущего значения
УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(ОбъектДляИзменения, СтруктураЗначенийДляОчистки, Истина);

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

Таким образом, мы не "удаляем" сам реквизит как таковой, а скорее "сбрасываем" его значение, что для большинства практических целей эквивалентно удалению данных.

Важные нюансы и лучшие практики

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

  1. Различие между Свойство и Значение: Мы уже много раз это подчеркивали, но это настолько фундаментально, что стоит повторить. Свойство – это ссылка на объект, описывающий сам реквизит, а Значение – это данные, которые хранятся в этом реквизите. Не путайте их типы при передаче параметров в запросы или функции.

  2. Использование Имя свойства: Для программного обращения к дополнительным реквизитам всегда старайтесь использовать их Имя, а не Наименование. Имя является уникальным идентификатором, который стабилен и предназначен для программного доступа, в то время как Наименование может быть изменено пользователем, что приведет к поломке вашего кода.

  3. Функции БСП: Активно используйте функции общего модуля УправлениеСвойствами и других модулей БСП. Они предоставляют готовые, протестированные и поддерживаемые механизмы для работы с дополнительными реквизитами, избавляя вас от необходимости писать низкоуровневый код для работы с ПланамиВидовХарактеристик и табличными частями.

  4. Особенности обменов данными: При настройке обменов между базами данных, где используются дополнительные реквизиты, будьте внимательны. Механизм БСП гарантирует корректную передачу данных, но могут потребоваться дополнительные настройки правил обмена, чтобы удостовериться в правильном сопоставлении ПлановВидовХарактеристик и их значений.

  5. Производительность: В высоконагруженных системах большое количество дополнительных реквизитов или частые операции с ними могут незначительно влиять на производительность. Однако в большинстве случаев влияние минимально, поскольку БСП оптимизирована для этих задач. Тем не менее, всегда стоит помнить о том, что запросы к табличным частям, особенно без индексов или с плохими условиями, могут быть медленными.

  6. Пользовательский интерфейс: Помните, что дополнительные реквизиты предназначены для расширения функционала без изменения конфигурации. Мы всегда можем управлять ими и их значениями через пользовательский интерфейс, и программный доступ служит для автоматизации или специализированных задач.

Работая с дополнительными реквизитами, мы расширяем возможности типовой конфигурации, делая ее более гибкой и адаптируемой к уникальным потребностям бизнеса. Понимание их структуры и использование предоставленных БСП инструментов позволяет нам эффективно и надежно интегрировать этот механизм в наши решения.

← На главную