Как преобразовать строку в число и отсортировать таблицу значений в 1С?

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

При выгрузке данных из запроса разработчики нередко сталкиваются с ситуацией, когда числовые данные хранятся в строковом реквизите (например, в дополнительных реквизитах и сведениях). В языке запросов 1С конструкция ВЫРАЗИТЬ() не выполняет преобразование типа из строки в число — она предназначена только для сужения составных типов или изменения длины. В результате попытка упорядочить такие строки приводит к лексикографической сортировке (где строка "10" оказывается раньше строки "2").

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

Анализ типичных ошибок при работе с ТаблицейЗначений

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


ВыгрузкаТовары = Запрос.Выполнить();
ТЗ = ВыгрузкаТовары.Выгрузить();

Для Каждого Стр Из ТЗ Цикл
    ТЗ.Колонки.Добавить("НоваяКолонка", Новый ОписаниеТипов("Число"));
    ТЗ.Колонки.НоваяКолонка = Стр.Свойство;
КонецЦикла;

В приведенном алгоритме допущены три критические ошибки:

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

Корректный способ создания числовой колонки и сортировки таблицы

Разберем правильную последовательность действий: сначала добавляем типизированную колонку в коллекцию, затем в цикле обходим строки таблицы, преобразуем строковые данные в число с помощью функции Число(), а после завершения цикла вызываем метод сортировки Сортировать().

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


ВыгрузкаТовары = Запрос.Выполнить();
ТЗ = ВыгрузкаТовары.Выгрузить();

// 1. Добавляем колонку один раз до начала цикла
Квалификатор = Новый КвалификаторыЧисла(15, 2);
ТЗ.Колонки.Добавить("ЧисловоеЗначение", Новый ОписаниеТипов("Число", Квалификатор));

// 2. Обходим строки и заполняем данные
Для Каждого Стр Из ТЗ Цикл
    ОчищеннаяСтрока = СокрЛП(Стр.Свойство);
    ОчищеннаяСтрока = СтрЗаменить(ОчищеннаяСтрока, Символы.НПП, "");
    ОчищеннаяСтрока = СтрЗаменить(ОчищеннаяСтрока, " ", "");
    
    Попытка
        Стр.ЧисловоеЗначение = Число(ОчищеннаяСтрока);
    Исключение
        Стр.ЧисловоеЗначение = 0;
    КонецПопытки;
КонецЦикла;

// 3. Выполняем сортировку таблицы значений
ТЗ.Сортировать("ЧисловоеЗначение Возр");

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

Альтернативный вариант: выравнивание строк ведущими нулями

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

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

Посмотрим, как реализовать выравнивание ведущими нулями:


Для Каждого Стр Из ТЗ Цикл
    // Дополняем строку нулями слева до фиксированной длины (например, 10 знаков)
    ИсходноеЗначение = СокрЛП(Стр.Свойство);
    Стр.Свойство = Прав("0000000000" + ИсходноеЗначение, 10);
КонецЦикла;

// Теперь строки вида "0000000001", "0000000022", "0000000444" сортируются корректно
ТЗ.Сортировать("Свойство Возр");

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

← На главную