Имя: Пароль:
1C
1C 7.7
v7: Как правильно выполнить обращение к переменной или функции по имени?
↓ (Волшебник 23.01.2024 08:53)
0 Chai Nic
 
18.01.24
11:33
Есть строковое значение, содержащее имя функции или переменной некого контекста. Как можно выполнить эту функцию и получить возвращаемое значение? Вроде как можно использовать Шаблон(), но у него два недостатка.

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

Вот пример-иллюстрация в коде обработки.
---
Перем Тест1;

Функция ЗначениеПеременной(знач СтрокаЗначение)  
    Попытка
        Возврат Шаблон("["+СтрокаЗначение+"]");
    Исключение
        Возврат "";
    КонецПопытки;
    
КонецФункции

Процедура Сформировать()  
    Тест1=123;
    
    Сообщить(ЗначениеПеременной("Тест1"));
    Сообщить(ЗначениеПеременной("Тест2"));
КонецПроцедуры
---
Вот что выводится в окно сообщений.

---
123
Тест2<<?>>
Переменная не определена (Тест2)
[Тест2]
---

Можно ли как-то сделать так, чтобы ошибка внутри шаблона перехватывалась?

Или может есть какой-то другой способ для обращения к переменным и функциям контекста или выполнения произвольного кода?
1 ADirks
 
18.01.24
11:47
(0) используй FormEx или 1С++
2 Chai Nic
 
18.01.24
11:51
(1) А поконкретнее? Какие там есть методы для программного обращения к коду, заданному строкой?
3 ADirks
 
18.01.24
12:03
(2) например
- 1С++,
    оМодуль = СоздатьОбъект("ВыполняемыйМодуль");
    Рез = 0;
    оМодуль.ВыполнитьФункциюКонтекста(Конт, ИмяМетода, сзАрг, Рез);

Функция ПеременнаяКонтекста(Конт, ИмяПеременной) Экспорт
    ТекстМодуля = "
    |Функция ЗначениеПеременной()
    |    Возврат "+ИмяПеременной+";
    |КонецФункции
    |";
    
    Модуль = СоздатьОбъект("ВыполняемыйМодуль");
    Модуль.УстановитьМодуль(ТекстМодуля);
    Модуль.НазначитьКонтекст(Конт);
    Модуль.КомпилироватьМодуль();
    Модуль.ВыполнитьМодуль();
    
    Возврат Модуль.ЗначениеПеременной();
КонецФункции

Функция УстановитьПеременную(Конт, ИмяПеременной, Значение) Экспорт
    ТекстМодуля = "
    |Функция УстЗнач(з)
    |    "+ИмяПеременной+" = з;
    |    Возврат "+ИмяПеременной+";
    |КонецФункции
    |";
    
    Модуль = Фаб.Модуль(Конт, ТекстМодуля);
    
    Возврат Модуль.УстЗнач(Значение);
КонецФункции



- FormEx
    оСервис = СоздатьОбъект("Сервис");
    Рез = 0;
    оСервис.ВыполнитьФункцию(Конт, ИмяМетода, сзАрг, Рез);
4 SleepyHead
 
18.01.24
14:15
5 GrayS19
 
18.01.24
14:23
(0) "Первый - он может возвращать только строку" - когда-то увидел как не только строку:

Значение = ЗначениеИзСтрокиВнутр(Шаблон("[ЗначениеВСтрокуВнутр("+ИмяРеквизитаФормы+")]")); // - это чтение реквизита формы через шаблон
6 Djelf
 
18.01.24
15:32
Не надо так. Насколько помню, все 10 вариантов, кроме ВыполняемыйМодуль никто не умеет прочитать переменную ГМ.

Вопрос: зачем проверять в своем модуле переменную, с такими выкрутасами?
Телепатирую: речь идет о ГММодуле, а это умеет только ВМ.

Можно выкрутится и штатно, с переменной, через А=А; и проверкой дальше на ПустоеЗначение.
Но возможно и в ГМ А=ПустоеЗначение(), так себе вариант, но так тоже можно.
7 victuan1
 
23.01.24
06:32
Даже у себя я нашел такие "выкрутасы" ;)

