Получение массива имен реквизитов обычной формы и имя ее основного реквизита

20.12.11

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

Платформа 1С 8 не позволяет получать информацию о реквизитах обычной формы. Эти функции позволят вам получать из любой обычной формы 1С 8.X массив имен ее реквизитов, а также имя ее основной реквизит.
Главные функции - ЛксПолучитьМассивИменРеквизитовФормы и ЛксПолучитьИмяОсновногоРеквизитаФормы. Функция ЛксСтрокаВнутрВХМЛТело взята отсюда //infostart.ru/projects/1801.

Если будете применять в реальном времени, делайте кэширование ДокументDOM.

Функция ЛксСтрокаВнутрВХМЛТело(вхСтрока, выхХМЛТело = Неопределено) Экспорт

   
//{ Получение одной длинной строки
   
выхХМЛТело = СтрЗаменить(вхСтрока,СИМВОЛЫ.ПС,"");
   
выхХМЛТело = СтрЗаменить(выхХМЛТело,СИМВОЛЫ.ВК,"");
   
//}

    //{ Заменяем символы, критичные для XML
    //    & на &
    //    < на <
    //    > на >
   
выхХМЛТело = СтрЗаменить(выхХМЛТело,"&","&");
   
выхХМЛТело = СтрЗаменить(выхХМЛТело,"<","<");
   
выхХМЛТело = СтрЗаменить(выхХМЛТело,">",">");

   
//{ Замена одинарных символов
   
выхХМЛТело = СтрЗаменить(выхХМЛТело,",","");
   
выхХМЛТело = СтрЗаменить(выхХМЛТело,"{","");
   
выхХМЛТело = СтрЗаменить(выхХМЛТело,"}","");
   
//}

    //{ Удаляем лишние блоки и
   
выхХМЛТело = СтрЗаменить(выхХМЛТело,"","");
   
выхХМЛТело = СтрЗаменить(выхХМЛТело,"","");
   
//}

    //{ Добавляем перенос строки к и к для удобства поиска различий
   
выхХМЛТело = СтрЗаменить(выхХМЛТело,"",""+СИМВОЛЫ.ПС);
   
выхХМЛТело = СтрЗаменить(выхХМЛТело,"",""+СИМВОЛЫ.ПС);
   
//}

   
Возврат выхХМЛТело;

КонецФункции

Функция
ЛксПолучитьДокументDOMФормы(Форма) Экспорт

   
СтрокаФормы = ЗначениеВСтрокуВнутр(Форма);
   
XMLСтрокаФормы = ЛксСтрокаВнутрВХМЛТело(СтрокаФормы);
   
ЧтениеXML = Новый ЧтениеXML;
   
ЧтениеXML.УстановитьСтроку(XMLСтрокаФормы);
   
ПостроительDOM = Новый ПостроительDOM;
   
ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
    Возврат
ДокументDOM;

КонецФункции
// ЛксПолучитьДокументDOMФормы()

Функция ЛксПолучитьXPathИмениРеквизитаВОписанииРеквизита(ИДВерсииПлатформы = "81")

    Если
ИДВерсииПлатформы = "81" Тогда
       
Результат = "/data[3]";
    ИначеЕсли
ИДВерсииПлатформы = "82" Тогда
       
Результат = "/data[4]";
    КонецЕсли;
    Возврат
Результат;

КонецФункции
// ПолучитьXPathИмениРеквизитаВОписанииРеквизита()

Функция ЛксПолучитьМассивИменРеквизитовФормы(Форма, ИДВерсииПлатформы = "81") Экспорт

   
Массив = Новый Массив;
   
ДокументDOM = ЛксПолучитьДокументDOMФормы(Форма);
   
РазыменовательПИ = Новый РазыменовательПространствИменDOM(ДокументDOM);
   
СтрокаXPath = "/elem[1]/elem[1]/elem[2]/elem[2]/elem" + ЛксПолучитьXPathИмениРеквизитаВОписанииРеквизита(ИДВерсииПлатформы) + "/text()";
   
РезультатXPath = ДокументDOM.ВычислитьВыражениеXPath(СтрокаXPath, ДокументDOM,
   
РазыменовательПИ, ТипРезультатаDOMXPath.НеупорядоченныйИтераторУзлов);
    Пока
1 = 1 Цикл
       
Узел = РезультатXPath.ПолучитьСледующий();
        Если
Узел = Неопределено Тогда
            Прервать;
        КонецЕсли;
       
Текст = Узел.ТекстовоеСодержимое;
       
Длина = СтрДлина(Текст);
       
