Как проверить значение свойства номенклатуры в условии в 1С 7.7?

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

При доработке старых конфигураций на платформе 1С 7.7 (таких как «Торговля и Склад 9.2» или «Комплексная конфигурация») программисты часто сталкиваются с необходимостью проверки дополнительных свойств товаров. Типичный сценарий — проверка признака «Маркировка» для определенных позиций номенклатуры перед выполнением какой-либо операции (например, перед выводом на печать или проведением документа).

В этой статье мы подробно разберем, как устроена архитектура механизма свойств в 1С 7.7, почему простая проверка «в лоб» приводит к аварийному завершению программы, и как написать надежный и быстродействующий код для решения этой задачи.

Архитектура механизма свойств «под капотом»

Прежде чем писать код проверки, давайте проанализируем, как именно свойства хранятся в базе данных 1С 7.7. В отличие от современных конфигураций на платформе 1С 8.x, где используются планы видов характеристик и регистры сведений, в 1С 7.7 свойства реализованы через связку из трех справочников:

  1. Справочник.ВидыСвойств — хранит названия характеристик (например, «Цвет», «Размер», «Маркировка»).
  2. Справочник.ЗначенияСвойств — подчинен справочнику ВидыСвойств. В нем хранятся конкретные значения для каждого вида (например, для вида «Цвет» значениями будут «Красный», «Синий»; для «Маркировки» — «Да», «Нет» или «1»).
  3. Справочник.СвойстваНоменклатуры — подчинен справочнику Номенклатура. Это связующий элемент, который содержит реквизиты:
    • ВидСвойства (ссылка на Справочник.ВидыСвойств);
    • ЗначениеСвойства (ссылка на Справочник.ЗначенияСвойств).

Реквизит ОсновноеСвойство в самой карточке Номенклатуры — это просто ссылка на элемент подчиненного справочника СвойстваНоменклатуры, который назначен главным для быстрого вывода в отчетах.

Решение 1: Проверка через «ОсновноеСвойство» с защитой от ошибок

Если вы точно уверены, что интересующее вас свойство (например, «Маркировка») назначено в качестве основного свойства товара, можно обратиться к нему напрямую. Однако здесь кроется опасный подводный камень.

Если написать код напрямую:


Если СокрЛП(Тов.ОсновноеСвойство.ЗначениеСвойства) = "1" Тогда
    // Действие
КонецЕсли;

Программа неминуемо завершится ошибкой: «Значение не представляет агрегатный объект (ЗначениеСвойства)» у любого товара, для которого основное свойство не заполнено (равно пустому значению).

Разберем безопасный вариант написания кода. Мы должны пошагово проверить существование объекта на каждом уровне вложенности:


// Безопасный метод проверки основного свойства товара
Если ПустоеЗначение(Тов.ОсновноеСвойство) = 0 Тогда
    // Проверяем, что элемент справочника "СвойстваНоменклатуры" выбран
    Если Тов.ОсновноеСвойство.ЗначениеСвойства.Выбран() = 1 Тогда
        // Сравниваем текстовое представление значения свойства
        Если СокрЛП(Тов.ОсновноеСвойство.ЗначениеСвойства) = "1" Тогда
            Предупреждение("Товар " + Тов.Наименование + " подлежит маркировке!");
        КонецЕсли;
    КонецЕсли;
КонецЕсли;

Решение 2: Поиск свойства, если оно НЕ является основным

На практике часто бывает так, что основным свойством товара назначен, например, «Размер» или «Производитель», а свойство «Маркировка» создано как дополнительное. В этом случае реквизит Тов.ОсновноеСвойство будет ссылаться на другой элемент, и предыдущий код не сработает.

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


// 1. Создаем объект для поиска вида свойства "Маркировка"
СпрВиды = СоздатьОбъект("Справочник.ВидыСвойств");
Если СпрВиды.НайтиПоНаименованию("Маркировка", 0, 1) = 1 Тогда
    
    СсылкаНаВидМаркировки = СпрВиды.ТекущийЭлемент();
    
    // 2. Создаем объект для обхода подчиненного справочника свойств товара
    СпрСвойства = СоздатьОбъект("Справочник.СвойстваНоменклатуры");
    
    // Указываем владельца - наш конкретный товар "Тов"
    СпрСвойства.ИспользоватьВладельца(Тов);
    СпрСвойства.ВыбратьЭлементы();
    
    Пока СпрСвойства.ПолучитьЭлемент() = 1 Цикл
        // Проверяем, совпадает ли вид найденного свойства с искомым видом
        Если СпрСвойства.ВидСвойства = СсылкаНаВидМаркировки Тогда
            
            // Получаем значение свойства
            ЗначениеСвойств = СпрСвойства.ЗначениеСвойства;
            
            Если ЗначениеСвойств.Выбран() = 1 Тогда
                Если СокрЛП(ЗначениеСвойств) = "1" Тогда
                    // Выполняем действия для маркированного товара
                    Сообщить("Товар " + Тов.Наименование + " успешно проверен на маркировку.");
                КонецЕсли;
            КонецЕсли;
            
            // Поскольку вид свойства уникален для товара, прерываем цикл
            Прервать;
        КонецЕсли;
    КонецЦикла;
КонецЕсли;

Особенности использования свойств в Запросах 1С 7.7

Рассмотрим ситуацию, когда проверку свойств нужно произвести не для одного товара, а в рамках отчета. В стандартных («черных») запросах 1С 7.7 обращение к свойствам описывается через точки:


|Товар = Регистр.ОстаткиТМЦ.Номенклатура;
|Свойство = Регистр.ОстаткиТМЦ.Номенклатура.ОсновноеСвойство.ЗначениеСвойства;
|Группировка Товар;
|Условие (СокрЛП(Свойство) = "1");

Важное предупреждение: Обращение через цепочку точек (Номенклатура.ОсновноеСвойство.ЗначениеСвойства) заставляет СУБД делать сложные множественные соединения таблиц (JOIN). В файловых базах данных (DBF) или на крупных базах SQL это приведет к колоссальному замедлению работы отчета.

Чтобы оптимизировать производительность при обработке больших массивов данных, рекомендуется:

← На главную