Функция ИнитЕГАИС()
    Перем тщи;
    
    Попытка
        Модуль = СоздатьОбъект("ВыполняемыйМодуль"); //проверка того, что 1С++ была уже загружена
    Исключение
        Если ЗагрузитьВК("1cpp.dll",,Ссылка1СПП)=0 Тогда
            Возврат 0;
        КонецЕсли;
    КонецПопытки;  
    
    Попытка
        МетаИнфо = СоздатьОбъект("MetaInfoClasses");
        Версия = МетаИнфо.ПолучитьВерсиюФайла();
    Исключение
        мсообщить("Неудачная попытка создания или использования объекта ""MetaInfoClasses"". Возможно, нужно установить более новую версию 1cpp.dll ("+Ссылка1СПП+")");
        Возврат 0
    КонецПопытки;
    
    Если Число(Версия) < 3 Тогда
        мсообщить("Установлена версия 1cpp.dll "+Версия+". Установите версию 1cpp.dll 3.х.х.х ("+Ссылка1СПП+")");
        Возврат 0
    КонецЕсли;
    
    //проверим объявлена ли глЕГАИС в осн. гл. модуле
    Попытка
        Если ПустоеЗначение(Модуль)=1 Тогда
            Модуль = СоздатьОбъект("ВыполняемыйМодуль");
        КонецЕсли;
        Модуль.УстановитьМодуль("т = глЕГАИС");
    Исключение
        мсообщить("Неудачная попытка использования объекта ""ВыполняемыйМодуль"". Возможно, нужно установить более новую версию 1cpp.dll ("+Ссылка1СПП+")");
        Возврат 0
    КонецПопытки;
    Попытка
        //Модуль.РазрешитьИсключения();
        Модуль.КомпилироватьМодуль();
        глЕГАИСобъявлена = 1;
    Исключение
        глЕГАИСобъявлена = 0;
    КонецПопытки;    
    
    ИмяКласса = "ЕГАИС.Общие";
    Если глЕГАИСобъявлена = 0 Тогда    //задействуем Формекс для объявления глобальной переменной. Если глЕГАИС объявлена в осн. гл. модуле, то Формекс не используется и не загружается
        Попытка
            Серв = СоздатьОбъект("Сервис");  //проверка того, что Формекс была уже загружена
        Исключение
            Если ЗагрузитьВК("Formex.dll",,СсылкаФормекс)=0 Тогда
                Возврат 0;
            КонецЕсли;
        КонецПопытки;
        Попытка
            Если ПустоеЗначение(Серв)=1 Тогда
                Серв = СоздатьОбъект("Сервис");
            КонецЕсли;
            Серв.ДобавитьГлобальныйМодуль("Перем глЕГАИС Экспорт;");
        Исключение
            мсообщить("Неудачная попытка создания внешнего глобального модуля. Возможно, нужно установить более новую версию formex.dll ("+СсылкаФормекс+")");
            Возврат 0
        КонецПопытки;
        
    Иначе //проверим инициализирована ли переменная
        Шаблон("[глПрисвоить(тщи,глЕГАИС)]");
        Если ТипЗначенияСтр(тщи)=ИмяКласса Тогда
            Возврат тщи
        КонецЕсли;
        
    КонецЕсли;
    
    Попытка
        Лицензия = СоздатьОбъект("КЗК2.Лицензия"); // проверка на загруженность компоненты Прекомпилятор,
    Исключение
        Если ЗагрузитьВК("precomp.dll") = 0 Тогда
            Возврат 0;
        //Иначе
        //    Лицензия = СоздатьОбъект("КЗК2.Лицензия");
        КонецЕсли;
    КонецПопытки;

    КлассЕсть = МетаИнфо.КлассСуществует(ИмяКласса);
    Если  КлассЕсть =0 Тогда

        Если ИнитСпПутей()=0 Тогда
            Возврат 0
        КонецЕсли;
        ФайлКласса = СтрЗаменить(ИмяКласса,".","_");
        Если ФС.СуществуетФайл(КаталогОбработки+ФайлКласса+".ert")=0 Тогда
            мсообщить("Не найден файл реализации класса "+КаталогОбработки+ФайлКласса+".ert"+РазделительСтрок+"Возможно, нужно перезапустить обработку ""Обмен ЕГАИС"" для переопределения каталога хранения.");
            Возврат 0
        КонецЕсли;    
        Если ФС.СуществуетФайл(КаталогОбработки+ФайлКласса+".prm")=0 Тогда
            ТФайл= СоздатьОбъект("Текст");
            ТФайл.ДобавитьСтроку("Класс "+ИмяКласса+"="+ФайлКласса+".ert{}");
            Попытка
                ТФайл.Записать(КаталогОбработки+ФайлКласса+".prm");
                ТФайл = ""; //обнуление ФС
            Исключение
                Сообщить("Ошибка при попытке записать файл "+КаталогОбработки+ФайлКласса+".prm: "+ОписаниеОшибки(), "!");
                ТФайл = ""; //обнуление ФС
                возврат 0;
            КонецПопытки;
        КонецЕсли;    
        Состояние("Инициализация класса "+ИмяКласса+" из файла "+КаталогОбработки+ФайлКласса+".ert"+"...");
        Попытка
            МетаИнфо.ЗагрузитьОписаниеКлассов(КаталогОбработки+ФайлКласса+".prm");
        Исключение
            мсообщить("Инициализация класса "+ИмяКласса+" закончилась неудачно!");
            Возврат 0
        КонецПопытки;
        Если МетаИнфо.КлассСуществует(ИмяКласса)=0 Тогда
            мсообщить("Не удалось загрузить класс "+ИмяКласса+" из файла "+КаталогОбработки+ФайлКласса+".ert");
            Возврат 0;
        КонецЕсли;
    КонецЕсли;
        
    Попытка
        тщи = СоздатьОбъект(ИмяКласса);
    Исключение
        мсообщить(ОписаниеОшибки());
        Возврат 0
    КонецПопытки;
    тщи.КаталогОбработки = КаталогОбработки;
    тщи.СпПутей = СпПутей;
    Шаблон("[глПрисвоить(глЕГАИС,тщи)]");
    тщи.Инит();

    Возврат тщи
КонецФункции
8 Волшебник
 
23.01.24
08:53
хватит разврата