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

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

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

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

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

// Формирует синоним переменной.
// Пример: на входе "ИмяПеременнойАБВГ", на выходе "Имя переменной АБВГ"
//
// Параметры
// ИмяРеквизита - Строка. Имя переменной, имя колонки таблицы
//
// Возвращаемое значение:
// Строка - Представление переменной
//
Функция СформироватьСиноним(ИмяРеквизита)

    Перем Синоним, ъ, Символ, ПредСимвол, СледСимвол, Прописная, ПредПрописная, СледПрописная, ДлинаСтроки;

Синоним = ВРег(Сред(ИмяРеквизита, 1, 1));
    ДлинаСтроки = СтрДлина(ИмяРеквизита);
Для ъ=2 По ДлинаСтроки Цикл
       Символ = Сред(ИмяРеквизита, ъ, 1);
        ПредСимвол = Сред(ИмяРеквизита, ъ-1, 1);
СледСимвол = Сред(ИмяРеквизита, ъ+1, 1);
Прописная = Символ = ВРег(Символ);
ПредПрописная = ПредСимвол = ВРег(ПредСимвол);
СледПрописная = СледСимвол = ВРег(СледСимвол);

// Варианты:
Если НЕ ПредПрописная И Прописная Тогда
Синоним = Синоним + " " + Символ;
ИначеЕсли Прописная И НЕ СледПрописная Тогда
Синоним = Синоним + " " + Символ;
 Иначе
           Синоним = Синоним + Символ;
       Конецесли;
КонецЦикла;

    Возврат Синоним;

КонецФункции // СформироватьСиноним()

