Как изменить или удалить данные из константы с типом ХранилищеЗначения?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Работа с константами, имеющими тип ХранилищеЗначения, часто вызывает вопросы у начинающих разработчиков. В отличие от примитивных типов (строка, число, булево), данные в хранилище упакованы (сериализованы) в двоичный формат. Это означает, что мы не можем просто обратиться к содержимому и выполнить команду "удалить элемент", используя язык запросов или простые методы обращения через точку.

Давайте разберем подробно, как правильно извлекать, модифицировать и записывать обратно сложные структуры данных (например, Массивы или Таблицы Значений), сохраненные в константе.

Понимание механизма и просмотр Хранилища Значения

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

  1. Чтение: Получаем объект хранилища из базы данных.
  2. Распаковка: Извлекаем из хранилища прикладной объект (массив, таблицу и т.д.) в оперативную память.
  3. Модификация: Вносим изменения в объект (удаляем лишнее, добавляем новое).
  4. Упаковка и запись: Создаем новое хранилище с обновленными данными и записываем его в константу.

Шаг 1. Извлечение данных из константы

Рассмотрим пример из обсуждения. Допустим, у нас есть константа ПлатформыРезерв (или НоваяКонстанта), в которой хранится массив ссылок на справочник "Клиенты". Чтобы начать работу с этими данными, нам нужно их "достать".

Обратите внимание на синтаксис. Простого обращения к менеджеру констант недостаточно.


// Получаем само значение константы (объект типа ХранилищеЗначения)
Хранилище = Константы.ПлатформыРезерв.Получить();

// Если константа пустая, метод вернет Неопределено
Если Хранилище = Неопределено Тогда
    Возврат; // Или инициализируем новый массив
КонецЕсли;

// Извлекаем данные из хранилища в переменную
МассивСсылок = Хранилище.Получить();

Частая ошибка — забыть второй вызов метода Получить(). Первый Получить() обращается к базе данных и возвращает объект-контейнер. Второй Получить() (метод объекта ХранилищеЗначения) распаковывает данные и возвращает конкретный тип (в нашем случае Массив).

В одной строке это выглядит так:


МассивСсылок = Константы.ПлатформыРезерв.Получить().Получить();

Шаг 2. Фильтрация данных (удаление ненужных элементов)

Задача автора: удалить из массива ссылки на клиентов, у которых реквизит "Ключевой" имеет значение Ложь. Поскольку мы выгрузили данные в переменную МассивСсылок, мы работаем с обычным массивом 1С в оперативной памяти.

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

Рассмотрим правильный код очистки массива:


// Получаем верхнюю границу массива для обратного цикла
Индекс = МассивСсылок.ВГраница();

// Цикл Пока, так как мы будем уменьшать Индекс вручную
Пока Индекс >= 0 Цикл
    
    ТекущаяСсылка = МассивСсылок[Индекс];
    
    // Проверяем условие. Нам нужно удалить тех, кто НЕ ключевой.
    // Обращение к реквизитам через точку допустимо, но помните о производительности
    // (в идеале такие данные лучше получать запросом, но здесь массив уже в памяти).
    
    Если НЕ ТекущаяСсылка.Ключевой Тогда
        МассивСсылок.Удалить(Индекс);
    КонецЕсли;
    
    // Переходим к предыдущему элементу
    Индекс = Индекс - 1;
    
КонецЦикла;

Альтернативный, часто более быстрый способ — создать новый массив и поместить туда только "нужные" элементы, а затем перезаписать старый массив.


НовыйМассив = Новый Массив;

Для Каждого ЭлементСсылка Из МассивСсылок Цикл
    Если ЭлементСсылка.Ключевой Тогда
        НовыйМассив.Добавить(ЭлементСсылка);
    КонецЕсли;
КонецЦикла;

// Теперь НовыйМассив содержит только правильных клиентов
МассивСсылок = НовыйМассив;

Шаг 3. Запись обновленных данных обратно

Теперь, когда переменная МассивСсылок содержит актуальные данные, нам нужно поместить её обратно в базу данных. Для этого мы должны создать новый объект ХранилищеЗначения. Напрямую присвоить массив константе нельзя.


// Упаковываем массив в хранилище
// Можно использовать сжатие для экономии места, если массив большой
НовоеХранилище = Новый ХранилищеЗначения(МассивСсылок, Новый СжатиеДанных(9));

// Записываем в константу
Константы.ПлатформыРезерв.Установить(НовоеХранилище);

Полный пример кода решения

Соберем все части вместе, чтобы решить задачу автора по удалению не ключевых клиентов из константы.


// 1. Чтение
ТекущееЗначение = Константы.ПлатформыРезерв.Получить();
Если ТипЗнч(ТекущееЗначение) <> Тип("ХранилищеЗначения") Тогда
    Сообщить("В константе нет хранилища!");
    Возврат;
КонецЕсли;

ИсходныйМассив = ТекущееЗначение.Получить();
Если ТипЗнч(ИсходныйМассив) <> Тип("Массив") Тогда
    Сообщить("В хранилище лежит не массив!");
    Возврат;
КонецЕсли;

// 2. Обработка (фильтрация)
ОтфильтрованныйМассив = Новый Массив;

Для Каждого СсылкаНаКлиента Из ИсходныйМассив Цикл
    // Проверка на "битую" ссылку и на признак
    Если ЗначениеЗаполнено(СсылкаНаКлиента) 
       И СсылкаНаКлиента.Ключевой = Истина Тогда
        
        ОтфильтрованныйМассив.Добавить(СсылкаНаКлиента);
        
    КонецЕсли;
КонецЦикла;

// 3. Запись
НовоеХранилище = Новый ХранилищеЗначения(ОтфильтрованныйМассив);
Константы.ПлатформыРезерв.Установить(НовоеХранилище);

Сообщить("Список обновлен. Осталось элементов: " + ОтфильтрованныйМассив.Количество());

Архитектурные рекомендации

Хотя технически хранение списков ссылок в константе типа ХранилищеЗначения возможно, в профессиональной разработке 1С это считается плохой практикой (антипаттерном) по нескольким причинам:

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

← На главную