В практике разработки на платформе 1С часто встречается ситуация, когда числовые данные (например, показатели веса, размера или оптической силы) хранятся в строковом реквизите Наименование. Это приводит к серьезным проблемам при построении отчетов в Системе компоновки данных (СКД): значения «0.0», «0,00», «+0,0» воспринимаются системой как разные строки. В результате вместо одной сгруппированной строки в отчете мы получаем несколько разрозненных позиций с одинаковым физическим смыслом. Рассмотрим, как решить эту проблему программно и архитектурно.
Проанализируем ситуацию: когда мы используем строковое поле в качестве группировки в СКД, СУБД выполняет сравнение символов по их кодам. Для компьютера строки "0,5" и "0.5" абсолютно разные. Более того, при сортировке таких данных мы получаем некорректный порядок (например, значение "10" окажется выше "2", так как символ "1" меньше символа "2").
Для решения этой задачи у нас есть два пути: оперативный (исправление отображения в самом отчете) и фундаментальный (нормализация данных в базе). Разберем их по порядку.
Самый правильный подход — привести все наименования в справочнике к единому «каноническому» виду. Если мы имеем дело с числами (например, диоптриями), нам нужно, чтобы они всегда выглядели одинаково: имели определенное количество знаков после запятой и, если нужно, знак плюс для положительных значений.
Разберем алгоритм преобразования строки в число и обратно в красиво отформатированную строку. Для этого мы можем использовать следующий код:
// Допустим, СтароеНаименование может быть "+1,5", "1.5" или "1,500"
СтароеНаименование = СправочникОбъект.Наименование;
// 1. Заменяем запятую на точку для корректной работы функции Число()
// и очищаем от лишних пробелов
ЧистоеЗначение = СтрЗаменить(СокрЛП(СтароеНаименование), ",", ".");
Попытка
лкЧисло = Число(ЧистоеЗначение);
Исключение
// Если в строке был текст, который невозможно преобразовать
лкЧисло = 0;
КонецПопытки;
// 2. Формируем новое наименование в едином стандарте
// Используем условие для добавления знака "+" для положительных чисел
НовоеНаименование = ?(лкЧисло > 0, "+", "") + Формат(лкЧисло, "ЧДЦ=2; ЧРД=,; ЧН=0,00; ЧО=1");
// Результат для "1,5" станет "+1,50"
// Результат для "-1.5" станет "-1,50"
Этот код можно использовать в групповой обработке справочника. В современных конфигурациях на базе БСП (Библиотека стандартных подсистем) для этого подойдет стандартная обработка «Групповое изменение реквизитов», где в дополнительных настройках можно включить выполнение произвольного кода на языке 1С.
Рассмотрим более элегантный способ управления знаками числа. В 1С функция Формат() обладает мощным синтаксисом. Чтобы не писать условие ?(лкЧисло > 0, "+", ""), мы можем воспользоваться параметром ЧВН= (выводить знак плюс для положительных чисел).
Посмотрим на пример более лаконичной записи:
// ЧДЦ=2 — два знака после запятой
// ЧВН=+ — всегда выводить знак (и плюс, и минус)
// ЧРД=, — разделитель дробной части — запятая
НовоеНаименование = Формат(лкЧисло, "ЧДЦ=2; ЧВН=+; ЧРД=,; ЧН=0,00");
Такой подход гарантирует, что все ваши данные в справочнике будут выглядеть единообразно, и группировка в СКД заработает автоматически, так как строки станут идентичными.
Если у вас нет прав на редактирование справочников или данных слишком много, мы можем решить задачу на уровне компоновки данных. Выясним, как это сделать без изменения исходных записей.
В СКД на закладке «Вычисляемые поля» можно создать новое поле, например, ОптическаяСилаЧислом. Однако язык выражений СКД ограничен. Лучшим решением будет:
ИмяВашегоМодуля.ПреобразоватьВЧисло(ОптическаяСилаНаименование).Это позволит пользователю видеть «красивое» наименование, но при этом отчет будет суммировать и группировать данные по реальному числовому значению.
Проанализируем ситуацию с точки зрения долгосрочного планирования. Хранение числовых данных только в строковом виде — это архитектурная уязвимость. Опытные разработчики рекомендуют добавить в справочник дополнительный реквизит ЗначениеЧислом с типом Число(5, 2).
Почему это лучше:
В этом случае в процедуре ПередЗаписью модуля объекта справочника следует прописать автоматическое формирование наименования на основе введенного числа. Рассмотрим пример:
Процедура ПередЗаписью(Отказ)
// Автоматически формируем наименование по стандарту из числового реквизита
ЭтотОбъект.Наименование = Формат(ЭтотОбъект.ЗначениеЧислом, "ЧДЦ=2; ЧВН=+; ЧРД=,");
КонецПроцедуры
Чтобы проблема разного написания не возникла снова, разберем методы контроля ввода. Если ваша предметная область (например, оптика) подразумевает определенный шаг значений (например, 0.25 диоптрий), стоит внедрить проверку кратности. Это отсечет ошибки, когда пользователь вместо «1,5» случайно вводит «1.55».
Также полезно использовать механизм «Завершение ввода текста» в поле ввода, чтобы система предлагала пользователю уже существующие элементы справочника, минимизируя создание дублей с разным написанием.
Мы рассмотрели несколько вариантов решения проблемы группировки «чисел в строках». Подведем итог: самым быстрым решением является использование групповой обработки с программным кодом нормализации наименований. Самым надежным решением является добавление числового реквизита и принудительное форматирование наименования при записи объекта. Выбор зависит от масштаба вашей информационной системы и требований к чистоте данных.