Склонение числа прописью

Публикация № 543753 18.08.16

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

Склонение числа прописью число прописью

Склоняет число прописью до 999999 Пример: до склонения "Не позднее 3 (Три) дней", после - "Не позднее 3 (Трех) дней"

Столкнулся с тем, что число дней в договоре необходимо указывать в склонении (например, 3 (Трех) дней), перекопал инет и мануал 1С-ный, ничего не нашел. Может, я слепой или не там искал, не суть. 

Накатал склонялку, реализовал до 999999, т.к. более не нужно. Можно посмотреть, как сделано, и добавить, кому надо, и больше, добавляем слово в структуру и его аналог, в общем, все просто.

Работает так: у функции на входе число прописью, обработанное стандартной функцией 1С ЧислоПрописью(...)

На выходе склоненное или, если не удалось, то, что передали.

Тестил так: от балды вбивал всякие числа - склоняет.

Вот код, может, кому пригодится.

Функция ПолучитьСтруктуруСклонени(ЧислоПрописью)
	ЧислоПрописью = СокрЛП(ЧислоПрописью);
	
	ПадежРодительный = новый структура;
	ПадежРодительный.Вставить("Один","Одного");
	ПадежРодительный.Вставить("Два","Двух");
	ПадежРодительный.Вставить("Три","Трех");
	ПадежРодительный.Вставить("Четыре","Четырех");
	ПадежРодительный.Вставить("Пять","Пяти");
	ПадежРодительный.Вставить("Шесть","Шести");
	ПадежРодительный.Вставить("Семь","Семи");
	ПадежРодительный.Вставить("Восемь","Восьми");
	ПадежРодительный.Вставить("Девять","Девяти");
	ПадежРодительный.Вставить("Десять","Десяти");
	ПадежРодительный.Вставить("Одиннадцать","Одиннадцати");
	ПадежРодительный.Вставить("Двенадцать","Двенадцати");
	ПадежРодительный.Вставить("Тринадцать","Тринадцати");
	ПадежРодительный.Вставить("Четырнадцать","Четырнадцати");
	ПадежРодительный.Вставить("Пятнадцать","Пятнадцати");
	ПадежРодительный.Вставить("Шестнадцать","Шестнадцати");
	ПадежРодительный.Вставить("Семнадцать","Семнадцати");
	ПадежРодительный.Вставить("Восемнадцать","Восемнадцати");
	ПадежРодительный.Вставить("Девятнадцать","Девятнадцати");
	ПадежРодительный.Вставить("Двадцать","Двадцати");
	ПадежРодительный.Вставить("Тридцать","Тридцати");
	ПадежРодительный.Вставить("Сорок","Сорока");
	ПадежРодительный.Вставить("Пятьдесят","Пятидесяти");
	ПадежРодительный.Вставить("Шестьдесят","Шестидесяти");
	ПадежРодительный.Вставить("Семьдесят","Семидесяти");
	ПадежРодительный.Вставить("Восемьдесят","Восьмидесяти");
	ПадежРодительный.Вставить("Девяносто","Девятоста");
	ПадежРодительный.Вставить("Сто","Ста");
	ПадежРодительный.Вставить("Двести","Двухсот");
	ПадежРодительный.Вставить("Триста","Трехсот");
	ПадежРодительный.Вставить("Четыреста","Четырехсот");
	ПадежРодительный.Вставить("Пятьсот","Пятисот");
	ПадежРодительный.Вставить("Шестьсот","Шестисот");
	ПадежРодительный.Вставить("Семьсот","Семисот");
	ПадежРодительный.Вставить("Восемьсот","Восьмисот");
	ПадежРодительный.Вставить("Девятьсот","Девятисот");
	ПадежРодительный.Вставить("Тысяча","Тысячи");
	ПадежРодительный.Вставить("Одна","Одной");
    ПадежРодительный.Вставить("Две","Двух");
	ПадежРодительный.Вставить("Тысяч","Тысяч");
	ПадежРодительный.Вставить("Тысячи","Тысяч");


	МассивСлов = новый массив;
	готово = ложь;
	ПервоеСлово = Истина;
	НовоеСлово = "";
	Перваябуква = "";
	Вырезка= "";
	ВернутьОшибка = ЧислоПрописью;
	Пока НЕ Готово Цикл
		НайденноеЗначение = "";
		НайденныйПробел = Найти(ЧислоПрописью," ");
		Если НайденныйПробел = 0 Тогда
			Если ПервоеСлово Тогда
				Если ПадежРодительный.Свойство(ЧислоПрописью, НайденноеЗначение) Тогда
					Возврат НайденноеЗначение;
				Иначе
					Возврат ВернутьОшибка;
				КонецЕсли;
			Иначе
				Вырезка = СокрЛП(ЧислоПрописью);
				Перваябуква = Врег(ЛЕВ(Вырезка,1));
				ЧислоПрописью = Перваябуква + Прав(Вырезка,СтрДлина(Вырезка)-1);

				Если ПадежРодительный.Свойство(ЧислоПрописью, НайденноеЗначение) Тогда
					НайденноеЗначение = НРЕГ(НайденноеЗначение);
					НовоеСлово = НовоеСлово + НайденноеЗначение + " ";
					Возврат сОКРлп(НовоеСлово);
				Иначе
					Возврат ВернутьОшибка;
				КонецЕсли;

			КонецЕсли;
		Иначе
			Вырезка = СокрЛП(ЛЕВ(ЧислоПрописью,НайденныйПробел));
			Перваябуква = Врег(ЛЕВ(Вырезка,1));
			Вырезка = Перваябуква + Прав(Вырезка,СтрДлина(Вырезка)-1);
			Если ПадежРодительный.Свойство(Вырезка, НайденноеЗначение) Тогда
				Если ПервоеСлово Тогда
					НовоеСлово = НовоеСлово + НайденноеЗначение + " ";
					первоеСлово = Ложь;
					ЧислоПрописью = СокрЛП(Прав(ЧислоПрописью,СтрДлина(ЧислоПрописью)-НайденныйПробел));
				Иначе
					НовоеСлово = НовоеСлово + НРЕГ(НайденноеЗначение) + " ";
					ЧислоПрописью = СокрЛП(Прав(ЧислоПрописью,СтрДлина(ЧислоПрописью)-НайденныйПробел));

				КонецЕсли;
			Иначе
				Возврат ВернутьОшибка;
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
КонецФункции

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. ZOMI 438 19.08.16 11:59 Сейчас в теме
Уж если так важна каждая буковка в договоре - не быстрее ли договор поправить на "не позднее чем за 3(Три) дня" ?

