Вывод количества лет, месяцев, дней "полупрописью"

25.04.13

Разработка - Универсальные функции

Функция, которая возвращает количество лет, месяцев, дней "полупрописью", т.е. в формате "4 года 5 месяцев 3 дня".

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

Полез я в типовую бухгалтерию от МиСофт, поправил, где только возможно, тестирую и получаю ошибку в непредвиденном месте: есть оказывается функция, которая возвращает вместо 13 месяцев строку "1 год 1 месяц". А у меня дробное число, вот и нарвался я на ошибку.

Скажу честно, мне не понравилась функция, которая вообще не использует возможности 1С по использованию т.н. "Предмета исчисления", вот и решил переписать.

Маленькое пояснение.

В одном из мест кода "день" представлен как "#$ень". Чтобы представить число дней в виде именно числа дальше по коду ищется этот самый "день" и удаляется все, что до него. Когда я искал просто букву "д", то получал результат в виде "12 дцать дней", "20 дцать дней", а усложнять код для поиска "день, дня, дней" не захотел.

Советую и "год, года, лет" в "Предмете исчисления" представить как "@@год, @@года, @@лет" для исключения из кода двойного поиска по словам "год, лет".

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

Собственно функция:

Функция РасшифровкаСрокаПолезногоИспользования(СрокПолезногоИспользования) Экспорт

РасшифровкаСрокаПолезногоИспользования = "";
Если ЗначениеЗаполнено(СрокПолезногоИспользования) Тогда
ЧастьМесяца = СрокПолезногоИспользования - Цел(СрокПолезногоИспользования);
ЧислоДней = Цел(30 * ЧастьМесяца);
Суффикс = "";
Если НЕ ЧислоДней = 0 Тогда
Суффикс = ЧислоПрописью(ЧислоДней, "НД = Ложь", "#$ень, #$ня, #$ней, м,,,,,0");
ПозицияПослеПрописи = Найти(Суффикс, "#$");
Суффикс = Сред(Суффикс, ПозицияПослеПрописи);
Суффикс = " " + СокрЛП(ЧислоДней) + " " + Суффикс;
КонецЕсли;
ЧислоЛет = Цел(СрокПолезногоИспользования / 12);
ЧислоМесяцев = Цел((СрокПолезногоИспользования % 12));
ЧислоЛетМесяцев = ЧислоЛет + ЧислоМесяцев/100;
Если ЧислоЛет = 0 Тогда
СтрокаЧислоЛетМесяцев = ЧислоПрописью(ЧислоМесяцев, "НД = Ложь", "месяц, месяца, месяцев, м,,,,,0");
СтрокаПоиска = "месяц";
Иначе
СтрокаЧислоЛетМесяцев = ЧислоПрописью(ЧислоЛетМесяцев, ?(ЧислоМесяцев = 0, "НД = Ложь", "НД = Истина"), "год, года, лет, м" + ?(ЧислоМесяцев = 0, ",,,,,0" ,", месяц, месяца, месяцев, м, 2"));
СтрокаПоиска = "год";
КонецЕсли;
ПозицияПослеЛет = Найти(СтрокаЧислоЛетМесяцев, СтрокаПоиска);
Если ПозицияПослеЛет = 0 Тогда
ПозицияПослеЛет = Найти(СтрокаЧислоЛетМесяцев, "лет");
Если ПозицияПослеЛет = 0 Тогда
//Фигня какая-то, оставим алгоритм МиСофт
От сих старый код типовой конфигурации
**************************************
Если НЕ (ЧислоЛет = 0) Тогда
// Построим строку с числом лет
Если (СтрДлина(ЧислоЛет) > 1) И (Число(Сред(ЧислоЛет, СтрДлина(ЧислоЛет) - 1, 1)) = 1) Тогда
СтрокаГод = " лет";
ИначеЕсли Число(Прав(ЧислоЛет, 1)) = 1 Тогда
СтрокаГод = " год";
ИначеЕсли (Число(Прав(ЧислоЛет, 1)) > 1) И (Число(Прав(ЧислоЛет, 1)) < 5) Тогда
СтрокаГод = " года";
Иначе
СтрокаГод = " лет";
КонецЕсли;
РасшифровкаСрокаПолезногоИспользования = РасшифровкаСрокаПолезногоИспользования + Строка(ЧислоЛет) + СтрокаГод;
КонецЕсли;
Если НЕ (ЧислоМесяцев = 0) Тогда
// Построим строку с числом месяцев
Если (СтрДлина(Цел(ЧислоМесяцев)) > 1) И (Число(Сред(Цел(ЧислоМесяцев), СтрДлина(Цел(ЧислоМесяцев)) - 1, 1)) = 1) Тогда
СтрокаМесяц = " месяцев";
ИначеЕсли Число(Прав(Цел(ЧислоМесяцев), 1)) = 1 Тогда
СтрокаМесяц = " месяц";
ИначеЕсли (Число(Прав(Цел(ЧислоМесяцев), 1)) > 1) И (Число(Прав(Цел(ЧислоМесяцев), 1)) < 5) Тогда
СтрокаМесяц = " месяца";
Иначе
СтрокаМесяц = " месяцев";
КонецЕсли;
РасшифровкаСрокаПолезногоИспользования = РасшифровкаСрокаПолезногоИспользования + ?(НЕ ЗначениеЗаполнено(РасшифровкаСрокаПолезногоИспользования), "", " ") + Строка(ЧислоМесяцев) + СтрокаМесяц;
КонецЕсли;
РасшифровкаСрокаПолезногоИспользования = "(" + РасшифровкаСрокаПолезногоИспользования + ")";
 
