Как реализовать хранение множества значений для одного реквизита справочника в 1С 7.7?

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

При разработке конфигураций на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с архитектурными ограничениями прошлых лет. Одно из наиболее существенных ограничений — отсутствие табличных частей у справочников (которые появились только в версии 8.0) и отсутствие стандартного типа данных «Хранилище значения» для хранения произвольных структур. Рассмотрим классическую задачу: в ветеринарной аптеке для каждой номенклатурной позиции необходимо хранить список животных, которым подходит данный препарат. Животных может быть много, и один товар может подходить сразу десятку разных видов. Это классическое отношение типа «многие ко многим» (Many-to-Many).

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

---

Вариант 1. Использование подчиненного справочника

Это классический и самый очевидный подход в рамках штатных возможностей метаданных 1С 7.7. Разберем его по шагам.

Создаем новый справочник (например, СовместимостьТоваров) и делаем его подчиненным справочнику Номенклатура. В качестве единственного реквизита этого подчиненного справочника указываем ссылку на справочник ВидыЖивотных (или просто текстовый реквизит, если полноценного справочника животных в системе нет).

Плюсы данного подхода:

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

Для программного обхода таких связей мы используем следующий шаблон кода:


// Выберем всех животных, закрепленных за конкретным товаром
СпрСовместимость = СоздатьОбъект("Справочник.СовместимостьТоваров");
СпрСовместимость.ИспользоватьВладельца(ТекущийТовар);
СпрСовместимость.ВыбратьЭлементы();
Пока СпрСовместимость.ПолучитьЭлемент() = 1 Цикл
    Сообщить("Подходит для: " + СокрЛП(СпрСовместимость.Животное.Наименование));
КонецЦикла;

Минусы подхода:

  1. Тяжело делать обратную выборку. Если нам нужно быстро найти все товары, которые подходят, к примеру, «Кроликам», платформе придется перебирать подчиненные элементы всех товаров базы данных, что приведет к катастрофическому падению производительности на больших объемах данных.

---

Вариант 2. Справочник-перекресток (независимая связующая сущность)

Чтобы обойти проблему односторонней выборки подчиненного справочника, мы можем спроектировать независимый связующий справочник. Назовем его СвязиНоменклатурыИЖивотных.

В этом справочнике создаем два обязательных реквизита:

Важная деталь конфигуратора: Для обоих реквизитов в свойствах обязательно устанавливаем флаг «Сортировка». В терминологии 1С 7.7 это означает автоматическое создание индексов в базе данных (как DBF, так и MS SQL) по этим полям.

Теперь мы можем одинаково быстро производить выборку в обе стороны. Проанализируем пример получения товаров для конкретного животного:


СпрСвязей = СоздатьОбъект("Справочник.СвязиНоменклатурыИЖивотных");
// Используем быстрый поиск по индексу реквизита
СпрСвязей.ВыбратьЭлементыПоРеквизиту("Животное", ВыбранноеЖивотное, 1, 1);
Пока СпрСвязей.ПолучитьЭлемент() = 1 Цикл
    Сообщить("Товар для этого животного: " + СокрЛП(СпрСвязей.Товар.Наименование));
КонецЦикла;

---

Вариант 3. Использование механизма свойств номенклатуры

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

Рассмотрим, как задействовать этот механизм без изменения метаданных конфигурации:

  1. В справочнике ВидыСвойств создаем элемент «Подходит для животных».
  2. В подчиненном справочнике ЗначенияСвойств создаем перечень: «Кошки», «Собаки», «Кролики».
  3. Связываем товары со свойствами через стандартный интерфейс.

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

---

Вариант 4. Сериализация «Списка значений» в текстовое поле

Если перед нами стоит задача не изменять структуру конфигурации созданием новых справочников, мы можем хранить данные прямо в элементе номенклатуры, используя сериализацию динамических объектов 1С.

Для этого в справочнике Номенклатура создаем реквизит СписокЖивотныхТекст с типом данных Строка неограниченной длины (или фиксированной, например, 200–500 символов, в зависимости от объема данных).

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

Рассмотрим программную реализацию сохранения данных:


// Код в модуле формы элемента при записи
СписокДляЗаписи = СоздатьОбъект("СписокЗначений");
// Выгружаем данные из экранной формы списка с галочками
СписокЖивотныхНаФорме.Выгрузить(СписокДляЗаписи);

// Преобразуем структуру в системную строку
СтрокаСериализации = ЗначениеВСтрокуВнутр(СписокДляЗаписи);
// Записываем в реквизит справочника
СписокЖивотныхТекст = СтрокаСериализации;

При открытии формы элемента выполняем обратную процедуру восстановления списка:


// Код при открытии формы элемента
Если ПустаяСтрока(СписокЖивотныхТекст) = 0 Тогда
    СписокВосстановленный = ЗначениеИзСтрокиВнутр(СписокЖивотныхТекст);
    СписокВосстановленный.ЗагрузитьВ(СписокЖивотныхНаФорме);
КонецЕсли;

Критический недостаток метода: Данный метод полностью лишает нас возможности использовать стандартные запросы 1С для поиска товаров по конкретному животному. База данных хранит текстовую строку вида {"ValueList",{"0","0",...}}, которую СУБД не может разобрать на логические составляющие. Метод подходит исключительно для информационного отображения данных внутри карточки товара.

---

Вариант 5. Использование битовой маски (для фиксированного списка)

Этот метод считается вершиной оптимизации в условиях жестких ресурсных ограничений платформ прошлых поколений. Он идеально подходит, если список животных относительно небольшой (до 30–50 видов) и редко меняется.

Идея заключается в том, что каждому животному сопоставляется свой уникальный бит (степень двойки):

В справочнике номенклатуры создается один числовой реквизит БитоваяМаска. Если товар подходит, например, кошкам и птицам, мы складываем их биты: $2 + 8 = 10$. Число 10 записывается в реквизит товара.

При анализе применимости товара программный код производит быстрое математическое вычисление. В связи с отсутствием в штатном языке 1С 7.7 побитового оператора И (AND), операцию можно реализовать через целочисленное деление:


// Проверим, подходит ли товар Птицам (бит 3, значение 8)
Функция ПодходитПтицам(ЗначениеМаски)
    // Делим значение на вес бита и проверяем остаток от деления на 2
    Если Целое(ЗначениеМаски / 8) % 2 = 1 Тогда
        Возврат 1; // Да, подходит
    КонецЕсли;
    Возврат 0; // Нет
КонецФункции

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

---

Резюме

Выбор конкретной реализации зависит от масштаба вашей информационной системы:

← На главную