Формирование синонима переменной из идентификатора

Программирование - Практика программирования

Функция формирует синоним переменной из идентификатора, как это делает платформа 1С8.

Функция формирует синоним переменной из идентификатора, как это делает платформа 1С8.
Используется при визуализации таблицы значений, давая читабельные для пользователей названия колонок:

  • "СуммаБезНДС" => "Сумма без НДС",
  • "СуммаЗадолженностиКонтрагента" => "Сумма задолженности контрагента",
  • "СинонимПеременной" => "Синоним переменной".

Для 7.7 переделывается легко.

// Формирует синоним переменной.
// Пример: на входе "ИмяПеременнойАБВГ", на выходе "Имя переменной АБВГ"
//
// Параметры
// ИмяРеквизита - Строка. Имя переменной, имя колонки таблицы
//
// Возвращаемое значение:
// Строка - Представление переменной
//
Функция СформироватьСиноним(ИмяРеквизита)
    
    Перем Синоним, ъ, Символ, ПредСимвол, СледСимвол, Прописная, ПредПрописная, СледПрописная, ДлинаСтроки;
    
    Синоним = ВРег(Сред(ИмяРеквизита, 1, 1));
    ДлинаСтроки = СтрДлина(ИмяРеквизита);
    Для ъ=2 По ДлинаСтроки Цикл
        Символ = Сред(ИмяРеквизита, ъ, 1);
        ПредСимвол = Сред(ИмяРеквизита, ъ-1, 1);
        СледСимвол = Сред(ИмяРеквизита, ъ+1, 1);
        Прописная = Символ = ВРег(Символ);
        ПредПрописная = ПредСимвол = ВРег(ПредСимвол);
        СледПрописная = СледСимвол = ВРег(СледСимвол);
        
        // Варианты:
        Если НЕ ПредПрописная И Прописная Тогда
            Синоним = Синоним + " " + Символ;
        ИначеЕсли Прописная И НЕ СледПрописная Тогда
            Синоним = Синоним + " " + Символ;
        Иначе
            Синоним = Синоним + Символ;
        Конецесли;
    КонецЦикла;
    
    Возврат Синоним;
    
КонецФункции // СформироватьСиноним()

См. также

Комментарии
1. Андрей Акулов (DrAku1a) 1213 21.11.12 02:55 Сейчас в теме
А вот обратное преобразование:

// Преобразовывает имя переменной к более читабельному виду, аналогично внутренним алгоритмам 1С
// Например "ОбменСБазой" -> "Обмен с базой"
Функция ПредставлениеПерменной(знач ИмяПеременной) Экспорт
	Перем МаленькиеБуквы, Буква, Ответ, сч, ПредыдущаяБуква, СледующаяБуква;
	ИмяПеременной = СокрЛП(ИмяПеременной);
	МаленькиеБуквы = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя_";
	Буква = Лев(ИмяПеременной, 1);
	Ответ = ""+Буква;
	Для сч=2 По СтрДлина(ИмяПеременной) Цикл
		ПредыдущаяБуква = Буква;
		Буква = Сред(ИмяПеременной, сч, 1);
		Если (Найти(МаленькиеБуквы, Буква)=0) и (Найти(МаленькиеБуквы, ПредыдущаяБуква)>0) Тогда
			СледующаяБуква = Сред(ИмяПеременной, сч+1, 1);
			Если (СледующаяБуква<>"") и (Найти(МаленькиеБуквы, СледующаяБуква)>0) Тогда
				Буква = НРег(Буква);
			КонецЕсли;
			Буква = " "+Буква;
		КонецЕсли;
		Ответ = Ответ + Буква;
	КонецЦикла;
	Возврат СтрЗаменить(Ответ, "_", " ");
КонецФункции
...Показать Скрыть


