Как реализовать хранение дополнительных реквизитов в 1С 7.7 без изменения структуры базы

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

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

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

Зачем нужны псевдореквизиты

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

  1. Экономия времени на обслуживании. Как уже было замечено, реструктуризация на больших объемах данных крайне болезненна.
  2. Минимизация роста БД. Если реквизит заполняется лишь в 0.001% случаев, его хранение в основной таблице (где под него выделяется место в каждой строке) нерационально.
  3. Гибкость. Псевдореквизиты позволяют добавлять новые свойства "на лету" без монопольного доступа к базе.

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

Это классический подход для 1С 7.7. Мы создаем справочник (например, ДопРеквизиты), где владельцем является наш документ. В справочнике создаются реквизиты ИмяРеквизита и Значение.

Плюсы: штатные средства контроля ссылочной целостности, привычный интерфейс.

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

Вариант 2: Создание внешней SQL-таблицы (прямые запросы)

Для систем на MS SQL Server это наиболее эффективный вариант. Мы создаем таблицу напрямую в SQL, минуя словарь метаданных 1С. Это позволяет избежать реструктуризации вовсе. Разберем реализацию этого метода подробнее, опираясь на программный комплекс для работы с дополнительными реквизитами.

Проанализируем структуру SQL-таблицы, которую мы можем создать для этих целей:


CREATE TABLE ДополнительныеРеквизитыОбъектов (
    Объект char(13) Not Null,  -- ID документа или элемента справочника
    Имя varchar(256) Not Null, -- Техническое имя реквизита
    Тип varchar(256) Not Null, -- Тип данных (Строка, Число, Ссылка)
    Значение_Ссылка char(13),  -- Для хранения ссылок на другие объекты 1С
    Значение_Число Numeric(19, 3),
    Значение_Строка varchar(256),
    Значение_Дата DateTime
)
CREATE INDEX ОбъектИмя ON ДополнительныеРеквизитыОбъектов(Объект, Имя)

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


Функция Установить(Объект, Имя, Значение, Комментарий = "") Экспорт
    Тип = ТипЗначенияСтр(Значение);
    // Определяем, в какую колонку SQL писать данные в зависимости от типа 1С
    Если Тип = "Число" Тогда
        Значение_Имя = "Значение_Число";
        Значение_Значение = "" + Значение;
    ИначеЕсли Тип = "Строка" Тогда
        Значение_Имя = "Значение_Строка";
        Значение_Значение = "'" + Значение + "'";
    // Обработка ссылочных типов (Документ, Справочник)
    ИначеЕсли (Тип = "Документ") Или (Тип = "Справочник") Тогда
        Значение_Имя = "Значение_Ссылка";
        Значение_Значение = "'" + РадугаСервис.ЗначениеВДлиннуюСтрокуБД(Значение) + "'";
        Тип = Тип + "." + Значение.Вид();
    КонецЕсли;

    идОбъект = РадугаСервис.ЗначениеВДлиннуюСтрокуБД(Объект);

    ТекстЗапроса = "
    |DELETE FROM ДополнительныеРеквизитыОбъектов
    |WHERE Объект = '" + идОбъект + "' AND Имя = '" + Имя + "'
    |
    |INSERT INTO ДополнительныеРеквизитыОбъектов 
    | (Объект, Имя, Тип, " + Значение_Имя + ") 
    |VALUES 
    | ('" + идОбъект + "', '" + Имя + "', '" + Тип + "', " + Значение_Значение + ")
    |";
    Возврат ЗапросСКЛ.Выполнить(ТекстЗапроса);
КонецФункции

Вариант 3: Композитная табличная часть

Если нам нужно добавить много реквизитов, которые по смыслу относятся к шапке, но мы не хотим трогать структуру шапки, можно использовать саму табличную часть документа. Для этого создаются служебные строки с определенным флагом (например, реквизит ТипСтроки = "Служебная").

Разберем этот метод: мы выделяем несколько колонок в ТЧ, которые в обычных строках пустуют, а в служебной — хранят наши "псевдореквизиты". При открытии формы мы фильтруем строки, визуально разделяя реальную табличную часть и "виртуальную шапку".

Важный момент: использование этого метода ограничено лимитом строк в табличной части (9999 строк для 7.7), поэтому для документов с огромными спецификациями он не подойдет.

Вариант 4: Упаковка в строку неограниченной длины

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

Рассмотрим алгоритм работы:

  1. При записи документа мы формируем объект СписокЗначений.
  2. Добавляем в него все наши дополнительные данные.
  3. Используем функцию ЗначениеВСтрокуВнутр() для сериализации списка в текст.
  4. Записываем этот текст в наш скрытый реквизит.
  5. При открытии выполняем обратную операцию через ЗначениеИзСтрокиВнутр().

Это самый простой в реализации способ, не требующий внешних компонент. Однако он делает невозможным поиск документов по этим свойствам через стандартные отчеты или SQL-запросы, так как данные внутри строки хранятся в специфическом формате 1С.

Интерфейсные решения для псевдореквизитов

Проанализируем, как вывести эти данные пользователю. Поскольку в 1С 7.7 нет динамических форм, у нас есть два пути:

Заключение

Выбор метода зависит от ваших задач. Если база небольшая и реструктуризация проходит быстро — лучше использовать штатные реквизиты. Если база огромная и вы работаете на SQL — оптимальным будет вариант с внешней SQL-таблицей и прямыми запросами. Для простых задач, где не требуется поиск, отлично подойдет сериализация в строку.

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

← На главную