При разработке печатных форм в 1С:Предприятие программисты часто сталкиваются с ситуацией, когда вместо ожидаемого значения «2018» система выводит строку с пробелом — «2 018». Особенно часто это происходит в задачах, связанных с расчетом периодов, например, когда в январе нужно вывести в документах «декабрь прошлого года». В этой статье мы подробно разберем, почему возникает этот артефакт, и рассмотрим несколько способов решения проблемы: от простых манипуляций со строками до архитектурно правильной работы с объектами типа Дата.
Для начала проанализируем ситуацию, описанную автором темы. Код выглядел следующим образом:
Если Формат(Дата1, "ДФ=ММММ") = "Январь" Тогда
Год_1 = Формат(Дата1, "ДФ=гггг") - 1;
Иначе
Год_1 = Формат(Дата1, "ДФ=гггг");
КонецЕсли;
Разберем по шагам, что здесь происходит. Функция Формат с параметром ДФ=гггг возвращает строку. Когда мы пытаемся вычесть из этой строки единицу (- 1), платформа 1С выполняет неявное преобразование типов. Она видит арифметическую операцию и пытается превратить строку «2019» в число 2019. После выполнения вычитания получается число 2018.
Важный момент: в 1С для числовых типов данных по умолчанию включено форматирование с разделением групп разрядов. По правилам русского языка (и соответствующим региональным настройкам ОС), тысячи отделяются от сотен неразрывным пробелом (символ с кодом 160). Именно поэтому при попытке вывести полученное число обратно в печатную форму или текстовое поле, мы видим «2 018».
Вместо того чтобы «раскладывать» дату на компоненты, превращать их в числа и выполнять арифметику вручную, мы можем воспользоваться встроенным механизмом работы с датами. Это позволит избежать ошибок при переходе года и обеспечит чистоту кода.
Рассмотрим, как оптимизировать алгоритм:
// Вместо условий и вычитания года, просто получаем дату предыдущего месяца
ДатаПрошлогоМесяца = ДобавитьМесяц(Дата1, -1);
// Теперь выводим месяц и год одним вызовом функции Формат
ПредставлениеПериода = Формат(ДатаПрошлогоМесяца, "ДФ='ММММ гггг'");
Почему этот способ лучше? Мы работаем с объектом типа Дата до самого последнего момента. Платформа сама определит, какой был год в прошлом месяце, и применит корректное форматирование. Обратите внимание на использование одинарных кавычек внутри строки формата — это позволяет корректно интерпретировать пробел между названием месяца и годом.
Если по каким-то причинам вам все же необходимо работать с годом как с числом (например, вы получили его функцией Год()), мы должны явно указать платформе, что группировать разряды не нужно. Для этого в строке формата числа используется параметр ЧГ=0 (Числовая Группировка).
Проанализируем пример кода:
// Вариант А: Если год уже является числом
НужныйГод = Год(Дата1) - 1;
СтрокаГода = Формат(НужныйГод, "ЧГ=0");
// Вариант Б: Применение в контексте исходной задачи
Если Месяц(Дата1) = 1 Тогда
ГодЧислом = Число(Формат(Дата1, "ДФ=гггг")) - 1;
Год_1 = Формат(ГодЧислом, "ЧГ=0");
Иначе
Год_1 = Формат(Дата1, "ДФ=гггг");
КонецЕсли;
Параметр ЧГ=0 сообщает системе: «выводи число как есть, не вставляя никаких разделителей». Это гарантирует получение строки «2018» вместо «2 018» независимо от региональных настроек сервера или компьютера пользователя.
Иногда программисты прибегают к «силовым» методам исправления строк. Это менее элегантный способ, но он имеет право на жизнь, если нужно быстро поправить отображение в существующем запутанном модуле. Однако здесь есть «подводный камень»: обычный пробел (клавиша Space) и неразрывный пробел, который вставляет 1С, — это разные символы.
Посмотрим, как правильно выполнить замену:
// Обычная замена пробела может не сработать
ГодСтрокой = СтрЗаменить(СтрокаСПробелом, Символы.НПП, "");
В данном примере Символы.НПП — это системная константа 1С, обозначающая Неразрывный Пробел Представления. Использование этой константы делает код более надежным, чем простое копирование невидимого символа в кавычки. Для решения различных задач строковой обработки и манипуляций с символами можно использовать библиотеку функций для работы со строками в 1С.
Подводя итог нашему анализу, дадим несколько практических советов по работе с датами и числами в 1С:
ДобавитьМесяц(), НачалоМесяца() или КонецКвартала(). Это сохранит тип данных Дата.ДФ=...), для чисел — параметры группировки (ЧГ=...).Самым лаконичным и профессиональным решением для исходной задачи будет использование одной строки кода, которая сразу решает и проблему расчета года, и проблему лишних пробелов:
ТекстДляПечати = Формат(ДобавитьМесяц(ТекущаяДата(), -1), "ДФ='ММММ гггг'");
Такой подход делает ваш код читаемым, устойчивым к ошибкам и понятным для коллег-разработчиков.