IE 2016

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

Опубликовал tormozit в раздел Программирование - Практика программирования

Платформа 1С 8 не позволяет получать информацию о реквизитах обычной формы. Эти функции позволят вам получать из любой обычной формы 1С 8.X массив имен ее реквизитов, а также имя ее основной реквизит.
Главные функции - ЛксПолучитьМассивИменРеквизитовФормы и ЛксПолучитьИмяОсновногоРеквизитаФормы. Функция ЛксСтрокаВнутрВХМЛТело взята отсюда http://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);

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

См. также

Лучшие комментарии

47. Andrei.Rch 30.10.2014 15:50
После ряда правок успешно завелось на 8.3. Во всех версиях выше есть ошибки из за кривого движка форума. Правильный тест сохранил во вложение.
# Ответить
43. tormozit 19.07.2012 17:02
Правильный вывод следует сразу же после прочтения названия публикации - "Получение массива имен реквизитов ОБЫЧНОЙ формы и имя ее основного реквизита". Все, кто пробуют метод за рамками описанной области применимости, получают не ожидаемый результат.
+ 2 [ soulsteps; CratosX; ]
# Ответить
3. tormozit 23.11.2008 21:03
Боюсь, я не смогу получить двоичные данные формы в общем случае. Поэтому данный способ - единственный.
+ 1 [ German; ]
# Ответить

Комментарии

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


Потому и затеял эти дела. Форму теперь можно получить из двоичных данных (Как это сделать можно будет посмотреть в новой версии Ei ). Ну а когда есть форма.
Код
Для каждого Элемент из Форма.Элементы.Формы Цикл
Сообщить(Элемент.Имя);
КонецЦикла; 
Показать полностью
# Ответить
3. tormozit 23.11.2008 21:03
Боюсь, я не смогу получить двоичные данные формы в общем случае. Поэтому данный способ - единственный.
+ 1 [ German; ]
# Ответить
4. tormozit 24.11.2008 12:16
Ждите скорого появления функции для получения основного реквизита формы. Она уже есть, токо оформить надо.
+ 1 [ coder1cv8; ]
# Ответить
5. coder1cv8 24.11.2008 12:28
Высший класс!!! +100 от меня!
Ответили: (6)
# Ответить
6. coder1cv8 24.11.2008 12:30
+(5) Про основной реквизит тоже очень интересно посмотреть.
Ответили: (7)
# Ответить
7. tormozit 26.11.2008 08:03
(6) Готово. Реквизиты формы покорены... )
# Ответить
8. Sol 30.11.2008 13:28
А в этой части не напутано?
> //{ Заменяем символы, критичные для XML
>// & на &
.........

