При доработке старых конфигураций на платформе 1С 7.7 (таких как «Торговля и Склад 9.2» или «Комплексная конфигурация») программисты часто сталкиваются с необходимостью проверки дополнительных свойств товаров. Типичный сценарий — проверка признака «Маркировка» для определенных позиций номенклатуры перед выполнением какой-либо операции (например, перед выводом на печать или проведением документа).
В этой статье мы подробно разберем, как устроена архитектура механизма свойств в 1С 7.7, почему простая проверка «в лоб» приводит к аварийному завершению программы, и как написать надежный и быстродействующий код для решения этой задачи.
Прежде чем писать код проверки, давайте проанализируем, как именно свойства хранятся в базе данных 1С 7.7. В отличие от современных конфигураций на платформе 1С 8.x, где используются планы видов характеристик и регистры сведений, в 1С 7.7 свойства реализованы через связку из трех справочников:
ВидыСвойств. В нем хранятся конкретные значения для каждого вида (например, для вида «Цвет» значениями будут «Красный», «Синий»; для «Маркировки» — «Да», «Нет» или «1»).Номенклатура. Это связующий элемент, который содержит реквизиты:
ВидСвойства (ссылка на Справочник.ВидыСвойств);ЗначениеСвойства (ссылка на Справочник.ЗначенияСвойств).Реквизит ОсновноеСвойство в самой карточке Номенклатуры — это просто ссылка на элемент подчиненного справочника СвойстваНоменклатуры, который назначен главным для быстрого вывода в отчетах.
Если вы точно уверены, что интересующее вас свойство (например, «Маркировка») назначено в качестве основного свойства товара, можно обратиться к нему напрямую. Однако здесь кроется опасный подводный камень.
Если написать код напрямую:
Если СокрЛП(Тов.ОсновноеСвойство.ЗначениеСвойства) = "1" Тогда
// Действие
КонецЕсли;
Программа неминуемо завершится ошибкой: «Значение не представляет агрегатный объект (ЗначениеСвойства)» у любого товара, для которого основное свойство не заполнено (равно пустому значению).
Разберем безопасный вариант написания кода. Мы должны пошагово проверить существование объекта на каждом уровне вложенности:
// Безопасный метод проверки основного свойства товара
Если ПустоеЗначение(Тов.ОсновноеСвойство) = 0 Тогда
// Проверяем, что элемент справочника "СвойстваНоменклатуры" выбран
Если Тов.ОсновноеСвойство.ЗначениеСвойства.Выбран() = 1 Тогда
// Сравниваем текстовое представление значения свойства
Если СокрЛП(Тов.ОсновноеСвойство.ЗначениеСвойства) = "1" Тогда
Предупреждение("Товар " + Тов.Наименование + " подлежит маркировке!");
КонецЕсли;
КонецЕсли;
КонецЕсли;
На практике часто бывает так, что основным свойством товара назначен, например, «Размер» или «Производитель», а свойство «Маркировка» создано как дополнительное. В этом случае реквизит Тов.ОсновноеСвойство будет ссылаться на другой элемент, и предыдущий код не сработает.
Выясним, как найти нужное свойство среди всех подчиненных элементов номенклатуры. Для этого нам понадобится программно перебрать элементы подчиненного справочника СвойстваНоменклатуры:
// 1. Создаем объект для поиска вида свойства "Маркировка"
СпрВиды = СоздатьОбъект("Справочник.ВидыСвойств");
Если СпрВиды.НайтиПоНаименованию("Маркировка", 0, 1) = 1 Тогда
СсылкаНаВидМаркировки = СпрВиды.ТекущийЭлемент();
// 2. Создаем объект для обхода подчиненного справочника свойств товара
СпрСвойства = СоздатьОбъект("Справочник.СвойстваНоменклатуры");
// Указываем владельца - наш конкретный товар "Тов"
СпрСвойства.ИспользоватьВладельца(Тов);
СпрСвойства.ВыбратьЭлементы();
Пока СпрСвойства.ПолучитьЭлемент() = 1 Цикл
// Проверяем, совпадает ли вид найденного свойства с искомым видом
Если СпрСвойства.ВидСвойства = СсылкаНаВидМаркировки Тогда
// Получаем значение свойства
ЗначениеСвойств = СпрСвойства.ЗначениеСвойства;
Если ЗначениеСвойств.Выбран() = 1 Тогда
Если СокрЛП(ЗначениеСвойств) = "1" Тогда
// Выполняем действия для маркированного товара
Сообщить("Товар " + Тов.Наименование + " успешно проверен на маркировку.");
КонецЕсли;
КонецЕсли;
// Поскольку вид свойства уникален для товара, прерываем цикл
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Рассмотрим ситуацию, когда проверку свойств нужно произвести не для одного товара, а в рамках отчета. В стандартных («черных») запросах 1С 7.7 обращение к свойствам описывается через точки:
|Товар = Регистр.ОстаткиТМЦ.Номенклатура;
|Свойство = Регистр.ОстаткиТМЦ.Номенклатура.ОсновноеСвойство.ЗначениеСвойства;
|Группировка Товар;
|Условие (СокрЛП(Свойство) = "1");
Важное предупреждение: Обращение через цепочку точек (Номенклатура.ОсновноеСвойство.ЗначениеСвойства) заставляет СУБД делать сложные множественные соединения таблиц (JOIN). В файловых базах данных (DBF) или на крупных базах SQL это приведет к колоссальному замедлению работы отчета.
Чтобы оптимизировать производительность при обработке больших массивов данных, рекомендуется:
ТаблицуЗначений.