Функция СтрШаблон с именованными маркерами

21.10.19

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

Функция позволяет задавать именованные маркеры формата [Имя], в отличии от типовых нумерованных формата %n

Преимущества по сравнению с типовой функцией СтрШаблон:
- Код вызова функции проще для восприятия за счет именованных маркеров и параметров.
- Устойчива к перестановкам параметров, к вставкам между параметрами, т.к. сопоставление выполняется по именам, а не по порядку.

Пример использования:

Текст = СтрШаблон_("Заказано товаров на сумму [Сумма] в количестве [Колво]",
  "Сумма", 2500, "Колво", 100);

Функция:

Функция СтрШаблон_(Шаблон, 
  п11="", п12="", п21="", п22="", п31="", п32="", п41="", п42="", п51="", п52="",
  п61="", п62="", п71="", п72="", п81="", п82="", п91="", п92="", п101="", п102="",
  п111="", п112="", п121="", п122="", п131="", п132="", п141="", п142="", п151="", п152="") экспорт
	     
	Результат = Шаблон;
	
	Для сч = 1 по 15 Цикл
		ИмяПараметра = Вычислить("п"+сч+"1");
		Маркер = "["+ИмяПараметра+"]";
		
		Если ИмяПараметра = "" Тогда
			Прервать; 
		ИначеЕсли СтрНайти(Результат, Маркер) = 0 Тогда
			ВызватьИсключение СтрШаблон("Не найден маркер %1 в шаблоне ""%2""", Маркер, Шаблон);
		Иначе	
			Результат = СтрЗаменить(Результат, Маркер, Вычислить("п"+сч+"2"));
		КонецЕсли;
		
	КонецЦикла;
	
	// Лишние маркеры удаляем
	Пока Истина Цикл
		Начало = СтрНайти(Результат, "[");
		Конец = СтрНайти(Результат, "]");
		
		Если Начало=0 ИЛИ Конец=0 ИЛИ Начало>Конец Тогда
			Прервать;
		КонецЕсли;
		
		Результат = Лев(Результат,Начало-1) + Сред(Результат,Конец+1);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

 

 
 Функция на RegExp (не нашел сценариев, где RegExp дал бы здесь прирост по сравнению с кодом 1С)

 

 
 Юнит-тесты под Vanessa-ADD 6.4.0

Вступайте в нашу телеграмм-группу Инфостарт

СтрШаблон Шаблон Строки Строка

См. также

Загрузка и выгрузка в Excel Универсальные функции Программист 1С:Предприятие 8 Россия Бесплатно (free)

Описанный ниже подход позволяет в три шага заполнять формулы в Excel файлы, вне зависимости от ОС сервера (MS Windows Server или Linux). Подход подразумевает отказ от работы с COM-объектом в пользу работы через "объектную модель документа" (DOM).

30.10.2025    4602    Abysswalker    11    

46

Универсальные функции Работа с интерфейсом Программист 1С:Предприятие 8 Бесплатно (free)

Порой необходимо временно отключить расширение 1С, не удаляя его, чтобы не потерять данные. Но в этом случае при каждом запуске всем будет лезть уведомление о неактивном расширении, хотя очевидно, это техническая информация, которой не стоит лишний раз пугать пользователей.

14.05.2025    8548    DeerCven    15    

62

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.

21.05.2024    56338    dimanich70    85    

174

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)

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

1 стартмани

18.03.2024    7939    7    John_d    13    

59

Универсальные функции Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

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

12.02.2024    70781    atdonya    31    

72

Универсальные функции Программист 1С:Предприятие 8 Бесплатно (free)

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

30.11.2023    9940    ke.92@mail.ru    17    

68
Отзывы
8. v77 162 22.10.19 10:29 Сейчас в теме
А что если так?

&НаКлиенте
Процедура Команда1(Команда)
	СуммаДолга = 100500;
	Имя = "Петр Петрович";
	ВВ = Вычислить(F("Приветонище, {Имя}. Ваш долг {СуммаДолга} руб."));
	Сообщить(ВВ);
КонецПроцедуры