Текст = Сред(Текст, 2, Длина - 2);
       
Массив.Добавить(Текст);
    КонецЦикла;
    Возврат
Массив;

КонецФункции
// ЛксПолучитьМассивИменРеквизитовФормы()

Функция ЛксПолучитьИмяОсновногоРеквизитаФормы(Форма, ИДВерсииПлатформы = "81") Экспорт

   
ДокументDOM = ЛксПолучитьДокументDOMФормы(Форма);
   
РазыменовательПИ = Новый РазыменовательПространствИменDOM(ДокументDOM);
   
ИмяЭлемента = "/elem[1]/elem[1]/elem[2]/elem[1]/data[1]/text()";
   
РезультатXPath = ДокументDOM.ВычислитьВыражениеXPath(ИмяЭлемента, ДокументDOM, РазыменовательПИ, ТипРезультатаDOMXPath.Строка);
   
КлючОсновногоРеквизита = РезультатXPath.СтроковоеЗначение;

   
ИмяЭлемента = "/elem[1]/elem[1]/elem[2]/elem[2]/elem/elem[1]/data[1]/text()";
   
РезультатXPath = ДокументDOM.ВычислитьВыражениеXPath(ИмяЭлемента, ДокументDOM, РазыменовательПИ,
   
ТипРезультатаDOMXPath.УпорядоченныйИтераторУзлов);
   
Счетчик = 1;
    Пока
1 = 1 Цикл
       
Узел = РезультатXPath.ПолучитьСледующий();
        Если
Узел = Неопределено Тогда
            Прервать;
        КонецЕсли;
        Если
Узел.ТекстовоеСодержимое = КлючОсновногоРеквизита Тогда
            Прервать;
        КонецЕсли;
       
Счетчик = Счетчик + 1;
    КонецЦикла;

    Если
Узел = Неопределено Тогда
        Возврат Неопределено;
    КонецЕсли;

   
СтрокаXPath = "/elem[1]/elem[1]/elem[2]/elem[2]/elem[" + Счетчик + "]" + ЛксПолучитьXPathИмениРеквизитаВОписанииРеквизита(ИДВерсииПлатформы) + "/text()";
   
РезультатXPath = ДокументDOM.ВычислитьВыражениеXPath(СтрокаXPath, ДокументDOM, РазыменовательПИ, ТипРезультатаDOMXPath.Строка);
   
Длина = СтрДлина(РезультатXPath.СтроковоеЗначение);
    Возврат
Сред(РезультатXPath.СтроковоеЗначение, 2, Длина - 2);

КонецФункции
// ЛксПолучитьИмяОсновногоРеквизитаФормы()

См. также

Вставляем картинку из буфера обмена (платформа 1С 8.3.24)

Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

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

1 стартмани

18.03.2024    2670    0    John_d    8    

54

GUID в 1С 8.3 - как с ними быть

Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

12.02.2024    4609    atdonya    22    

45

Переоткрытие внешних обработок

Универсальные функции Платформа 1С v8.3 Бесплатно (free)

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

30.11.2023    3961    ke.92@mail.ru    16    

61

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    8822    YA_418728146    6    

141

Печать непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    2072    21    progmaster    7    

3

Расширение: Быстрые отборы через буфер [Alt+C] Копировать список, [Alt+V] Вставить список, [Ctrl+C] Копировать из файлов

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    16146    133    sapervodichka    112    

129

Система контроля ведения учета [БСП]

Универсальные функции Механизмы типовых конфигураций БСП (Библиотека стандартных подсистем) Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    7243    quazare    8    

109
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. German 413 23.11.08 19:57 Сейчас в теме
2. German 413 23.11.08 20:31 Сейчас в теме
У Брикса вся фишка в том что он не мог на основе двоичных данных(текстовых) получить форму.
Код
СтрокаФормы = ЗначениеВСтрокуВнутр(Форма);
Форма=ЗначениеИзСтрокиВнутр(СтрокаФормы ); //ошибка 
Показать полностью


Потому и затеял эти дела. Форму теперь можно получить из двоичных данных (Как это сделать можно будет посмотреть в новой версии Ei ). Ну а когда есть форма.
Код
Для каждого Элемент из Форма.Элементы.Формы Цикл
Сообщить(Элемент.Имя);
КонецЦикла; 
Показать полностью