P.S. ъ - как счетчик цика... мда... оригинально.
GATTUSO; anchovy; awk; Rustig; shakmaev; +5 Ответить 1
2. nelse (nelse) 21.11.12 04:09 Сейчас в теме
Мура
GATTUSO; srv7; shakmaev; RomanUzmov; wolfsoft; +5 Ответить 1
3. Андрей Акулов (DrAku1a) 1213 21.11.12 08:05 Сейчас в теме
(2) Иногда требуется и так поизвращаться...
4. Сергей Буланкин (bulas) 104 21.11.12 08:23 Сейчас в теме
Если для счетчика вместо ъ использовать Ё, то работает быстрее.
zfilin; srv7; Rustig; SeiOkami; Артано; +5 Ответить 1
5. Антон Рощин (wolfsoft) 2416 21.11.12 11:43 Сейчас в теме
Для ъ=2 По ДлинаСтроки Цикл
<...>
СледСимвол = Сред(ИмяРеквизита, ъ+1, 1);

Дальше можно не смотреть.
GATTUSO; srv7; Serj1C; +3 Ответить 1
6. vladal (Vladal) 21.11.12 12:41 Сейчас в теме
(4) bulas, многолетние опыты британских учёных подтвердили использование именно маленького твёрдого знака "ъ" вместо заглавной "Ё".
7. vladal (Vladal) 21.11.12 12:43 Сейчас в теме
(5) wolfsoft, предложи свой вариант, мне интересно.
8. Игорь Гончаров (SPID) 21.11.12 13:02 Сейчас в теме
А что вернет по идентификатору СуммаСНДС? Не тестировал, но кажется получается "Сумма СНДС".
9. Сергей Ожерельев (Поручик) 3624 21.11.12 13:28 Сейчас в теме
Я бы вместо маленького твёрдого знака использовал большой мягкий Ь
anchovy; ShantinTD; +2 Ответить
10. Антон Рощин (wolfsoft) 2416 21.11.12 14:01 Сейчас в теме
(7) vladal, лень копаться, навскидку, чтобы не было выходов за границы строки, например так:

Функция СформироватьСиноним(ИмяРеквизита)
	
	Перем Синоним, ъ, Символ, ПредСимвол, СледСимвол, Прописная, ПредПрописная, СледПрописная, ДлинаСтроки;
	
	Синоним = ВРег(Сред(ИмяРеквизита, 1, 1));
	ДлинаСтроки = СтрДлина(ИмяРеквизита);
	
	Для ъ=2 По ДлинаСтроки Цикл
		
		Символ = Сред(ИмяРеквизита, ъ, 1);
		ПредСимвол = Сред(ИмяРеквизита, ъ-1, 1);
		//СледСимвол = Сред(ИмяРеквизита, ъ+1, 1);
		
		Прописная = Символ = ВРег(Символ);
		ПредПрописная = ПредСимвол = ВРег(ПредСимвол);
		//СледПрописная = СледСимвол = ВРег(СледСимвол);
		
		// Варианты:
		Если НЕ ПредПрописная И Прописная Тогда
			Синоним = Синоним + " " + Символ;
		//ИначеЕсли Прописная И НЕ СледПрописная Тогда
		//	Синоним = Синоним + " " + Символ;
		Иначе
			Синоним = Синоним + Символ;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Синоним;
	
КонецФункции // СформироватьСиноним()
...Показать Скрыть
11. vladal (Vladal) 21.11.12 17:18 Сейчас в теме
(8) SPID, да так и вернёт "Сумма СНДС"
12. vladal (Vladal) 21.11.12 17:23 Сейчас в теме
(10) wolfsoft, вроде ошибок не было. СледСимвол в последней итерации возвращает пустую строку (8-ка). В 7.7 нет возможности попробовать.
13. andrewks 1208 21.11.12 17:26 Сейчас в теме
(12) vladal, Сред() не будет ругаться на выход за границы, а просто вернёт пустоту. это ж не си/паскали вам
14. andrewks 1208 21.11.12 17:27 Сейчас в теме
не думал, что подобного рода вспомогательные процедурки, коих пишешь по несколько за день, тянут на публикацию.
GATTUSO; romign; ilov_boris; tolyan_ekb; +4 Ответить 1
15. vladal (Vladal) 21.11.12 17:28 Сейчас в теме
(14) andrewks, да вот сам не думал )))
16. vladal (Vladal) 21.11.12 17:32 Сейчас в теме
(1) DrAku1a, гиде взял? ))

Вот пару строк для этого: (8-ка)

	Синоним = ТРег(ИмяРеквизита);
	Синоним = СтрЗаменить(Синоним, " ", "");
	
	Возврат Синоним;
