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

Функция формирует синоним переменной из идентификатора, как это делает платформа 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 не будет опубликован. Обязательные поля помечены *