3. tormozit 7136 23.11.08 21:03 Сейчас в теме
Боюсь, я не смогу получить двоичные данные формы в общем случае. Поэтому данный способ - единственный.
4. tormozit 7136 24.11.08 12:16 Сейчас в теме
Ждите скорого появления функции для получения основного реквизита формы. Она уже есть, токо оформить надо.
coder1cv8; +1 Ответить
5. coder1cv8 3468 24.11.08 12:28 Сейчас в теме
Высший класс!!! +100 от меня!
6. coder1cv8 3468 24.11.08 12:30 Сейчас в теме
+(5) Про основной реквизит тоже очень интересно посмотреть.
7. tormozit 7136 26.11.08 08:03 Сейчас в теме
(6) Готово. Реквизиты формы покорены... )
8. Sol 54 30.11.08 13:28 Сейчас в теме
А в этой части не напутано?
> //{ Заменяем символы, критичные для XML
>// & на &
.........

Вроде в http://infostart.ru/profile/16971/blogs/344/ в (11) было правильно:
> //{ Заменяем символы, критичные для XML
>// & на &
.........
9. tormozit 7136 01.12.08 21:42 Сейчас в теме
(8) Это движок форума постарался ;)
13. tormozit 7136 06.02.09 12:46 Сейчас в теме
(8) Люди, помогите с проблемой отображения злых символов (&)!
10. tormozit 7136 01.12.08 21:53 Сейчас в теме
Теперь стало некрасиво, зато правильно) Не знаю как в новом форуме оформить код... =(
11. Sol 54 01.12.08 21:55 Сейчас в теме
А я не пойму даже, как комментарии упорядочить, чтобы как раньше - новые были сверху.
12. tormozit 7136 01.12.08 22:33 Сейчас в теме
(12) Согласен. Последние сверху - очень рульно было.
14. larisab 160 02.06.09 20:09 Сейчас в теме
Не могли бы вы еще раз привести функцию ЛксСтрокаВнутрВХМЛТело в виде кода, а не текста, без лишних \, видимо убирая их, что то оставила или удалила лишнюю. Дает ошибку в XMLСтрокаФормы.

15. larisab 160 02.06.09 21:21 Сейчас в теме
Сделала, в итоге применения этого метода (0) параметр: КакойТоОбъект.ПолучитьФорму("ФормаЭлемента")), возращает строку "СправочникОбъект", а не массив реквизитов формы и ее основной реквизит.
16. tormozit 7136 02.06.09 21:29 Сейчас в теме
(15) Вставил как есть. Теперь отображается вроде нормально.
17. larisab 160 02.06.09 21:45 Сейчас в теме
(16) А насчет "возращает строку "СправочникОбъект", а не массив реквизитов формы и ее основной реквизит."
Как получить элементы формы?
18. tormozit 7136 02.06.09 21:49 Сейчас в теме
(17) Вопрос не ясен. Прошу сформулировать четко, что ты хочешь получить. Функции проверены на практике. Они возвращают именно то, что заявлено.
19. larisab 160 02.06.09 21:55 Сейчас в теме
ФормаОбъекта = ГрафикОбъект.ПолучитьФорму("ФормаЭлемента");
ПолученнаяФорма = ЛксПолучитьИмяОсновногоРеквизитаФормы(ФормаОбъекта);
Хочу в текст кнопки Месяц вставить:
ТекущаяКнопка = Формат(ДатаМесяца, "ДФ=""ММММ гггг""");
ПолученнаяФорма.КоманднаяПанельКалендаря.Кнопки.Месяц.Текст = ТекущаяКнопка;
20. larisab 160 02.06.09 22:09 Сейчас в теме
+19 ГрафикОбъект это уже полученный СправочникОбъект ГрафикиРаботы в ЗУПе.
21. vladnet 361 04.06.09 23:21 Сейчас в теме
+1 Искал давно как то как получить имя основного реквизита формы, жаль тогда не нашел )
22. vladnet 361 16.12.09 13:28 Сейчас в теме
В 8.2 не работает ни получение списка реквизитов, ни получение основного реквизита. :(
23. tormozit 7136 28.08.10 15:29 Сейчас в теме
(22) Теперь работает и в 8.2. Единственное - не стал делать получение версии платформы из системной информации в нужном формате. Т.е. нужно в функцию версию платформы передавать в виде строки "81" или "82"
24. vladnet 361 29.08.10 10:56 Сейчас в теме
25. Akela_Crimea 30.08.10 11:12 Сейчас в теме
Я так понял, что с управляемыми формами эта фича не работает?
Или это я глючу?
26. tormozit 7136 30.08.10 11:19 Сейчас в теме
(25) Да. Управляемые формы не поддерживаются.
27. mt171 01.10.10 10:42 Сейчас в теме
tormozit, спасибо за разработку!
Только у меня (8.2.12.80 + ЗУП 2.5.27.6) выдаёт ошибку:

Ошибка при вызове метода контекста (Прочитать): Ошибка разбора XML: - [1,1]
Фатальная ошибка:
Document is empty

ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
по причине:
Ошибка разбора XML: - [1,1]
Фатальная ошибка:
Document is empty

В чём может быть причина? Вызываю из модуля формы при открытии, в качестве параметра ЭтаФорма,"82". Сама строка XMLСтрокаФормы заполнена
42. frc 19.07.12 16:49 Сейчас в теме
(27) mt171,
ну да, видимо, с 2010 года так ничего и не изменилось по 8.2 - так не работает получение реквизитов.
28. Sergey K 65 22.03.11 12:24 Сейчас в теме
Кто-нибудь приведите пример, для чего м.б. использован данный функционал? когда требуется программное определения реквизитов формы?
29. HIgor 21 15.12.11 16:29 Сейчас в теме
Вещь полезная. Для неуправляемых форм видимо единственное решение. Но давайте здесь тоже не кастрированную функцию ЛксСтрокаВнутрВХМЛТело запишем :

Функция ЛксСтрокаВнутрВХМЛТело(вхСтрока, выхХМЛТело = Неопределено) Экспорт

//{ Получение одной длинной строки
выхХМЛТело = СтрЗаменить(вхСтрока,СИМВОЛЫ.ПС,"");
выхХМЛТело = СтрЗаменить(выхХМЛТело,СИМВОЛЫ.ВК,"");
//}

//{ Заменяем символы, критичные для XML
// & на "&"
// < на "<"
// > на ">"
выхХМЛТело = СтрЗаменить(выхХМЛТело,"&","&");
выхХМЛТело = СтрЗаменить(выхХМЛТело,"<","<");
выхХМЛТело = СтрЗаменить(выхХМЛТело,">",">");

//{ Замена одинарных символов
выхХМЛТело = СтрЗаменить(выхХМЛТело,",","</data><data>");
выхХМЛТело = СтрЗаменить(выхХМЛТело,"{","<elem><data>");
выхХМЛТело = СтрЗаменить(выхХМЛТело,"}","</data></elem>");
//}

//{ Удаляем лишние блоки и 
выхХМЛТело = СтрЗаменить(выхХМЛТело,"<data><elem>","<elem>");
выхХМЛТело = СтрЗаменить(выхХМЛТело,"</elem></data>","</elem>");
//}

//{ Добавляем перенос строки к и к для удобства поиска различий
выхХМЛТело = СтрЗаменить(выхХМЛТело,"</elem>","</elem>"+СИМВОЛЫ.ПС);
выхХМЛТело = СтрЗаменить(выхХМЛТело,"</data>","</data>"+СИМВОЛЫ.ПС);
//}

Возврат выхХМЛТело;

КонецФункции
Показать
30. tormozit 7136 15.12.11 17:35 Сейчас в теме
31. fomix 33 22.12.11 15:05 Сейчас в теме
Присодиняюсь к [28]
Кто-нибудь приведите пример, для чего м.б. использован данный функционал? когда требуется программное определения реквизитов формы???????????????????????????????????????????
32. AlexO 135 28.12.11 23:21 Сейчас в теме
Тоже не понял - а зачем этот массив получать? ну там деструктивный анализ формы - еще куда ни шло (хотя как его применяют в статьях - сомнительная цель).
Но какое практическое применение данного массива реквизитов?
33. tormozit 7136 29.12.11 00:01 Сейчас в теме
Например это полезно в команде "Отладить источник" в подсистеме ИР, которая открывает консоль кода и передает в нее грубо говоря форму. Контекстная подсказка подсказывает реквизиты формы.
34. frc 19.07.12 12:22 Сейчас в теме
(33)
а что на входе? некая XML-выгрузка?
35. frc 19.07.12 12:27 Сейчас в теме
(34) frc,
а, вроде разобрался - на входе Форма, превращается СтрокаВнутр, потом эта строка разбирается по кускам и перегружается в формат XML-DOM для анализа...
А что такое "делайте кэширование DOM"?
36. tormozit 7136 19.07.12 12:27 Сейчас в теме
(34) На входе чего? На входе команды всегда ключ записи или ссылка.
37. frc 19.07.12 12:30 Сейчас в теме
(36)
На входе чего?

на входе в функцию "ЛксПолучитьМассивИменРеквизитовФормы"
На входе команды всегда ключ записи или ссылка.

т.е. ссылка на ФормаОбъект?
38. tormozit 7136 19.07.12 13:56 Сейчас в теме
(37) Под командой я подразумевал одноименный объект управляемого приложения. Но теперь я вижу что вопрос был про другое.
39. frc 19.07.12 16:03 Сейчас в теме
(38)
На тот вопрос вы и не ответили :)
Вот ошибка так и возникает:
в
ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);

