Особенности и решение проблем сортировки в таблице значений 1С 7.7

Программист 1С v7.7 Бухгалтерский учет
← На главную

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

Понимание основ метода Сортировать()

Для начала разберем синтаксис метода. В 1С 7.7 метод Сортировать() принимает строку с именами колонок, разделенных запятыми. Направление сортировки указывается символами + (по возрастанию, по умолчанию) или - (по убыванию).

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


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

Проблема «вылетающих» нулей при сортировке чисел

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

  1. Нетипизированные колонки: Если при создании колонки методом НоваяКолонка() не был жестко указан тип Число, платформа может воспринимать значения как неопределенные или сравнивать их по правилам типов (где пустое значение или ноль могут иметь специфический приоритет).
  2. Сортировка по строковому представлению: Если числовые данные были преобразованы в строку без форматирования (например, "10", "2", "0"), то строковая сортировка поставит "2" выше "10".
  3. Логическая ошибка структуры ТЗ: Самая частая причина, которую мы разберем далее — это смешивание разных типов строк в одной таблице.

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


Таблоид.НоваяКолонка("Порядок", "Строка", 20);
// В цикле заполнения:
Таблоид.Порядок = Формат(Таблоид.Значение, "Ч(0)20.2");
// Теперь сортировка по колонке "Порядок" всегда будет корректной
Таблоид.Сортировать("Порядок-");

Многоуровневая сортировка и иерархические отчеты

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

Типичная ошибка выглядит так: мы заполняем таблицу, а затем вызываем сортировку по ключевому полю (например, количеству дней просрочки):

Таблоид.Сортировать("Проср-");

В этом случае строки итогов по контрагентам, у которых поле Проср равно нулю (или не заполнено), «улетят» в конец или начало списка, перемешавшись с документами других контрагентов. Посмотрим, как выглядит структура данных, приводящая к хаосу:

Если отсортировать только по Проср-, мы получим: Докум Альфа (10), Докум Бета (5), Агент Альфа (0), Агент Бета (0). Иерархия нарушена.

Решение: правильный порядок колонок в сортировке

Чтобы иерархический отчет «взлетел», необходимо включать все уровни группировки в параметры метода Сортировать(). Выясним причину успеха правильной последовательности:

Разберем эталонный пример многоуровневой сортировки из практики:


// Правильная сортировка для сохранения иерархии:
// 1. Сначала группируем по счету
// 2. Внутри счета - по валюте
// 3. Внутри валюты - по конкретному агенту
// 4. Чтобы строка итогов агента была ПЕРЕД документами, используем колонку Статус
// 5. И только в самом конце сортируем документы агента по просрочке
Таблоид.Сортировать("Счет+, Валюта+, Агент+, Статус+, Проср-, Позиция+");

Почему это работает:

  1. Колонка Статус должна содержать значения, которые при алфавитной сортировке выстроят строки в нужном порядке. Например, если итог по агенту имеет статус "Агент", а документы — "Докум", то при сортировке по возрастанию (+) строка "Агент" всегда окажется выше строк "Докум" для одного и того же контрагента.
  2. Использование ПозицияДокумента (через ПолучитьПозицию()) в конце сортировки гарантирует, что документы с одинаковой просрочкой будут выведены в хронологическом порядке. Это обеспечивает так называемую «стабильность» сортировки.

Практические советы по работе с ТЗ в 1С 7.7

Проанализируем еще несколько важных моментов, которые помогут избежать ошибок:

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

2. Сортировка по внутреннему идентификатору: Если вам нужно просто сгруппировать строки по объектам (Справочникам, Документам), используйте символ * после имени колонки:

Таблоид.Сортировать("Агент*");

Это заставит систему сравнивать внутренние ID объектов, а не их строковые представления (наименования), что работает значительно быстрее.

3. Проверка после Свернуть(): Помните, что метод Свернуть() часто нарушает текущий порядок строк. Если после сворачивания таблицы вам нужен определенный порядок, обязательно вызывайте Сортировать() повторно.

4. Очистка перед заполнением: При формировании сложных отчетов не забывайте использовать УдалитьСтроки(), чтобы старые данные не влияли на новую выборку. В контексте обсуждения это важно, так как «фантомные» строки из прошлых запусков часто принимаются за баги сортировки.

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


// Добавляем итоги по агенту в общую таблицу
Итоговая.ВыбратьСтроки();
Пока Итоговая.ПолучитьСтроку() = 1 Цикл
    Таблоид.НоваяСтрока();
    Таблоид.Статус = "1_Агент"; // Используем префикс для сортировки
    Таблоид.Счет   = Итоговая.Счет;
    Таблоид.Агент  = Итоговая.Агент;
    Таблоид.Сумма  = Итоговая.Сумма;
    Таблоид.Проср  = 0; // Итог не имеет просрочки
КонецЦикла;

// Добавляем документы
// ... код выборки документов ...
Таблоид.Статус = "2_Докум"; 
// ...

// Финальный аккорд
Таблоид.Сортировать("Счет, Агент, Статус, Проср-");

С таким подходом вы всегда будете уверены, что данные в ваших отчетах на платформе 1С 7.7 расположены именно так, как задумано логикой программы, а любые странности в поведении системы — лишь повод еще раз внимательно проверить критерии сортировки.

← На главную