В современных конфигурациях 1С, таких как «Управление нашей фирмой» (УНФ), механизм дополнительных реквизитов реализован на базе Библиотеки стандартных подсистем (БСП). Это мощный инструмент, позволяющий пользователям добавлять новые поля в документы без изменения конфигурации. Однако перед разработчиком часто встает задача: как управлять этими данными программно, например, в обработке или при проведении документа? В этой статье мы подробно разберем все способы взаимодействия с дополнительными реквизитами — от простого перебора табличной части до использования профессионального программного интерфейса БСП.
Прежде чем приступать к написанию кода, проанализируем, как 1С хранит эти данные. Дополнительные реквизиты — это не обычные поля таблицы базы данных. Они располагаются в специальной табличной части документа, которая почти всегда называется ДополнительныеРеквизиты. Эта табличная часть состоит из двух ключевых колонок:
ДополнительныеРеквизитыИСведения.Важный нюанс: если значение дополнительного реквизита типа «Булево» равно Ложь, система в целях оптимизации часто просто не создает строку в табличной части. Таким образом, отсутствие строки эквивалентно значению Ложь.
Рассмотрим ситуацию, когда у нас уже есть объект документа (например, РасходнаяНакладная), и нам нужно изменить в нем логическое поле «ВыведенИзОборота». Этот метод наиболее нагляден и часто используется в простых обработках.
Разберем по шагам алгоритм изменения значения:
// 1. Находим ссылку на само свойство (реквизит) в Плане видов характеристик
ДопРеквизитПроверено = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("ВыведенИзОборота");
Если ДопРеквизитПроверено.Пустая() Тогда
Сообщить("Свойство 'ВыведенИзОборота' не найдено в системе!");
Возврат;
КонецЕсли;
// 2. Ищем строку с этим свойством в табличной части документа
ПараметрыПоиска = Новый Структура("Свойство", ДопРеквизитПроверено);
НайденныеСтроки = ОбъектДокумента.ДополнительныеРеквизиты.НайтиСтроки(ПараметрыПоиска);
Если НайденныеСтроки.Количество() > 0 Тогда
// Если строка найдена, просто меняем значение
СтрокаТЧ = НайденныеСтроки[0];
Иначе
// Если строки нет (реквизит не был заполнен), добавляем новую
СтрокаТЧ = ОбъектДокумента.ДополнительныеРеквизиты.Добавить();
СтрокаТЧ.Свойство = ДопРеквизитПроверено;
КонецЕсли;
// 3. Устанавливаем нужное значение
СтрокаТЧ.Значение = Истина;
// 4. Не забываем записать сам объект документа
ОбъектДокумента.Записать(РежимЗаписиДокумента.Запись);
Проанализируем этот код: мы используем метод НайтиСтроки, который возвращает массив. Если массив пуст, мы создаем новую запись. Это универсальный подход, гарантирующий, что мы не создадим дублирующиеся строки для одного и того же свойства.
Использование прямого обращения к ТЧ эффективно, но архитектурно правильнее использовать методы общего модуля УправлениеСвойствами. Это позволяет избежать ошибок при изменении структуры метаданных и делает код более компактным. Рассмотрим, как прочитать и записать свойства через этот интерфейс.
Чтение значения:
Для быстрого получения значения реквизита без написания сложных запросов или циклов воспользуемся функцией ЗначениеСвойства:
Значение = УправлениеСвойствами.ЗначениеСвойства(СсылкаНаДокумент, "ВыведенИзОборота");
Если Значение = Истина Тогда
// Ваша логика
КонецЕсли;
Массовая запись свойств:
Если нам нужно обновить свойства сразу у объекта, лучше всего использовать метод ЗаписатьСвойстваУОбъекта. Проанализируем пример кода:
// Подготовим таблицу для записи свойств
ТаблицаСвойств = Новый ТаблицаЗначений;
ТаблицаСвойств.Колонки.Добавить("Свойство");
ТаблицаСвойств.Колонки.Добавить("Значение");
// Добавим строку с нашим реквизитом
НоваяСтрока = ТаблицаСвойств.Добавить();
НоваяСтрока.Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("ВыведенИзОборота");
НоваяСтрока.Значение = Истина;
// Записываем свойства в объект
УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(ОбъектДокумента, ТаблицаСвойств);
ОбъектДокумента.Записать();
Преимущество этого метода в том, что БСП берет на себя всю рутину по поиску существующих строк, удалению пустых значений и оптимизации записи в базу данных.
Часто задача звучит иначе: «Найти все расходные накладные, где галочка НЕ стоит». Здесь начинающие разработчики часто сталкиваются с проблемой: запрос возвращает пустой результат для документов, где реквизит никогда не устанавливался.
Выясним причину: как мы уже знаем, если значение Ложь, строки в ТЧ может не быть. Поэтому обычное соединение с табличной частью по условию Значение = Ложь не сработает. Нам нужно использовать ЛЕВОЕ СОЕДИНЕНИЕ и проверку на NULL.
Рассмотрим правильную структуру запроса:
ВЫБРАТЬ
РасходнаяНакладная.Ссылка КАК Ссылка
ИЗ
Документ.РасходнаяНакладная КАК РасходнаяНакладная
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РасходнаяНакладная.ДополнительныеРеквизиты КАК ДопРеквизиты
ПО РасходнаяНакладная.Ссылка = ДопРеквизиты.Ссылка
И ДопРеквизиты.Свойство = &ЦелевоеСвойство
ГДЕ
(ДопРеквизиты.Значение = ЛОЖЬ ИЛИ ДопРеквизиты.Значение ЕСТЬ NULL)
В этом запросе мы соединяем основную таблицу документов с таблицей доп. реквизитов только по конкретному свойству. Условие ЕСТЬ NULL позволяет нам поймать те документы, у которых этой строки в табличной части вообще нет (что для типа Булево означает Ложь).
При работе с дополнительными реквизитами в УНФ стоит придерживаться следующих правил:
НайтиПоНаименованию("ВыведенИзОборота") опасен тем, что пользователь может переименовать реквизит в пользовательском интерфейсе. Если вы разрабатываете тиражное решение, лучше использовать поиск по уникальному идентификатору (GUID) или добавить реквизиту «Имя для разработчика» в настройках БСП.УправлениеСвойствамиУТКлиент или УправлениеСвойствамиУНФ для перерисовки динамических элементов формы.ДополнительныеРеквизиты хранятся в самом документе (нужна запись объекта), а ДополнительныеСведения хранятся в независимом регистре сведений (можно менять без перезаписи документа).СтрокаТЧ.Значение. Если в настройках реквизита указан тип «Число», попытка записать туда строку приведет к ошибке при записи объекта.Подводя итог, можно сказать, что наиболее надежным и гибким способом является использование методов модуля УправлениеСвойствами. Это избавляет от необходимости вручную обрабатывать специфику хранения пустых значений и обеспечивает совместимость кода с будущими обновлениями конфигурации.