{ОбщийМодуль.эрФункцииОбщегоНазначения.Модуль(354)}: Ошибка при вызове метода контекста (Прочитать)
по причине:
{ОбщийМодуль.эрФункцииОбщегоНазначения.Модуль(354)}: Ошибка при вызове метода контекста (Прочитать)

по причине:
Ошибка разбора XML: - [1,1]
Фатальная ошибка:
Document is empty
40. frc 19.07.12 16:04 Сейчас в теме
Могу форму в XML (переменная ЧтениеXML) дать.
41. frc 19.07.12 16:30 Сейчас в теме
В общем, значит так и нельзя получить никаких реквизитов таким методом...
43. tormozit 7136 19.07.12 17:02 Сейчас в теме
Правильный вывод следует сразу же после прочтения названия публикации - "Получение массива имен реквизитов ОБЫЧНОЙ формы и имя ее основного реквизита". Все, кто пробуют метод за рамками описанной области применимости, получают не ожидаемый результат.
soulsteps; CratosX; +2 Ответить
44. sergant500 11.02.13 23:28 Сейчас в теме
Если метод выдает ошибку, то заменяем строки в посте №29 (HIgor)

выхХМЛТело = СтрЗаменить(выхХМЛТело,"&","&");
выхХМЛТело = СтрЗаменить(выхХМЛТело,"<","<");
выхХМЛТело = СтрЗаменить(выхХМЛТело,">",">");


на

выхХМЛТело = СтрЗаменить(выхХМЛТело,"&","&");
выхХМЛТело = СтрЗаменить(выхХМЛТело,"<","<");
выхХМЛТело = СтрЗаменить(выхХМЛТело,">",">");

Спасибо за наводку Сергею Чуяну (Собеседник) http://infostart.ru/public/20069/
вызов функции

Процедура ДополнительныеДействияСФормой(ФормаОбъекта) Экспорт
	ИмяОсновногоРеквизита = ЛксПолучитьИмяОсновногоРеквизитаФормы(ФормаОбъекта);
	ОсновнойРеквизит = ФормаОбъекта[ИмяОсновногоРеквизита]; 
	Если ТипЗнч(ОсновнойРеквизит) = Тип("СправочникОбъект.Контрагенты") Тогда
		Сообщить(ОсновнойРеквизит);
	КонецЕсли;	
КонецПроцедуры


Все хорошо работает, но наблюдается потеря времени при открытии форм.
Например функция УстановитьДоступностьПоляВводаНомера, которая вызывается ПриОткрытии() многих форм документов или элементов справочников затрачивает времени 0,003-004 сек. без проверки основного реквизита. А с проверкой 0,35 – 0,6 и больше в зависимости от сложности формы. Визуально заметна разница во времени. Придется мириться с задержкой примерно в половину секунды при открытии любой из форм.
45. sergant500 11.02.13 23:31 Сейчас в теме
Почему-то движок съедает текст. Нужно читать "заменить на"

выхХМЛТело = СтрЗаменить(выхХМЛТело,"&","& amp;"); // пробел убрать между & и amp
выхХМЛТело = СтрЗаменить(выхХМЛТело,"<","& lt;"); // пробел убрать между & и lt
выхХМЛТело = СтрЗаменить(выхХМЛТело,">","& gt;"); // пробел убрать между & gt
46. Sabfir 08.08.13 11:49 Сейчас в теме
Полезная штука, жаль только, что ресурснозатратная :(
47. Andrei.Rch 6 30.10.14 15:50 Сейчас в теме
После ряда правок успешно завелось на 8.3. Во всех версиях выше есть ошибки из за кривого движка форума. Правильный тест сохранил во вложение.
Прикрепленные файлы:
Общий модуль РеквизитыОбычнойФормыТолстыйКлиент_ Модуль.txt
Mkonst; Азбука Морзе; unoDosTres; tormozit; wtlz; dour-dead; +6 Ответить
48. пользователь 14.04.15 16:46
Сообщение было скрыто модератором.
...
49. tormozit 7136 08.08.23 20:15 Сейчас в теме
Для управляемой формы подобного (без выгрузки конфигурации в файлы) способа не нашел. Внутреннее представление управляемой формы не содержит имен реквизитов.
Оставьте свое сообщение