2. maxvcb 67 19.08.16 12:04 Сейчас в теме
(1) ZOMI, мне не важна юристам важна. Меня попросили я сделал разговоры разговаривать не в моих правилах.
zinnaz; kuzyara; baracuda; +3 1 Ответить
3. Fragster 1123 19.08.16 16:12 Сейчас в теме
Есть хорошая универсальная штука (в договорах, например, еще есть пункты типа "в лице генерального директора, действующего на основании устава", где выделенные куски также должны браться из базы) http://infostart.ru/public/330103/
BarsukM; daMaster; klinval; premierex; Uncore; ZOMI; +6 Ответить
4. maxvcb 67 19.08.16 18:51 Сейчас в теме
(3) Fragster, и? она числительные склоняет? к чему вот писать охинею? я выложил довольно таки простой код склонения числительных, мне зачем ваши фамилии? К чему вот это сообщение?
5. maxvcb 67 19.08.16 18:55 Сейчас в теме
(3) Fragster, склоняет таки, не посмотрел код сразу, приношу извинения. Ну дело то добровольное, у меня код по проще. Я выложил не хотите не берите че минусовать то.
7. dgolovanov 22.08.16 16:51 Сейчас в теме
(5) слюнями много брызжете, вот и минусуют
6. Артано 738 22.08.16 01:57 Сейчас в теме
Я для данной задачи использовал типовую склонялку, склоняющую рубли. Просто вместо слова рубль используется день :-)
116hrus; ARL; Uncore; +3 1 Ответить
8. Uncore 1262 23.08.16 09:40 Сейчас в теме
9. maxvcb 67 23.08.16 13:23 Сейчас в теме
(6) Артано, чет не понятно, тут склоняются не Дни а Числа.
11. Артано 738 24.08.16 07:12 Сейчас в теме
(9) перечитайте еще раз моё сообщение и вы всё поймете. Если нет, то изучите имеющиеся механизмы склонения в типовых. Изобретать велосипеды может быть приятно, но смекалку и находчивость еще никто не отменял
12. Terve!R 24.08.16 11:16 Сейчас в теме
(11) ты бы еще склонять через morpher.ru предложил)
Если конфа на БСП, то конечно лучше разобраться и типовые функции склонения использовать. Но тут кажется весьма универсальный для данной задачи велосипед получился, пусть будет :)
13. maxvcb 67 24.08.16 11:51 Сейчас в теме
(11) Артано, перечитал, тут либо я дурак либо одно из двух.
Типовая склонялка это ЧислоПрописью(СрЭск,,",мр1,мр2,мр3,р,жр1,жр2,жр3,ж.0");
где мр и жр это варианты числа
типа рубля, рублей.Рублев
и выдает она
Семь тысяч Двести Тридцать ддва рубля, ты Ркбли поменял на дни иии?
Когда мой велосипед склоняет Семь тысяч Двести Тридцать ДВа в Семи тысяч Тридцати двух и по х** чего рублей дне колес насосов.
Ну и?
ДмитрийС; +1 Ответить
15. ДмитрийС 16.02.18 12:59 Сейчас в теме
(11) Соглашусь с автором, не совсем понятно, как вы собирались стандартным механизмом склонять числительные? Ведь речь идет как раз об этом, а не о "днях, рублях и т.д."