53 Comments

  1. DrAku1a

    А вот обратное преобразование:

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

    Показать

    P.S. ъ — как счетчик цика… мда… оригинально.

    Reply
  2. nelse

    Мура

    Reply
  3. DrAku1a

    (2) Иногда требуется и так поизвращаться…

    Reply
  4. bulas

    Если для счетчика вместо ъ использовать Ё, то работает быстрее.

    Reply
  5. wolfsoft
    Для ъ=2 По ДлинаСтроки Цикл

    <…>

    СледСимвол = Сред(ИмяРеквизита, ъ+1, 1);

    Дальше можно не смотреть.

    Reply
  6. v.l.

    (4) bulas, многолетние опыты британских учёных подтвердили использование именно маленького твёрдого знака «ъ» вместо заглавной «Ё».

    Reply
  7. v.l.

    (5) wolfsoft, предложи свой вариант, мне интересно.

    Reply
  8. SPID

    А что вернет по идентификатору СуммаСНДС? Не тестировал, но кажется получается «Сумма СНДС».

    Reply
  9. Поручик

    Я бы вместо маленького твёрдого знака использовал большой мягкий Ь

    Reply
  10. wolfsoft

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

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

    Показать

    Reply
  11. v.l.

    (8) SPID, да так и вернёт «Сумма СНДС»

    Reply
  12. v.l.

    (10) wolfsoft, вроде ошибок не было. СледСимвол в последней итерации возвращает пустую строку (8-ка). В 7.7 нет возможности попробовать.

    Reply
  13. andrewks

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

    Reply
  14. andrewks

    не думал, что подобного рода вспомогательные процедурки, коих пишешь по несколько за день, тянут на публикацию.

    Reply
  15. v.l.

    (14) andrewks, да вот сам не думал )))

    Reply
  16. v.l.

    (1) DrAku1a, гиде взял? ))

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

     Синоним = ТРег(ИмяРеквизита);
    Синоним = СтрЗаменить(Синоним, » «, «»);
    
    Возврат Синоним;
    Reply
  17. andrewks

    (16) что она даст для «Цена закупки» ?

    Reply
  18. v.l.

    (17) andrewks, ну если пошагово, то так:

        Синоним = ТРег(ИмяРеквизита);            | «Цена Закупки»
    Синоним = СтрЗаменить(Синоним, » «, «»); | «ЦенаЗакупки» 
    Reply
  19. wolfsoft

    (12) в (13) уже ответили

    (16) у нас прямо конкурс решений образовался 🙂

    «ленивый» вариант для обратного преобразования

    Функция СформироватьРеквизит(Синоним)
    
    Стр = СтрЗаменить(Синоним, » «, Символы.ПС);
    СтрДлина = СтрЧислоСтрок(Стр);
    
    ИмяРеквизита = «»;
    Для Индекс = 1 По СтрДлина Цикл
    
    ТекСтр = СтрПолучитьСтроку(Стр, Индекс);
    
    Если ПустаяСтрока(ТекСтр) Тогда
    Продолжить;
    КонецЕсли;
    
    ИмяРеквизита = ИмяРеквизита + ВРег(Лев(ТекСтр, 1)) + Сред(ТекСтр, 2);
    
    КонецЦикла;
    
    Возврат ИмяРеквизита;
    
    КонецФункции // СформироватьРеквизит()
    

    Показать

    Reply
  20. v.l.

    (19) О! А это уже универсальное решение для любой платформы. Респект и уважуха.

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

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

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

    —-

    upd: Хотя нет, Символы.ПС — это ж для 8-ки, а в 7.7 РазделительСтрок.

    Да и отталкиваться тогда удобнее от пробелов.

    Reply
  21. andrewks

    (18) допустим. а для «Сумма НУ» ?

    Reply
  22. andrewks

    (19) wolfsoft, вот это нормально. сам именно такой алгоритм утвердил «в голове», да писАть лень было )

    Reply
  23. v.l.

    Чуть позже, дома проверю)))

    Reply
  24. DrAku1a

    (16),(18) блин… протупил я… это не обратное преобразование — это аналог получается… 🙂

    (20) По-идее правильно преобразовывать: «Слава КПСС» <-> «Слава_КПСС», а «Цена закупки» <-> «ЦенаЗакупки», так что, (16) — не совсем верно.

    Reply
  25. ShantinTD

    (20) про СлаваКПСС — улыбнул. Спасибо.

    не в тему:

    Разбор предложения: Дочь генерала.

    Дочь — «кто?», генерала — «что делала?».

    Reply
  26. v.l.

    (24) DrAku1a, Трям!

    А это идея — аббревиатуры отделять знаком подчёркивания.

    Да и подчёркивание я не учел в начальной процедуре.

    Reply
  27. sstar90

    Внесу и свою лепту — в прикрепленной обработке функции преобразования, которые я использую.

    Результат их выполнения:

    «Сумма_С_НДС», «СуммаСНДС» => «Сумма с НДС»

    «Сумма с НДС», «Сумма _ с НДС» => «СуммаСНДС»

    Reply
  28. v.l.

    (27) sstar90, зачёт.

    Reply
  29. Rustig

    (20) надо создать слова-исключения, передавать через параметр, выделять из строки целиком, как раз кажется так и реализовано в (27)

    Reply
  30. eugen91

    да, по мне можно было красивее найти выход

    Reply
  31. v.l.

    (30) eugen91, предлагай!

    Reply
  32. maloi_a

    Проверка на прописные буквы делается просто:

    // 7.х

    Прописная = Символ>=»А» И Символ<=»Я» ИЛИ Символ>=»A» И Символ<=»Z»;

    // 8.х

    Прописная = КодСимвола(Символ)>=КодСимвола(«А») И КодСимвола(Символ)<=КодСимвола(«Я»)

    ИЛИ КодСимвола(Символ)>=КодСимвола(«A») И КодСимвола(Символ)<=КодСимвола(«Z»);

    Reply
  33. v.l.

    (32) maloi_a, точно. Для 7.7 сгодится. Но ведь в 8-ке куда проще написать

    Прописная = Символ = ВРег(Символ);

    . С латиницей понятно, там действительно алфавит находится в одной последовательности, не прерываясь.

    Что же делать с национальными кодировками? Украинский, белорусский, казахский языки имеют свои буквы, которые не вписываются в диапазон А..Я, они часто стоят отдельно. Та же Ё и ё не вписываются в диапазон «а»..»я», они раньше. Так же и с «Ґ» и «ґ», «Є» и «є», «І» и «і», «Ї» и «ї», «Ў» и «ў». Да и КодСимвола(«Z») ведь постоянный, можно просто заменить на диапазон 0x41..0x5a. Правда? )))

    За подсказку спасибо, в 7.7 код не тестировал, честно.

    Reply
  34. maloi_a

    (33)

    Всё правильно.

    Да и с русским языком тоже проблема с «Ё».

    В 7.х простое сравнение строк не пойдёт.

    Проверил, там «=» к строкам правильно, а «>», «<» для строк применяются без учёта регистра.

    Надо использовать КодСимв() и проверку на Ё.

    Reply
  35. v.l.

    (34) maloi_a, не только Ё, но и на другие буквы с диакритическими знаками. Не помню уже, но в каком-то типовом семёрочном клиент-банке при выгрузке/загрузке в/из ДБФ все эти буквы с диакритическими знаками конвертировались туда-сюда. Уже не помню, во что, но эти белорусские Ў были вместе с украинскими Є и Ї. Потому что в ДБФ они терялись (((

    Reply
  36. O-Planet

    Обсуждение пошло явно не в то русло 🙂

    Предлагаю альтернативное решение проблемы:

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

    Показать

    Зацените мощЪ мысли… 😀

    Reply
  37. O-Planet

    Пс… И не говорите мне про НРЕГ! Тогда оно уже почти перестанет быть быдлокодом…

    Reply
  38. maloi_a

    (37)

    Процедуру заменить на функцию

    и

    Стр=Лев(Стр,Х-1)+» «+Сред(Махонькие,П,1)+Сред(Стр,Х+1);

    Тогда будет всё правильно.

    Reply
  39. KillHunter

    да хороший вариант:

    Стр=Лев(Стр,Х-1)+» «+Сред(Махонькие,П,1)+Сред(Стр,Х+1);

    Reply
  40. O-Planet

    (38) точно, П

    Reply
  41. O-Planet

    А вот интересно, на какой длине строки этот вариант начнёт работать быстрее, чем оригинальный в статье?

    Reply
  42. ildarovich

    Предложу свой вариант на основе стэйт-машины

    Функция Синонимайзер(Имя, Ответ = «», Стэйт = 7, б = «») Экспорт
    Для ё = 1 По СтрДлина(Имя) Цикл
    а = Сред(Имя, ё, 1);
    Стэйт = (НРег(а) <> а) * 4 + Цел(Стэйт / 2);
    Ответ = Ответ + ?(Стэйт = 2, НРег(б), ?(ё = 2, ВРег(б), б)) + ?(Стэйт = 4 ИЛИ Стэйт = 5, » «, «»);
    б = а
    КонецЦикла;
    Возврат Ответ + б
    КонецФункции

    Показать

    Выгодное отличие здесь в том, что символ вырезается из строки и проверяется на регистр только один раз. Если б не надо было первую букву делать заглавной — было бы еще красивее.

    Reply
  43. Jogeedae

    непорядок 🙂

    СинКосТан32Котан

    Син кос тан32 котан — преобразование 1с-ки

    Син кос тан 32Котан — преобразование Синонимайзера

    Reply
  44. maloi_a

    (41)

    При длине имени больше 200 ВариацияЪ() будет быстрее.

    Увы.

    Мой вариант самый эффективный — сравнение «<>» работает быстрее встроенной Врег().

    Reply
  45. ildarovich

    (43) Внес исправления, теперь должно работать правильно…

    Reply
  46. v.l.

    (42) Класс!

    Значения параметров что обозначают? // сплю я еще

    Reply
  47. ildarovich

    (46) Значения параметров обозначают начальные значения переменных цикла. Делая их параметрами, мы, кроме сокращения количества строк в записи функции, добиваемся некоторого расширения ее возможностей. Например, присвоив параметру Ответ значение «Синоним:» мы получим результат, начинающийся со строки «Синоним:». Присвоив параметру Стэйт значение 7 * 2 * 2 * 2 * 2 * 2 (7 умножить на два в некоторой степени), мы «защитим от преобразования» соответствующее количество символов в имени. Присвоив параметру б некоторое значение, мы получим результат, начинающийся с этого значения, записанного в верхнем регистре.

    Reply
  48. v.l.

    (47) ildarovich, вона, как… Для меня пока слишком умнО.

    Reply
  49. Поручик

    Немного подумал и решил использовать в рабочем проекте.

    Reply
  50. nick-max

    Вот мой вариант:

    http://infostart.ru/public/196681/

    Reply
  51. nalivai-chai

    Хотел здесь найти функцию, которая вернет правильный идентификатор по произвольной строке, но не нашел(:

    Пришлось самому писать, вот может кому пригодиться:

    // Возвращает правильный идентификатор переменной языка 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;
    
    КонецФункции
    
    

    Показать

    Reply
  52. v.l.

    (51) nalivai-chai, «нижнее подчеркивание»… Хм… навеяло: «В подвале клуба любителей тавтологии обнаружен смертельно убитый труп погибшего мертвеца».

    А можно ж и переделать: убрать недопустимые символы и символ после пробела преобразовать к верхнему регистру, а пробел удалить.

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

    Там динамически формируются колонки в таблице значений по фамилиям менеджеров.

    В типовых есть процедура,разлагающая строку на массив слов. Обходя массив делать первый символ верхним. Навскидку:

    Подстроки = Общегоназначения.РазложитьСтрокуВМассивПодстрок(Синоним, » «);
    Имя = «»;
    Для каждого ТекСтрока Из Подстроки Цикл
    Имя = Имя + ТРег(ТекСтрока);
    КонецЦикла;
    
    Reply
  53. nalivai-chai

    (52) однако, не один такой, из Википедии:

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

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *