Как эффективно перекинуть данные из Списка Значений в Таблицу Значений в 1С 7.7

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

В разработке на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с необходимостью конвертации данных между различными типами коллекций. Одной из классических задач является преобразование объекта СписокЗначений (СЗ) в объект ТаблицаЗначений (ТЗ). Казалось бы, задача тривиальная, но стандартный метод Выгрузить() имеет свои существенные ограничения, которые заставляют нас искать более изящные или производительные решения. Давайте подробно разберем, как сделать это "красиво" и максимально эффективно.

Проблема стандартного метода Выгрузить

Начнем с того, что проанализируем штатное поведение платформы. Рассмотрим типичный код:


ТЗ = СоздатьОбъект("ТаблицаЗначений");
СЗ.Выгрузить(ТЗ);

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

Способ 1: Классический перебор (Цикл)

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

  1. Создаем объект ТаблицаЗначений.
  2. Добавляем необходимые колонки: "Значение", "Представление", "Пометка".
  3. Запускаем цикл по количеству элементов в Списке Значений.
  4. На каждой итерации добавляем строку в ТЗ и заполняем ячейки.

Посмотрим на пример реализации:


ТЗ = СоздатьОбъект("ТаблицаЗначений");
ТЗ.НоваяКолонка("Значение");
ТЗ.НоваяКолонка("Представление");
ТЗ.НоваяКолонка("Пометка", "Число", 1, 0);

Для н = 1 По СЗ.РазмерСписка() Цикл
    ТЗ.НоваяСтрока();
    ТекЗнач = "";
    ТекПредст = "";
    ТекЗнач = СЗ.ПолучитьЗначение(н, ТекПредст);
    
    ТЗ.Значение = ТекЗнач;
    ТЗ.Представление = ТекПредст;
    ТЗ.Пометка = СЗ.Пометка(н);
КонецЦикла;

Важный момент: использование переменной ТекПредст во втором параметре метода ПолучитьЗначение() позволяет нам за один вызов получить и объект, и его текстовое описание. Это чуть быстрее, чем вызывать отдельно ПолучитьЗначение и ПолучитьПредставление.

Способ 2: Создание универсальной функции в стиле 1С 8.х

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

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


Процедура глСЗвТЗ(СЗ, ТЗ) Экспорт
    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    ТЗ.НоваяКолонка("Значение");
    ТЗ.НоваяКолонка("Представление");
    
    Для н = 1 По СЗ.РазмерСписка() Цикл
        ТЗ.НоваяСтрока();
        Стр = "";
        ТЗ.Значение = СЗ.ПолучитьЗначение(н, Стр);
        ТЗ.Представление = Стр;
    КонецЦикла;
КонецПроцедуры

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

глСЗвТЗ(МойСписок, МояТаблица);

Способ 3: "Хакерский" метод через внутреннюю строку (ЗначениеВСтрокуВнутр)

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

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

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

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

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

Способ 4: Использование внешних компонент (1С++)

Если ваша конфигурация использует библиотеку 1С++, то задача решается гораздо эффективнее. Класс ИндексированнаяТаблица предоставляет методы для прямой загрузки данных. Кроме того, часто данные в СЗ попадают из SQL-запроса. В таком случае правильнее будет вообще миновать этап создания СЗ и выгружать результат Recordset напрямую в ТЗ.

Посмотрим на пример, если мы используем возможности расширения платформы:


// Пример использования ИндексированнойТаблицы из 1С++
итз = СоздатьОбъект("ИндексированнаяТаблица");
итз.НоваяКолонка("Значение");
итз.НоваяКолонка("Представление");
// Далее используем методы быстрой загрузки или прямой работы с данными

Способ 5: "Ленивая" синхронизация

Иногда нам не нужно физически переносить данные. Если цель конвертации — отобразить данные Списка Значений в табличном поле на форме с дополнительными колонками, мы можем применить следующий прием:

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

Этот метод позволяет экономить память, не дублируя данные Списка Значений в памяти еще и в виде полноценной Таблицы Значений. Выясним причину популярности этого метода: он обеспечивает мгновенный визуальный результат без тяжелых операций копирования.

Выводы и рекомендации

Мы проанализировали различные подходы к задаче переноса данных из СЗ в ТЗ в 1С 7.7. Подведем итог:

  1. Для большинства задач: Используйте обычный цикл (Способ 1). Это надежно, понятно любому программисту, который будет сопровождать ваш код, и не вызывает проблем при обновлении платформы.
  2. Для красоты кода: Вынесите цикл в Глобальный модуль (Способ 2), создав процедуру с понятным именем.
  3. При работе с огромными массивами: Если счет идет на сотни тысяч строк, рассмотрите вариант с использованием 1С++ или (в крайнем случае) манипуляции с внутренней строкой.
  4. Архитектурный совет: Как справедливо замечено в Сообщении 17 форума, часто бывает проще с самого начала использовать Таблицу Значений вместо Списка Значений. ТЗ — более универсальный объект, который легко заменяет СЗ во многих ситуациях (например, для подбора элементов).

Таким образом, выбор метода зависит от конкретного контекста задачи: объема данных и требований к чистоте кода в модуле.

← На главную