Если это было не голословное утверждение, то просьба привести пример, дабы всех поставить на место.
10. maxvcb 67 23.08.16 13:29 Сейчас в теме
что за люди такие, пишут не в тему еще и минусы ставят. Любители покакать в коментариях
user774630; evg_m; +2 2 Ответить
14. Svasily 14.08.17 14:53 Сейчас в теме
Опечатка : Девятоста
А в остальном, спасибо.
16. Tommy82 62 20.04.18 13:47 Сейчас в теме
спасибо, утащил, то, что надо
17. o4karek 20.04.18 14:32 Сейчас в теме
А есть еще стандартная СтрокаСЧислом().
Вроде то же самое делает
18. maxvcb 67 20.04.18 15:55 Сейчас в теме
(17) ага в точности то же самое, а это я так от нефик делать писал =)))
19. o4karek 20.04.18 16:10 Сейчас в теме
20. maxvcb 67 20.04.18 16:29 Сейчас в теме
(19) ну почитайте переписку выше мы уже это обсудили, что типовая склонялка немного не так работает как эта, поэтому эта и была мной написана. Примерно то же самое, но не то же.
21. o4karek 20.04.18 17:14 Сейчас в теме
(20) в переписке выше - ЧислоПрописью(). Я, конечно, очкарег, но СтрокаСЧислом() и ЧислоПрописью() - слегка не одно и тоже.
Пример из СП практически ваш:
// Пример вывода строки, содержащей количество дней до нового года
Строка = СтрокаСЧислом(";остался %1 день;;осталось %1 дня;осталось %1 дней;осталось %1 дня",
    ДнейДоНовогоГода,
    ВидЧисловогоЗначения.Количественное,
    "L=ru");
Строка = "До Нового Года " + Строка;
// Результаты вычисления:
// "До Нового Года остался 1 день"
// "До Нового Года осталось 2 дня"
// "До Нового Года осталось 5 дней"
Показать
22. maxvcb 67 20.04.18 17:24 Сейчас в теме
(21) я извиняюсь не обратил внимания на имя функции.

Тогда все еще печальнее, строка с числом это вообще не то пальто, число прописью хоть какой то схожий функционал т.к. склоняет числа, тогда как вами указанная функция склоняет слово после числа, нет?
23. o4karek 20.04.18 17:30 Сейчас в теме
(22) Может вы все-таки в СП заглянете? И перестанете ставить диагноз по фотке? :)
24. maxvcb 67 20.04.18 17:45 Сейчас в теме
(23) не имею времени на бессмысленную переписку. во первых мой пост вышел по времени ранее чем функция вами описываемая появилась на платформе 1с(статья из ссылки дата и дата моего поста).
во вторых я вам отвечаю что это что то похожее так же как красный ремень для синих джинсов и синий ремень для красных. СП я глянул остаюсь при своем.
25. zinnaz 22.02.19 13:23 Сейчас в теме
maxvcb, спасибо, что поделились разработкой, вещь полезная.
26. user1040609 22.08.19 18:08 Сейчас в теме
Большое спасибо, очень помогли, единственно на вход пришлось подавать очищенное от нулей на конце, иначе ошибку било
27. Mad_117 25.09.19 12:21 Сейчас в теме
28. kit 73 30.11.21 12:56 Сейчас в теме
29. xabigv 06.12.21 08:47 Сейчас в теме
в его случае хватило бы и простого
	ЧислоПрописью = ЧислоПрописью(Число);
        
	ПадежРодительный = Новый Структура;
	ПадежРодительный.Вставить("Один","Одного");
	ПадежРодительный.Вставить("Два","Двух");
	ПадежРодительный.Вставить("Три","Трех");
	ПадежРодительный.Вставить("Четыре","Четырех");
	ПадежРодительный.Вставить("Пять","Пяти");
	ПадежРодительный.Вставить("Шесть","Шести");

	НайденныйПробел = Найти(ЧислоПрописью," ");
	Вырезка  = Лев(ЧислоПрописью,НайденныйПробел -1);
	НайденноеЗначение = "";
	Если ПадежРодительный.Свойство(Вырезка, НайденноеЗначение) Тогда
		Возврат НайденноеЗначение;		
	Иначе
		Возврат ЧислоПрописью;
	КонецЕсли;
Показать


Я сделал проще

СоответствиеЧислоПрописью = Новый Соответствие;	
	СоответствиеЧислоПрописью.Вставить(1,"Одного");
	СоответствиеЧислоПрописью.Вставить(2,"Двух");
 	СоответствиеЧислоПрописью.Вставить(3,"Трех");
 	СоответствиеЧислоПрописью.Вставить(4,"Четырех");
	СоответствиеЧислоПрописью.Вставить(5,"Пяти");
	СоответствиеЧислоПрописью.Вставить(6,"Шести");

	НайденноеЗначение = СоответствиеЧислоПрописью.Получить(Число);
Показать
Оставьте свое сообщение