17. andrewks 1208 21.11.12 18:34 Сейчас в теме
(16) vladal, что она даст для "Цена закупки" ?
18. vladal (Vladal) 21.11.12 20:23 Сейчас в теме
(17) andrewks, ну если пошагово, то так:

    Синоним = ТРег(ИмяРеквизита);            | "Цена Закупки"
    Синоним = СтрЗаменить(Синоним, " ", ""); | "ЦенаЗакупки" 
Rustig; Serj1C; +2 Ответить 2
19. Антон Рощин (wolfsoft) 2416 21.11.12 20:28 Сейчас в теме
(12) в (13) уже ответили

(16) у нас прямо конкурс решений образовался :)
"ленивый" вариант для обратного преобразования

Функция СформироватьРеквизит(Синоним)
	
	Стр = СтрЗаменить(Синоним, " ", Символы.ПС);
	СтрДлина = СтрЧислоСтрок(Стр);
	
	ИмяРеквизита = "";
	Для Индекс = 1 По СтрДлина Цикл
		
		ТекСтр = СтрПолучитьСтроку(Стр, Индекс);
		
		Если ПустаяСтрока(ТекСтр) Тогда
			Продолжить;
		КонецЕсли;
		
		ИмяРеквизита = ИмяРеквизита + ВРег(Лев(ТекСтр, 1)) + Сред(ТекСтр, 2);
		
	КонецЦикла;
	
	Возврат ИмяРеквизита;
	
КонецФункции // СформироватьРеквизит()
...Показать Скрыть
20. vladal (Vladal) 21.11.12 20:29 Сейчас в теме
(19) О! А это уже универсальное решение для любой платформы. Респект и уважуха.

Конкурс! да! профинтерес размяться )))

Я вот думаю над параметром "ЦенаСНДС", чтобы его в "Цена с НДС" перевести, наверно, составить словарь односимвольных слов "С", "а", "в", "к". Если массив прописных букв начинается с этого слова, отедалить её как слово.

"СлаваКПСС" тогда сработает как "Слава к ПСС", зато "СуммаСНДС" будет правильно - "Сумма с НДС"!

----

upd: Хотя нет, Символы.ПС - это ж для 8-ки, а в 7.7 РазделительСтрок.
Да и отталкиваться тогда удобнее от пробелов.
21. andrewks 1208 21.11.12 20:31 Сейчас в теме
(18) vladal, допустим. а для "Сумма НУ" ?
22. andrewks 1208 21.11.12 20:32 Сейчас в теме
(19) wolfsoft, вот это нормально. сам именно такой алгоритм утвердил "в голове", да писАть лень было )
23. vladal (Vladal) 21.11.12 20:34 Сейчас в теме
Чуть позже, дома проверю)))
24. Андрей Акулов (DrAku1a) 1213 22.11.12 02:27 Сейчас в теме
(16),(18) блин... протупил я... это не обратное преобразование - это аналог получается... :-)
(20) По-идее правильно преобразовывать: "Слава КПСС" <-> "Слава_КПСС", а "Цена закупки" <-> "ЦенаЗакупки", так что, (16) - не совсем верно.
25. Тимофей Шантин (ShantinTD) 85 22.11.12 10:27 Сейчас в теме
(20) vladal, про СлаваКПСС - улыбнул. Спасибо.

не в тему:
Разбор предложения: Дочь генерала.
Дочь - "кто?", генерала - "что делала?".
26. vladal (Vladal) 22.11.12 12:17 Сейчас в теме
(24) DrAku1a, Трям!

А это идея - аббревиатуры отделять знаком подчёркивания.
Да и подчёркивание я не учел в начальной процедуре.
27. Сергей (sstar90) 22.11.12 14:59 Сейчас в теме
Внесу и свою лепту - в прикрепленной обработке функции преобразования, которые я использую.
Результат их выполнения:
"Сумма_С_НДС", "СуммаСНДС" => "Сумма с НДС"
"Сумма с НДС", "Сумма _ с НДС" => "СуммаСНДС"
Прикрепленные файлы:
ВнешняяОбработка1.epf
28. vladal (Vladal) 22.11.12 17:02 Сейчас в теме
29. г. Казань Рустем Гумеров (Rustig) 822 23.11.12 21:02 Сейчас в теме
(20) надо создать слова-исключения, передавать через параметр, выделять из строки целиком, как раз кажется так и реализовано в (27)
30. Евгений Рачковский (eugen91) 25.11.12 01:33 Сейчас в теме
да, по мне можно было красивее найти выход
31. vladal (Vladal) 26.11.12 13:58 Сейчас в теме
32. Alexandr Maloi (maloi_a) 26.11.12 14:18 Сейчас в теме
Проверка на прописные буквы делается просто:

// 7.х
Прописная = Символ>="А" И Символ<="Я" ИЛИ Символ>="A" И Символ<="Z";
// 8.х
Прописная = КодСимвола(Символ)>=КодСимвола("А") И КодСимвола(Символ)<=КодСимвола("Я")
ИЛИ КодСимвола(Символ)>=КодСимвола("A") И КодСимвола(Символ)<=КодСимвола("Z");
33. vladal (Vladal) 26.11.12 15:04 Сейчас в теме
(32) maloi_a, точно. Для 7.7 сгодится. Но ведь в 8-ке куда проще написать
Прописная = Символ = ВРег(Символ);
. С латиницей понятно, там действительно алфавит находится в одной последовательности, не прерываясь.
Что же делать с национальными кодировками? Украинский, белорусский, казахский языки имеют свои буквы, которые не вписываются в диапазон А..Я, они часто стоят отдельно. Та же Ё и ё не вписываются в диапазон "а".."я", они раньше. Так же и с "Ґ" и "ґ", "Є" и "є", "І" и "і", "Ї" и "ї", "Ў" и "ў". Да и КодСимвола("Z") ведь постоянный, можно просто заменить на диапазон 0x41..0x5a. Правда? )))

За подсказку спасибо, в 7.7 код не тестировал, честно.
34. Alexandr Maloi (maloi_a) 26.11.12 15:49 Сейчас в теме
(33)
Всё правильно.
Да и с русским языком тоже проблема с "Ё".
В 7.х простое сравнение строк не пойдёт.
Проверил, там "=" к строкам правильно, а ">", "<" для строк применяются без учёта регистра.
Надо использовать КодСимв() и проверку на Ё.
35. vladal (Vladal) 26.11.12 19:43 Сейчас в теме
(34) maloi_a, не только Ё, но и на другие буквы с диакритическими знаками. Не помню уже, но в каком-то типовом семёрочном клиент-банке при выгрузке/загрузке в/из ДБФ все эти буквы с диакритическими знаками конвертировались туда-сюда. Уже не помню, во что, но эти белорусские Ў были вместе с украинскими Є и Ї. Потому что в ДБФ они терялись (((
36. Олег Пономаренко (O-Planet) 6708 27.11.12 11:20 Сейчас в теме
Обсуждение пошло явно не в то русло :)
Предлагаю альтернативное решение проблемы:

Процедура ВариацияЪ(Знач Стр,П=1)
	Если П>59 Тогда
		Возврат Стр;
	КонецЕсли;	
	Большие="ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁQWERTYUIOPASDFGHJK­LZXCVBNM";
	Махонькие="йцукенгшщзхъфывапролджэячсмитьбюёqwertyuiopasdfgh­jklzxcvbnm";
	Х=Найти(Стр,Сред(Большие,П,1));
	Если Х=0 Тогда
		П=П+1;
	Иначе
		Стр=Лев(Стр,Х-1)+" "+Сред(Махонькие,Х,1)+Сред(Стр,Х+1);
	КонецЕсли;	
	Возврат ВариацияЪ(Стр,П);
КонецПроцедуры
...Показать Скрыть


Зацените мощЪ мысли... :D
37. Олег Пономаренко (O-Planet) 6708 27.11.12 11:23 Сейчас в теме
Пс... И не говорите мне про НРЕГ! Тогда оно уже почти перестанет быть быдлокодом...
38. Alexandr Maloi (maloi_a) 27.11.12 15:18 Сейчас в теме
(37)
Процедуру заменить на функцию
и
Стр=Лев(Стр,Х-1)+" "+Сред(Махонькие,П,1)+Сред(Стр,Х+1);

Тогда будет всё правильно.
39. Vladimir Zemenkov (KillHunter) 6 27.11.12 16:07 Сейчас в теме
да хороший вариант:
Стр=Лев(Стр,Х-1)+" "+Сред(Махонькие,П,1)+Сред(Стр,Х+1);
40. Олег Пономаренко (O-Planet) 6708 27.11.12 17:22 Сейчас в теме
41. Олег Пономаренко (O-Planet) 6708 27.11.12 17:25 Сейчас в теме
А вот интересно, на какой длине строки этот вариант начнёт работать быстрее, чем оригинальный в статье?
42. Сергей (ildarovich) 5212 28.11.12 02:04 Сейчас в теме
Предложу свой вариант на основе стэйт-машины
Функция Синонимайзер(Имя, Ответ = "", Стэйт = 7, б = "") Экспорт
	Для ё = 1 По СтрДлина(Имя) Цикл
		а = Сред(Имя, ё, 1);
		Стэйт = (НРег(а) <> а) * 4 + Цел(Стэйт / 2);
		Ответ = Ответ + ?(Стэйт = 2, НРег(б), ?(ё = 2, ВРег(б), б)) + ?(Стэйт = 4 ИЛИ Стэйт = 5, " ", "");
		б = а
	КонецЦикла;
	Возврат Ответ + б
КонецФункции
...Показать Скрыть
Выгодное отличие здесь в том, что символ вырезается из строки и проверяется на регистр только один раз. Если б не надо было первую букву делать заглавной - было бы еще красивее.
43. PlatonovStepan (Jogeedae) 39 28.11.12 05:15 Сейчас в теме
непорядок :)
СинКосТан32Котан
Син кос тан32 котан - преобразование 1с-ки
Син кос тан 32Котан - преобразование Синонимайзера
44. Alexandr Maloi (maloi_a) 28.11.12 09:16 Сейчас в теме
(41)
При длине имени больше 200 ВариацияЪ() будет быстрее.
Увы.
Мой вариант самый эффективный - сравнение "<>" работает быстрее встроенной Врег().
45. Сергей (ildarovich) 5212 28.11.12 11:00 Сейчас в теме
(43) Внес исправления, теперь должно работать правильно...
Прикрепленные файлы:
Jogeedae; +1 Ответить
46. vladal (Vladal) 29.11.12 11:36 Сейчас в теме
(42) Класс!
Значения параметров что обозначают? // сплю я еще
47. Сергей (ildarovich) 5212 05.12.12 21:03 Сейчас в теме
(46) Значения параметров обозначают начальные значения переменных цикла. Делая их параметрами, мы, кроме сокращения количества строк в записи функции, добиваемся некоторого расширения ее возможностей. Например, присвоив параметру Ответ значение "Синоним:" мы получим результат, начинающийся со строки "Синоним:". Присвоив параметру Стэйт значение 7 * 2 * 2 * 2 * 2 * 2 (7 умножить на два в некоторой степени), мы "защитим от преобразования" соответствующее количество символов в имени. Присвоив параметру б некоторое значение, мы получим результат, начинающийся с этого значения, записанного в верхнем регистре.
48. vladal (Vladal) 06.12.12 01:35 Сейчас в теме
(47) ildarovich, вона, как... Для меня пока слишком умнО.
49. Сергей Ожерельев (Поручик) 3624 17.01.13 12:19 Сейчас в теме
Немного подумал и решил использовать в рабочем проекте.
50. nick max (nick-max) 176 06.08.13 11:02 Сейчас в теме
51. Андрей Андреевич (nalivai-chai) 590 20.09.13 15:52 Сейчас в теме
Хотел здесь найти функцию, которая вернет правильный идентификатор по произвольной строке, но не нашел(:
Пришлось самому писать, вот может кому пригодиться:

//	Возвращает правильный идентификатор переменной языка 1С из произвольной строки.
//
Функция ПолучитьПравильноеИмяИдентификатораЯзыка1С(Строка)
	
	ДлинаСтроки = СтрДлина(Строка);
	
	Идентификатор = "";
	
	ПерваяБуква = Истина;
	
	Для НомерСимвола = 1 По ДлинаСтроки Цикл
		
		ТипСимвола = ТипСимвола(Строка, НомерСимвола); 
		Если ТипСимвола >= 1 И ТипСимвола <= 4 Тогда
			Если ПерваяБуква Тогда
				Идентификатор = Идентификатор + ВРег(Сред(Строка, НомерСимвола, 1));
			Иначе
				Идентификатор = Идентификатор + Сред(Строка, НомерСимвола, 1);
			КонецЕсли;
			ПерваяБуква = Ложь;
		Иначе
			Если ТипСимвола >= 5 И ТипСимвола <= 6 Тогда
				Идентификатор = Идентификатор + Сред(Строка, НомерСимвола, 1);
			КонецЕсли;
			ПерваяБуква = Истина;
		КонецЕсли;
		
	КонецЦикла;
	
	Если ПустаяСтрока(Идентификатор) Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Если ТипСимвола(Идентификатор, 1) = 5 Тогда
		Идентификатор = "_" + Идентификатор;
	КонецЕсли;
	
	Возврат Идентификатор;
   
КонецФункции
	
//	Возвращает код типа символа:
//		1	- верхний регистр кириллицы;
//		2	- нижний регистр криллицы;
//		3	- верхний регистр латиницы;
//		4	- нижний регистр латинцы;
//		5	- цифра;
//		6	- нижние подчеркивание;
//		-1	- не является ни буквой, ни цифрой.
Функция ТипСимвола(Стр, Поз = 1) Экспорт
	
	Код_с = КодСимвола(Стр, Поз);
		
	Код_0		= 48;	//	КодСимвола("0");
	Код_9 		= 57;	//	КодСимвола("9");

	Код_в_Эй	= 65;	//	КодСимвола("A");
	Код_в_Зэд	= 90;	//	КодСимвола("Z");
	Код_н_эй	= 97;	//	КодСимвола("a");
	Код_н_зэд	= 122;	//	КодСимвола("z");
	
	Код_		= 95;   //	КодСимвола("_");

	Код_в_А		= 1040;	//	КодСимвола("А");
	Код_в_Я		= 1071;	//	КодСимвола("Я");
	Код_н_а		= 1072;	//	КодСимвола("а");
	Код_н_я		= 1103;	//	КодСимвола("я");
	
	Если (Код_с >= Код_в_А) И (Код_с <= Код_в_Я) Тогда
		Возврат 1;
	ИначеЕсли (Код_с >= Код_н_а) И (Код_с <= Код_н_я) Тогда
		Возврат 2;
	ИначеЕсли (Код_с >= Код_в_Эй) И (Код_с <= Код_в_Зэд) Тогда
		Возврат 3;
	ИначеЕсли (Код_с >= Код_н_эй) И (Код_с <= Код_н_зэд) Тогда
		Возврат 4;
	ИначеЕсли (Код_с >= Код_0) И (Код_с <= Код_9) Тогда
		Возврат 5;
	ИначеЕсли Код_с = Код_ Тогда
		Возврат 6;
	КонецЕсли;
		
	Возврат -1;
	
КонецФункции

...Показать Скрыть
52. V. L. (Vladal) 412 17.10.13 11:57 Сейчас в теме
(51) nalivai-chai, "нижнее подчеркивание"... Хм... навеяло: "В подвале клуба любителей тавтологии обнаружен смертельно убитый труп погибшего мертвеца".

А можно ж и переделать: убрать недопустимые символы и символ после пробела преобразовать к верхнему регистру, а пробел удалить.
Аналог такой функции я использовал в отчете по менеджерам в 2008 году http://infostart.ru/public/16635
Там динамически формируются колонки в таблице значений по фамилиям менеджеров.

В типовых есть процедура,разлагающая строку на массив слов. Обходя массив делать первый символ верхним. Навскидку:
Подстроки = Общегоназначения.РазложитьСтрокуВМассивПодстрок(Синоним, " ");
Имя = "";
Для каждого ТекСтрока Из Подстроки Цикл
	Имя = Имя + ТРег(ТекСтрока);
КонецЦикла;
...Показать Скрыть
53. Андрей Андреевич (nalivai-chai) 590 17.10.13 19:59 Сейчас в теме
(52) Vladal, однако, не один такой, из Википедии:

... Кроме того, этот символ часто называют «Нижнее подчёркивание», что также некорректно и является плеоназмом — подчёркивание всегда выполняется снизу...
Оставьте свое сообщение