&НаКлиенте
Функция F(Стр)
	Стр = СтрЗаменить(Стр,"{",Символы.ПС+"^");	
	Стр = СтрЗаменить(Стр,"}",Символы.ПС);
	Стр = СтрРазделить(Стр,Символы.ПС);
	Результат = """""";
	Для Каждого Ст Из Стр Цикл
		Если СтрНачинаетсяС(Ст,"^") Тогда
			Результат = Результат + "+" + Сред(Ст,2,СтрДлина(Ст));	
		Иначе
			Результат = Результат + "+""" + Ст + """";
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;
КонецФункции
Показать
shaykhelov; +1 Ответить
Остальные комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. WalterMort 247 21.10.19 17:47 Сейчас в теме
Однако в коде своего шаблона, автор использует платформенный СтрШаблон, хотя мог использовать и свой.
TMV; kirinalex; tnaiko; +3 Ответить
7. kirinalex 16 21.10.19 21:03 Сейчас в теме
(1) возникает нехороший эффект из за удаления лишних маркеров
нужно будет экранирование квадратных скобок прикрутить
17. dhurricane 22.10.19 14:13 Сейчас в теме
(1) Кстати, действительно еще можно было бы сделать незамысловатую обертку для встроенной функции :)
Функция СтрШаблон_(Знач Шаблон, 
		п11="", п12="", п21="", п22="", п31="", п32="", п41="", п42="", п51="", п52="",
		п61="", п62="", п71="", п72="", п81="", п82="", п91="", п92="", п101="", п102="") экспорт
					
	Шаблон = СтрЗаменить(Шаблон, "["+п11+"]", "%1");
	Шаблон = СтрЗаменить(Шаблон, "["+п21+"]", "%2");
	Шаблон = СтрЗаменить(Шаблон, "["+п31+"]", "%3");
	Шаблон = СтрЗаменить(Шаблон, "["+п41+"]", "%4");
	Шаблон = СтрЗаменить(Шаблон, "["+п51+"]", "%5");
	Шаблон = СтрЗаменить(Шаблон, "["+п61+"]", "%6");
	Шаблон = СтрЗаменить(Шаблон, "["+п71+"]", "%7");
	Шаблон = СтрЗаменить(Шаблон, "["+п81+"]", "%8");
	Шаблон = СтрЗаменить(Шаблон, "["+п91+"]", "%9");
	Шаблон = СтрЗаменить(Шаблон, "["+п101+"]", "%10");
	
	Возврат СтрШаблон(Шаблон, п12, п22, п32, п42, п52, п62, п72, п82, п92, п102);
	
КонецФункции
Показать
18. kirinalex 16 22.10.19 15:10 Сейчас в теме
(17) интересное решение, если не учитывать что в таком виде оно не работает)
ну и если сделать его рабочим, что не трудно, то при несоответствии маркеров параметрам в результате получаем ошибку "Слишком много фактических параметров" - как говорится, разбирайся как хочешь)
20. dhurricane 22.10.19 15:20 Сейчас в теме
(18) Проклятье! Что-то много я сегодня невпопад пишу. Пожалуй, отойду на сегодня от клавиатуры подальше. :)
2. A.Sytchev 21.10.19 17:56 Сейчас в теме
А чем она лучше БСПшной СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку?

https://www.screenpresso.com/=RXKZc
Дмитрий74Чел; ef42; chebser; litonchik; PLAstic; +5 Ответить
3. kirinalex 16 21.10.19 18:05 Сейчас в теме
(2) Читабельнее и не нужно создавать структуру.
Для сравнения:

СтрШаблон_(, "Имя","Вася", "Фамилия","Пупкин", "Город","Москва", "СемейноеПоложение","Все сложно")

Новый Структура("Имя, Фамилия, Город, СемейноеПоложение", "Вася", "Пупкин", "Москва", "Все сложно")
4. A.Sytchev 21.10.19 18:09 Сейчас в теме
(3) Насчет читабельности я бы поспорил.

Параметры = Новый Структура;
Параметры.Вставить("Имя", "Вася");
Параметры.Вставить("Фамилия",  "Пупкин");
Параметры.Вставить("Город",  "Москва");
Параметры.Вставить("СемейноеПоложение", "Все сложно");


А если мне надо 16 параметров?
5. kirinalex 16 21.10.19 18:18 Сейчас в теме
(4)
 СтрШаблон_(, 
   "Имя", "Вася", 
   "Фамилия", "Пупкин", 
   "Город", "Москва",
   "СемейноеПоложение", "Все сложно")


А если мне надо 16 параметров?

Сложный вопрос. У меня нет на него ответа.
Для справки - платформенный СтрШаблон допускает не больше 10ти параметров.

А в индустрии разработки программирования шагнули намного дальше: https://python-scripts.com/string-formatting
6. kirinalex 16 21.10.19 21:02 Сейчас в теме
немного оптимизировал
исправил ошибку в Тест_НеНайденМаркер
8. v77 162 22.10.19 10:29 Сейчас в теме
А что если так?

&НаКлиенте
Процедура Команда1(Команда)
	СуммаДолга = 100500;
	Имя = "Петр Петрович";
	ВВ = Вычислить(F("Приветонище, {Имя}. Ваш долг {СуммаДолга} руб."));
	Сообщить(ВВ);
КонецПроцедуры

&НаКлиенте
Функция F(Стр)
	Стр = СтрЗаменить(Стр,"{",Символы.ПС+"^");	
	Стр = СтрЗаменить(Стр,"}",Символы.ПС);
	Стр = СтрРазделить(Стр,Символы.ПС);
	Результат = """""";
	Для Каждого Ст Из Стр Цикл
		Если СтрНачинаетсяС(Ст,"^") Тогда
			Результат = Результат + "+" + Сред(Ст,2,СтрДлина(Ст));	
		Иначе
			Результат = Результат + "+""" + Ст + """";
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;
КонецФункции
Показать
shaykhelov; +1 Ответить
11. v77 162 22.10.19 11:30 Сейчас в теме
Померил скорость велосипеда из (8). Работает в три раза быстрее и писанины в два раза меньше.

Текст = СтрШаблон_("Заказано товаров на сумму [Сумма] в количестве [Колво]",
  "Сумма", 2500, "Колво", 100);

Текст = Вычислить(F("Заказано товаров на сумму {Сумма} в количестве {Колво}"));
14. kirinalex 16 22.10.19 14:08 Сейчас в теме
(11)
писанины в два раза меньше.

где именно меньше?
15. kirinalex 16 22.10.19 14:10 Сейчас в теме
(8)
СуммаДолга = 100500;
Имя = "Петр Петрович";
ВВ = Вычислить(F("Приветонище, {Имя}. Ваш долг {СуммаДолга} руб."));

А если СуммаДолга лежит в Выборке то нужно будет сделать так?

СуммаДолга = Выборка.Сумма;
Имя = "Петр Петрович";
ВВ = Вычислить(F("Приветонище, {Имя}. Ваш долг {СуммаДолга} руб."));
16. kirinalex 16 22.10.19 14:11 Сейчас в теме
(8)
Функция F(Стр)

Вы считаете что имя функции "F" это нормально? Она будет глобальной?
19. v77 162 22.10.19 15:17 Сейчас в теме
(16) F или не F какая разница. Назовите как хотите.

А если СуммаДолга лежит в Выборке то нужно будет сделать так?

Ну так и писать {Выборка.Сумма}

ВВ = Вычислить(F("Приветонище, {Имя}. Ваш долг {Выборка.Сумма} руб."));
21. kirinalex 16 22.10.19 15:25 Сейчас в теме
(19) ну тогда удачи вам с такой замечательной функцией F

Хотя вашу идею я запомню на всякий пожарный. Мысля у народа работает)
22. v77 162 22.10.19 16:32 Сейчас в теме
(21)
Мысля у народа работает)
А ты типа не народ :)
9. dhurricane 22.10.19 10:40 Сейчас в теме
Мне кажется, что прерывать цикл при первой встрече пустого имени параметра неудачная идея. Это усложнит применение функции для различных шаблонов строк, зависящих от некоторого условия, но при этом с примерно одинаковым набором параметров. Во встроенной функции "СтрШаблон" это как раз порой и раздражает - строгое соответствие списка маркеров списку параметров функции.

Аналогично с удалением неиспользованных параметров. Разве не удобнее становится, когда забытый маркер бросается в глаза при выводе готовой строки?
10. kirinalex 16 22.10.19 11:18 Сейчас в теме
(9) Приведите пример кода когда прерывание при встрече пустого параметра будет неудобно.

Аналогично с удалением неиспользованных параметров. Разве не удобнее становится, когда забытый маркер бросается в глаза при выводе готовой строки?

Я исходил из предположения удобства, когда маркер оказался не нужен в конкретном случае. Так он удалится автоматически. И также работает платформенная СтрШаблон - просто удаляет маркер
12. dhurricane 22.10.19 12:45 Сейчас в теме
(10)
Приведите пример кода когда прерывание при встрече пустого параметра будет неудобно.
Не могу. :) Пока получше думал над примерами, пришел к выводу, что во всех случаях для Вашей функции любая универсальность будет врагом читаемости.

И также работает платформенная СтрШаблон - просто удаляет маркер
Да, конечно. Я нахожу это неудобным, но это дело вкуса, безусловно.

Я ошибся и на счет встроенной СтрШаблон. Поспешил, извините. Она не требует строго соответствия параметров маркерам. Только чтобы маркеров было не меньше, чем параметров функции. Аналогично и у Вас: лишние имена маркеров приведут к исключительной ситуации. Пару раз сталкивался с подобной особенностью, когда хотел написать что-то вроде такого:
Если ЗначениеЗаполнено(Выборка.Склад) Тогда
	ТекстСообщения = НСтр("ru = 'Не хватает товара %1 в количестве %2 на складе %3'");
Иначе
	ТекстСообщения = НСтр("ru = 'Не хватает товара %1 в количестве %2'");
КонецЕсли; 

ТекстСообщения = СтрШаблон(ТекстСообщения, 
	Выборка.Номенклатура, 
	Выборка.Количество, 
	Выборка.Склад);
Показать
И мне кажется такое поведения функции СтрШаблон также неудобным.
13. kirinalex 16 22.10.19 14:05 Сейчас в теме
(12)
И также работает платформенная СтрШаблон - просто удаляет маркер
Да, конечно. Я нахожу это неудобным, но это дело вкуса, безусловно.
Эту реализация я в полной мере еще сам не оценил на практике и сделал так, чтобы у программиста не было потребности самому вычищать эти маркеры или составлять шаблон динамически, а также потому что в платформенной СтрШаблон сделано также. Есть несколько вариантов как сделать - пока остановился на этом.

Если ЗначениеЗаполнено(Выборка.Склад) Тогда
ТекстСообщения = НСтр("ru = 'Не хватает товара %1 в количестве %2 на складе %3'");
Иначе
ТекстСообщения = НСтр("ru = 'Не хватает товара %1 в количестве %2'");
КонецЕсли;

ТекстСообщения = СтрШаблон(ТекстСообщения,
Выборка.Номенклатура,
Выборка.Количество,
Выборка.Склад);
Показать
Ну, лично я не пишу такие универсальные конструкции, не задаю параметры объектам если в них нет реальной потребности. В данном примере это Склад.
23. v77 162 22.10.19 17:01 Сейчас в теме
Кстати. Можно еще ускорить, если заранее шаблон заготовить

	Шаблон = F("Приветонище, {Выборка.Наименование}. Ваш долг {Выборка.СуммаДолга} руб.");
	Пока Выборка.Следующий() Цикл
		ВВ = Вычислить(Шаблон);
		Сообщить(ВВ);
	КонецЦикла;

24. kirinalex 16 22.10.19 17:13 Сейчас в теме
(23) Все таки, на написание функции меня сподвигла не оптимизация, а случаи нечитабельности больших шаблонов. Дискуссия получается полезная, но пока меня никто не убедил отказаться от своей реализации. Краткости кода я предпочитаю стабильность и читабельность.
25. v77 162 22.10.19 17:15 Сейчас в теме
(24) А моя то чем не читабельная. Очень даже читабельная. Да в добавок еще и быстрая. И кода меньше писать.
26. kirinalex 16 22.10.19 17:18 Сейчас в теме
(25) сама функция? Я бы не сказал что читабельная.
И реализация точно не стабильная, т.к. не проверяется синтаксическим контролем.
27. v77 162 22.10.19 17:20 Сейчас в теме
(26) Ну функцию можно написать какую угодно. Тем более сейчас уже не важно как быстро она будет парсить шаблон, т.к. её в цикле можно не использовать.
Для отправки сообщения требуется регистрация/авторизация