При разработке в среде 1С:Предприятие 8 начинающие программисты часто сталкиваются с неочевидным поведением табличных частей и таблиц, расположенных на управляемой форме. Типичный сценарий — необходимость получить значения одной из колонок таблицы в виде простого массива, а затем отсортировать его (например, классическим алгоритмом пузырька в учебных целях или встроенными методами платформы для реальных задач). В этой статье мы подробно разберем, почему стандартные методы таблиц значений могут вызывать ошибки на форме, как правильно выгружать данные и какими способами их можно быстро отсортировать.
Разберем типичную ошибку, с которой сталкиваются разработчики при попытке вызвать метод ВыгрузитьКолонку() напрямую у таблицы, расположенной на управляемой форме. Начинающий разработчик часто думает, что на форме находится обычный объект ТаблицаЗначений. Однако это не так.
В управляемом приложении 1С (начиная с платформы 8.2 и в актуальной 8.3) данные на форме хранятся в специальных программных обертках — реквизитах формы. Таблица на управляемой форме имеет тип ДанныеФормыКоллекция, а не ТаблицаЗначений. Это сделано для оптимизации передачи данных между клиентом и сервером. Объект ДанныеФормыКоллекция имеет ограниченный набор методов. У него есть метод Выгрузить(), но полностью отсутствует метод ВыгрузитьКолонку(). Именно поэтому при попытке выполнить код напрямую возникает системная ошибка платформы. Для решения смежной задачи динамического отображения структуры данных на форме подойдёт пример программного вывода таблицы значений на управляемую форму.
Рассмотрим подробнее три эффективных способа решения этой задачи: от простого получения массива до его оптимальной сортировки на клиенте и сервере.
Самый быстрый способ получить массив из колонки таблицы формы в серверном коде — это предварительное преобразование коллекции формы в полноценный объект ТаблицаЗначений. Как только мы получаем физическую таблицу значений в памяти сервера, нам становится доступен весь ее богатый функционал, включая метод ВыгрузитьКолонку().
Проанализируем пример кода, выполняемый в контексте сервера:
&НаСервере
Процедура ПолучитьИОтсортироватьМассивНаСервере()
// Предположим, что "цифры" — это имя реквизита вашей формы с типом ДанныеФормыКоллекция
// Шаг 1: Конвертируем коллекцию формы в реальную Таблицу Значений
ВременнаяТЗ = РеквизитФормыВЗначение("цифры"); // Или использовать метод "цифры.Выгрузить()"
// Шаг 2: Выгружаем нужную колонку "Значение" в одномерный массив
МассивЗначений = ВременнаяТЗ.ВыгрузитьКолонку("Значение");
// Теперь МассивЗначений содержит чистые данные (числа, строки), готовые к сортировке
КонецПроцедуры
Этот способ прост в написании, однако у него есть существенный минус: метод Выгрузить() или преобразование через РеквизитФормыВЗначение() заставляет платформу копировать абсолютно все колонки и строки таблицы в оперативную память сервера. Если в вашей таблице содержатся десятки тысяч строк или множество тяжелых колонок, это может негативно сказаться на производительности системы.
Чтобы избежать избыточного расхода оперативной памяти и не создавать временные таблицы в памяти, мы можем получить значения колонки простым и быстрым перебором строк. Этот способ универсален, так как он одинаково успешно работает как на стороне сервера (&НаСервере), так и на стороне тонкого клиента (&НаКлиенте).
Посмотрим на пример реализации данного подхода:
МассивЗначений = Новый Массив;
// Быстро обходим коллекцию строк таблицы формы
Для Каждого СтрокаТаблицы Из цифры Цикл
// Добавляем в массив только значение из конкретной колонки
МассивЗначений.Добавить(СтрокаТаблицы.Значение);
КонецЦикла;
Данный подход является наиболее профессиональным и безопасным с точки зрения расхода ресурсов процессора и памяти, поскольку мы извлекаем только те данные, которые нам действительно необходимы для работы.
Если перед вами стоит задача реализовать алгоритм сортировки массива вручную (например, в рамках учебной задачи или реализации специфического алгоритма сравнения), классический алгоритм сортировки «пузырьком» на встроенном языке 1С будет выглядеть следующим образом.
Разберем по шагам работу алгоритма сортировки по возрастанию:
КоличествоЭлементов = МассивЗначений.Количество();
// Внешний цикл прохода по всему массиву
Для и = 0 По КоличествоЭлементов - 1 Цикл
// Внутренний цикл для сравнения соседних элементов
Для й = 0 По КоличествоЭлементов - и - 2 Цикл
// Если левый элемент больше правого, меняем их местами
Если МассивЗначений[й] > МассивЗначений[й + 1] Тогда
// Используем временную переменную для обмена значениями
ВременнаяПеременная = МассивЗначений[й];
МассивЗначений[й] = МассивЗначений[й + 1];
МассивЗначений[й + 1] = ВременнаяПеременная;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Важное замечание: Сортировка пузырьком во встроенном языке 1С имеет вычислительную сложность O(N²). Поскольку встроенный язык 1С является интерпретируемым, ручная сортировка массивов из нескольких тысяч элементов может выполняться заметно медленнее, чем стандартные механизмы платформы.
В реальной практической разработке для сортировки одномерных массивов программисты практически никогда не пишут сортировку пузырьком вручную. Платформа 1С:Предприятие предоставляет встроенный инструмент, который производит сортировку на уровне платформенного C++ кода, что работает в десятки раз быстрее любого кода на встроенном языке.
Для этого используется объект СписокЗначений. Этот метод замечателен тем, что он доступен непосредственно на клиенте (&НаКлиенте), а значит, нам не нужно совершать серверный вызов для упорядочивания данных.
Рассмотрим, как это реализовать:
&НаКлиенте
Процедура СортироватьМассивНаКлиенте()
// 1. Получаем массив значений (например, обходом в цикле)
МассивЗначений = Новый Массив;
Для Каждого Строка Из цифры Цикл
МассивЗначений.Добавить(Строка.Значение);
КонецЦикла;
// 2. Создаем Список Значений и загружаем в него наш массив одной командой
ВспомогательныйСписок = Новый СписокЗначений;
ВспомогательныйСписок.ЗагрузитьЗначения(МассивЗначений);
// 3. Вызываем быструю сортировку платформы (по умолчанию сортирует по возрастанию)
ВспомогательныйСписок.СортироватьПоЗначению(НаправлениеСортировки.Возр);
// Если требуется сортировка по убыванию, используем:
// ВспомогательныйСписок.СортироватьПоЗначению(НаправлениеСортировки.Убыв);
// 4. Выгружаем отсортированные данные обратно в исходный массив
МассивЗначений = ВспомогательныйСписок.ВыгрузитьЗначения();
КонецПроцедуры
Мы подробно проанализировали особенности работы с коллекциями данных на управляемых формах 1С 8. Теперь мы знаем, как обойти ограничение типа ДанныеФормыКоллекция, научились извлекать данные без лишней нагрузки на серверную память и рассмотрели несколько вариантов сортировки полученного массива. Использование связки Массив + СписокЗначений на клиенте позволит вашему коду работать максимально быстро и отзывчиво для конечного пользователя.