**************************************
До сих старый код типовой конфигурации
 

КонецЕсли;
КонецЕсли;
Если РасшифровкаСрокаПолезногоИспользования = "" Тогда
РасшифровкаСрокаПолезногоИспользования = СокрЛП(?(ЧислоЛет = 0, ЧислоМесяцев, ЧислоЛет)) + " " + Сред(СтрокаЧислоЛетМесяцев, ПозицияПослеЛет);
//Уберем обязательное двузначное число месяцев, если оно получилось:
РасшифровкаСрокаПолезногоИспользования = СтрЗаменить(РасшифровкаСрокаПолезногоИспользования, " 0", " ") + СтрЗаменить(Суффикс, "#$", "д");
 
 
КонецЕсли;
КонецЕсли;
Возврат РасшифровкаСрокаПолезногоИспользования;
КонецФункции// РасшифровкаСрокаПолезногоИспользования()

Здесь же оставил часть кода МиСофта на непредвиденные мною ситуации.

См. также

Вставляем картинку из буфера обмена (платформа 1С 8.3.24)

Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    2671    0    John_d    8    

54

GUID в 1С 8.3 - как с ними быть

Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    4612    atdonya    22    

45

Переоткрытие внешних обработок

Универсальные функции Платформа 1С v8.3 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    3961    ke.92@mail.ru    16    

61

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

28.08.2023    8831    YA_418728146    6    

141

Печать непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    2077    21    progmaster    7    

3

Расширение: Быстрые отборы через буфер [Alt+C] Копировать список, [Alt+V] Вставить список, [Ctrl+C] Копировать из файлов

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    16148    133    sapervodichka    112    

129

Система контроля ведения учета [БСП]

Универсальные функции Механизмы типовых конфигураций БСП (Библиотека стандартных подсистем) Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    7243    quazare    8    

109
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. juntatalor 63 24.04.13 21:38 Сейчас в теме
Функция, безусловно, хорошая.

Но вы слышали, что вместо того, чтобы использовать вот такие конструкции:

(Число(Прав(Цел(ЧислоМесяцев), 1)) < 5)

Можно использовать операцию остатка целочисленного деления?

ЧислоМесяцев % 10 < 5?
13jaguar; elenko1; +2 Ответить
2. vld_trade 32 25.04.13 00:23 Сейчас в теме
(1) Это код МиСофт, который я оставил для сравнения или на случай моего тупизма.
3. Intervent 25.04.13 10:44 Сейчас в теме
На входе: 1.2
На выходе: 1 месяц 6 #$ней
Ожидал: 1 месяц 6 дней
4. vld_trade 32 25.04.13 11:22 Сейчас в теме
(3) Поправил и саму функцию и вставил пояснение про эти самые "#$ни". В 11:20 (GMT+3) публикация обновлена (проверил).
Товарищи программисты! Представленная в публикации функция, если ее вставить в код 1С не заработает!
Удалите из кода строчки, разукрашенные фиолетовым.
5. Intervent 25.04.13 13:48 Сейчас в теме
Если решил использовать ЧислоПрописью(), то можно проще:
Функция РасшифровкаСрокаПолезногоИспользования2(СрокПолезногоИспользования) Экспорт
	НазванияПериодов = "день,дня,дней,месяц,месяца,месяцев,год,года,лет";
	Периоды = СтрЗаменить(НазванияПериодов, ",", Символы.ПС);
	СрокВДнях = Цел(СрокПолезногоИспользования * 30);
	ЧислоДней    =  СрокВДнях % 30;
	ЧислоМесяцев = (СрокВДнях - ЧислоДней) / 30 % 12;
	ЧислоЛет     = (СрокВДнях - ЧислоМесяцев * 30 - ЧислоДней) / 360;
	Возврат СокрЛ(?(СрокВДнях < 30, "0 месяцев", "")
			+ Полупропись(ЧислоЛет,     Периоды, 6) 
			+ Полупропись(ЧислоМесяцев, Периоды, 3)
			+ Полупропись(ЧислоДней,    Периоды)); 
