Каждый разработчик, работавший с платформой 1С:Предприятие 7.7, наверняка сталкивался с феноменом, который в кругу программистов называют «жертвой неразрывного пробела». Ситуация стандартная: мы выводим числовое значение в отчет, применяем к нему красивое форматирование с разделением триад, но при определенных условиях (например, когда число равно нулю) в ячейке вместо пустоты зависает невидимый глазу символ. Обычная функция СтрЗаменить с передачей стандартного пробела в кавычках " " не помогает, а в отладчике переменная и вовсе кажется пустой. В этой статье мы подробно разберем природу этого явления и рассмотрим несколько надежных способов решения проблемы.
Давайте проанализируем ситуацию на примере форматной строки, упомянутой в теме форума: Формат(Продажа, "Ч019.2"). Разберем этот формат по символам, чтобы понять логику работы платформы 1С 7.7:
Ч — указывает системе, что мы форматируем числовое значение.0 — чрезвычайно важный флаг. Он отвечает за подавление вывода нулевых значений. Если переменная Продажа равна нулю, система не должна выводить «0.00», а обязана вернуть пустую строку.19 — жестко заданная общая длина поля вывода. Платформа обязана вернуть строку длиной ровно 19 символов..2 — указывает на то, что число должно иметь ровно два знака в дробной части (копейки).Когда значение переменной Продажа отлично от нуля (например, 1500), платформа формирует строку, дополняя ее слева обычными пробелами (код 32) до длины в 19 символов, а само число разделяет на триады неразрывным пробелом (код 160). В итоге мы получаем строку вида: " 1 500.00".
Но что происходит, когда Продажа равна нулю? Флаг 0 подавляет вывод самого числа. Однако требование к длине строки в 19 символов никуда не исчезает! Платформа генерирует строку, состоящую исключительно из 19 пробелов. При этом часть из этих пробелов система делает «неразрывными» (символы-разделители триад), ориентируясь на региональные настройки операционной системы Windows. Именно поэтому стандартная функция СтрЗаменить(Строка, " ", "") удаляет только обычные пробелы с кодом 32, оставляя скрытые неразрывные пробелы с кодом 160 на месте.
Рассмотрим, почему попытки решения «в лоб» часто терпят неудачу:
СокрЛП(): Данная функция отлично справляется с обрезкой обычных пробелов (код 32) по краям строки, но она абсолютно игнорирует неразрывные пробелы (код 160), считая их полноценными значащими символами.КодСимв(Лев(Строка, 1)) возвращает значение 32 (обычный пробел), так как дополнение строки до заданной длины 19 всегда начинается именно с обычных пробелов. В итоге заменяются только они, а скрытые неразрывные пробелы внутри строки остаются нетронутыми.В платформе 1С:Предприятие 8.х существует удобное предопределенное свойство Символы.НПП. В «семерке» такого аналога нет, но мы можем использовать встроенную функцию Симв(), передав ей ASCII-код неразрывного пробела — 160.
Давайте посмотрим на пример кода, который гарантированно очистит строку от любых видов пробелов:
// Получаем отформатированное строковое представление числа
ВременнаяСтрока = Формат(Продажа, "Ч019.2");
// Удаляем неразрывные пробелы (код 160)
ВременнаяСтрока = СтрЗаменить(ВременнаяСтрока, Симв(160), "");
// Дополнительно удаляем обычные пробелы (код 32)
РезультатСтрока = СтрЗаменить(ВременнаяСтрока, " ", "");
Этот способ универсален и отлично подходит, если вам в дальнейшем необходимо преобразовывать полученную строку обратно в число или передавать ее в сторонние системы через выгрузку в текстовые файлы.
Зачем бороться с последствиями, если можно предотвратить появление неразрывных пробелов еще на этапе форматирования? Главная ошибка исходного кода заключалась в жестком ограничении ширины поля (число 19 в параметре Ч019.2).
Если нам не требуется выравнивать числа по правому краю в текстовом файле фиксированной длины, мы можем полностью отказаться от указания ширины. Давайте изменим форматную строку:
// При нулевом значении функция вернет абсолютно пустую строку "" без пробелов
РезультатСтрока = СокрЛП(Формат(Продажа, "Ч0.2"));
Если же перед нами стоит задача полностью избавиться от разделения тысяч на триады программным путем (чтобы число выводилось как «1500.00» вместо «1 500.00»), мы можем воспользоваться недокументированной возможностью настройки разделителей прямо в функции Формат(). Синтаксис 1С 7.7 позволяет жестко переопределить разделитель дробной части и разделитель триад, указав их в конце форматной строки.
Посмотрим на примеры:
// Точка на конце форматной строки отключает группировку триад
БезТриад = Формат(1500, "Ч0.2."); // Вернет строку "1500.00" без пробелов
// Задаем точку как разделитель дробной части, а запятую - как разделитель триад
СвоиРазделители = Формат(1500, "Ч0.2.,"); // Вернет строку "1,500.00"
Если проблема возникает исключительно при выводе печатной формы отчета (таблицы), можно воспользоваться классическим приемом визуального разделения логики. Вместо того чтобы мучить форматные строки в коде, мы можем проверять значение показателя перед выводом строки в отчет.
Рассмотрим, как реализовать этот алгоритм в модуле отчета:
Если Продажа = 0 Тогда
// Исходное значение нулевое - выводим секцию с пустыми ячейками
Таб.ВывестиСекцию("Строка_Пустая");
Иначе
// Значение заполнено - выводим стандартную секцию с форматированием
Таб.ВывестиСекцию("Строка_Данные");
КонецЕсли;
Этот метод хорош тем, что полностью исключает влияние региональных настроек операционной системы пользователя на визуальное отображение отчета на экране и при печати.
Если в вашей базе данных вообще не требуется разделять числа пробелами (например, это специфика учета конкретного предприятия), вы можете отключить использование неразрывных пробелов глобально для всей информационной базы.
Разберем по шагам, как это сделать:
Важное замечание: Этот шаг повлияет на отображение чисел во всех стандартных отчетах и журналах документов по всей базе. Перед применением данного метода обязательно согласуйте это решение с пользователями системы и бухгалтерией.