Вроде в http://infostart.ru/profile/16971/blogs/344/ в (11) было правильно:
> //{ Заменяем символы, критичные для XML
>// & на &
.........
Ответили: (13) (9)
# Ответить
9. tormozit 01.12.2008 21:42
(8) Это движок форума постарался ;)
# Ответить
10. tormozit 01.12.2008 21:53
Теперь стало некрасиво, зато правильно) Не знаю как в новом форуме оформить код... =(
# Ответить
11. Sol 01.12.2008 21:55
А я не пойму даже, как комментарии упорядочить, чтобы как раньше - новые были сверху.
Ответили: (8)
# Ответить
12. tormozit 01.12.2008 22:33
(12) Согласен. Последние сверху - очень рульно было.
Ответили: (12)
+ 1 [ support; ]
# Ответить
13. tormozit 06.02.2009 12:46
(8) Люди, помогите с проблемой отображения злых символов (&;)!
# Ответить
14. larisab 02.06.2009 20:09
Не могли бы вы еще раз привести функцию ЛксСтрокаВнутрВХМЛТело в виде кода, а не текста, без лишних \, видимо убирая их, что то оставила или удалила лишнюю. Дает ошибку в XMLСтрокаФормы.
# Ответить
15. larisab 02.06.2009 21:21
Сделала, в итоге применения этого метода (0) параметр: КакойТоОбъект.ПолучитьФорму("ФормаЭлемента")), возращает строку "СправочникОбъект", а не массив реквизитов формы и ее основной реквизит.
Ответили: (16)
# Ответить
16. tormozit 02.06.2009 21:29
(15) Вставил как есть. Теперь отображается вроде нормально.
Ответили: (17)
# Ответить
17. larisab 02.06.2009 21:45
(16) А насчет "возращает строку "СправочникОбъект", а не массив реквизитов формы и ее основной реквизит."
Как получить элементы формы?
Ответили: (18)
# Ответить
18. tormozit 02.06.2009 21:49
(17) Вопрос не ясен. Прошу сформулировать четко, что ты хочешь получить. Функции проверены на практике. Они возвращают именно то, что заявлено.
# Ответить
19. larisab 02.06.2009 21:55
ФормаОбъекта = ГрафикОбъект.ПолучитьФорму("ФормаЭлемента");
ПолученнаяФорма = ЛксПолучитьИмяОсновногоРеквизитаФормы(ФормаОбъекта);
Хочу в текст кнопки Месяц вставить:
ТекущаяКнопка = Формат(ДатаМесяца, "ДФ=""ММММ гггг""");
ПолученнаяФорма.КоманднаяПанельКалендаря.Кнопки.Месяц.Текст = ТекущаяКнопка;
# Ответить
20. larisab 02.06.2009 22:09
+19 ГрафикОбъект это уже полученный СправочникОбъект ГрафикиРаботы в ЗУПе.
# Ответить
21. vladnet 04.06.2009 23:21
+1 Искал давно как то как получить имя основного реквизита формы, жаль тогда не нашел )
# Ответить
22. vladnet 16.12.2009 13:28
В 8.2 не работает ни получение списка реквизитов, ни получение основного реквизита. :(
Ответили: (23)
# Ответить
23. tormozit 28.08.2010 15:29
(22) Теперь работает и в 8.2. Единственное - не стал делать получение версии платформы из системной информации в нужном формате. Т.е. нужно в функцию версию платформы передавать в виде строки "81" или "82"
Ответили: (24)
# Ответить
24. vladnet 29.08.2010 10:56
(23) Спасибо )
# Ответить
25. Akela_Crimea 30.08.2010 11:12
Я так понял, что с управляемыми формами эта фича не работает?
Или это я глючу?
Ответили: (26)
# Ответить
26. tormozit 30.08.2010 11:19
(25) Да. Управляемые формы не поддерживаются.
# Ответить
27. mt171 01.10.2010 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)
# Ответить
28. Sergey K 22.03.2011 12:24
Кто-нибудь приведите пример, для чего м.б. использован данный функционал? когда требуется программное определения реквизитов формы?
# Ответить
29. HIgor 15.12.2011 16:29
Вещь полезная. Для неуправляемых форм видимо единственное решение. Но давайте здесь тоже не кастрированную функцию ЛксСтрокаВнутрВХМЛТело запишем :

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

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

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

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

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

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

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

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

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

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

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

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

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


на

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

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

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


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

выхХМЛТело = СтрЗаменить(выхХМЛТело,"&","& amp;"); // пробел убрать между & и amp
выхХМЛТело = СтрЗаменить(выхХМЛТело,"<","& lt;"); // пробел убрать между & и lt
выхХМЛТело = СтрЗаменить(выхХМЛТело,">","& gt;"); // пробел убрать между & gt
# Ответить
46. Sabfir 08.08.2013 11:49
Полезная штука, жаль только, что ресурснозатратная :(
# Ответить
47. Andrei.Rch 30.10.2014 15:50
После ряда правок успешно завелось на 8.3. Во всех версиях выше есть ошибки из за кривого движка форума. Правильный тест сохранил во вложение.

Прикрепленные файлы:

Общий модуль РеквизитыОбычнойФормыТолстыйКлиент_ Модуль.txt
# Ответить
Внимание! За постинг в данном форуме $m не начисляются.
Внимание! Для написания сообщения необходимо авторизоваться
Текст сообщения*
Прикрепить файл