КонецФункции 

Функция Полупропись(Число, Периоды, Сдвиг = 0) Экспорт
	Если Число > 0 Тогда
		Пропись = ЧислоПрописью(Число,, "1,2,3,м,,,,,0");
		Возврат " " + Число + " " + СтрПолучитьСтроку(Периоды, Сдвиг + Прав(Пропись, 1));
	КонецЕсли; 
КонецФункции
Показать

Тест на правильность:
&НаКлиенте
Процедура Команда1(Команда)
   Тест();
КонецПроцедуры
	
&НаСервереБезКонтекста
Процедура Тест()
	Для Месяцы = 0 По 300 Цикл
		Для Дни = 0 По 30 Цикл
			Срок = Месяцы + Дни / 30 + 0.001;
			Вариант1 = РасшифровкаСрокаПолезногоИспользования (Срок);		
			Вариант2 = РасшифровкаСрокаПолезногоИспользования2(Срок);
			Если Вариант1 <> Вариант2 Тогда
				Сообщить("Вариант1: " + Вариант1);
				Сообщить("Вариант2: " + Вариант2);
				Возврат;
			КонецЕсли;
		КонецЦикла; 
	КонецЦикла;
	Сообщить("Функции совпадают");
КонецПроцедуры
Показать

По замерам, Вариант1/Вариант2 = 9/11 сек. (на 301*31 итераций), зато Вариант2 читабельней.
Если требуется оптимизированный вариант, то лучше делать без тяжёлой ЧислоПрописью().
13jaguar; vld_trade; +2 Ответить
6. vld_trade 32 25.04.13 14:55 Сейчас в теме
(5) Намного читабельнее, спасибо за наводку про "Периоды", которые "все в одном". В "Периоды", если использовать Структуру вместо текста, можно получить повышение производительности?
7. Intervent 25.04.13 16:09 Сейчас в теме
Пожалуйста. :)
Давай замерим (для упрощения выбираю одинаковый номер - 1):
Процедура Тест()
	Для Счёт = 1 По 99999 Цикл
		Вариант2 = ЗамерМногострочнаяСтрока(); //1,315
		Вариант3 = ЗамерМассив();              //1,363
		Вариант4 = ЗамерСтруктура();           //2,050
	КонецЦикла;
КонецПроцедуры

&НаСервереБезКонтекста
Функция ЗамерМногострочнаяСтрока()
   НазванияПериодов = "день,дня,дней,месяц,месяца,месяцев,год,года,лет";
   Периоды = СтрЗаменить(НазванияПериодов, ",", Символы.ПС);
   ЗамерМногострочнаяСтрока = СтрПолучитьСтроку(Периоды,1);
КонецФункции

&НаСервереБезКонтекста
Функция ЗамерМассив()
   Массив = Новый Массив(9);
   Массив[0] = "день";  Массив[3] = "месяц";   Массив[6] = "год"; 
   Массив[1] = "дня";   Массив[4] = "месяца";  Массив[7] = "года"; 
   Массив[2] = "дней";  Массив[5] = "месяцев"; Массив[8] = "лет";    
   ЗамерМассив = Массив[1];
КонецФункции 

&НаСервереБезКонтекста
Функция ЗамерСтруктура()
	Период = "";
	Структура = Новый Структура;
	Структура.Вставить("i1", "день");
	Структура.Вставить("i2", "дня");
	Структура.Вставить("i3", "дней");
	Структура.Вставить("i4", "месяц");
	Структура.Вставить("i5", "месяца");
	Структура.Вставить("i6", "месяцев");
	Структура.Вставить("i7", "год");
	Структура.Вставить("i8", "года");
	Структура.Вставить("i9", "лет");
	Структура.Свойство("i" + 1, Период);
	ЗамерСтруктура = Период;
КонецФункции 
Показать

Итог: прироста производительности нет.
8. brunet 39 28.08.13 18:08 Сейчас в теме
В сроках полезного использования могут быть только целые месяца и никаких дней там не должно быть.
Оставьте свое сообщение