Posted: Fri May 12, 2017 4:58 pm Post subject: Zmacros - генератор программ
Добрый день.
Время затраченное програмистом над решением поставленной задачи, когда он не занят всем другим, делется на 2 типа:
1) творчество
2) рутина
C творчеством все просто – каджый творит как может. Для автоматизайии рутины я написал программу которая генерирует тексты по шаблону, заменяя переменные нужными значениями.
Эту задачу можно решить макросами, но макросы просты в написании и тяжелы в редактировании особенно в отладке, они не поддаются отладке. Для того чтоб писать также легко как с макросами и в тоже время без них была написана эта программа. Потому как макросы в общем случае не приветствуются.
Я поквжу примеры кода котрые иногда необходимо написать и как это генерировать быстрее и проще.
F8 - перезапускает программу
Refresh - перечитывает шаблон создает переменные для шаблона
List сохраненные шаблоны в базе
Save - сохранить в базу
Run - подставить переменные в шаблон
Первый пример создание экрана для alv .
Нужно объявмить переменные, инициализировать экран, обработать события. Все экраны алв однотипны. Мняется в них кроме имена структуры и имена таблицы только суффиксы переменных обозначающие пренадлежность к конкретному экрану. Делать это можно разными способами:
1) каждый раз писать с нуля
2) копипастить из другой программы и подпровлять индексы
и наиболее оптимальный способ
3) воспользоваться шаблоном
что нужно сгенерировать
Code:
*----------------------------
*-- top screen 0100
, ok_code TYPE sy-ucomm
, gr_alv_0100 TYPE REF TO cl_gui_alv_grid
, gr_cont_0100 TYPE REF TO cl_gui_custom_container
, gt_fieldcat_0100 TYPE lvc_t_fcat
, gt_sort_0100 TYPE lvc_t_sort
, gs_layout_0100 TYPE lvc_s_layo
, gs_vari_0100 TYPE disvariant
*----------------------------
*screen logic
PROCESS BEFORE OUTPUT.
MODULE STATUS_0100.
*
PROCESS AFTER INPUT.
MODULE USER_COMMAND_0100.
*----------------------------
*modules
MODULE status_0100 OUTPUT.
SET PF-STATUS 'STATUS0100'.
SET TITLEBAR 'TITLEBAR0100'.
IF gr_alv_0100 IS NOT BOUND.
CREATE OBJECT gr_cont_0100
EXPORTING
container_name = 'CONT_0100'.
CASE ok_code .
WHEN 'BACK'.
SET SCREEN 0.
* when 'XXXXXXX'.
ENDCASE.
clear ok_code.
ENDMODULE.
вот шаблон
Code:
*----------------------------
*-- top screen {screen_number}
, ok_code TYPE sy-ucomm
, gr_alv_{screen_number} TYPE REF TO cl_gui_alv_grid
, gr_cont_{screen_number} TYPE REF TO cl_gui_custom_container
, gt_fieldcat_{screen_number} TYPE lvc_t_fcat
, gt_sort_{screen_number} TYPE lvc_t_sort
, gs_layout_{screen_number} TYPE lvc_s_layo
, gs_vari_{screen_number} TYPE disvariant
*----------------------------
*screen logic
PROCESS BEFORE OUTPUT.
MODULE STATUS_{screen_number}.
*
PROCESS AFTER INPUT.
MODULE USER_COMMAND_{screen_number}.
*----------------------------
*modules
MODULE status_{screen_number} OUTPUT.
SET PF-STATUS 'STATUS{screen_number}'.
SET TITLEBAR 'TITLEBAR{screen_number}'.
IF gr_alv_{screen_number} IS NOT BOUND.
CREATE OBJECT gr_cont_{screen_number}
EXPORTING
container_name = 'CONT_{screen_number}'.
CASE ok_code .
WHEN 'BACK'.
SET SCREEN 0.
* when 'XXXXXXX'.
ENDCASE.
clear ok_code.
ENDMODULE.
По нажатию кнопки обновить програма выбирает из шаблона все переменные автоматически. Количество переменных в шаблоне ограничено только здравым смыслом. Простые пременные в шаблоне берутся в фигурные скобки{} например {screen_number}
второй пример – объявление типов внутри программы
что желаем получить
Code:
TYPES:
BEGIN OF t_data_row,
LINE TYPE CIFCOUNT,
T_TYPE TYPE CLASSTTYPE,
TABNAME TYPE TABNAME,
JJOIN TYPE TABNAME,
LEFT1 TYPE TABNAME,
RIGHT1 TYPE TABNAME,
LV_KEY_SELECT TYPE TABNAME,
LEFT_61 TYPE ECP_FIELDNAME,
RIGHT_61 TYPE ECP_FIELDNAME,
LV_KEY_JOIN TYPE ECP_FIELDNAME,
SORTORDER TYPE ANZST,
CRITERIAFOR TYPE ADDIFCTCOD,
DISABLE TYPE CLASSTTYPE,
OR1 TYPE AKB_NOTE,
OR2 TYPE AKB_NOTE,
OR3 TYPE AKB_NOTE,
OR4 TYPE AKB_NOTE,
END OF t_data_row .
шаблон
Code:
TYPES:
BEGIN OF t_{type},
$1-1 TYPE $1-2,
END OF t_{type} .
Можно скопировать из словаря имена полей и типов, потом руками расставлять запятые, ключевое слово type или воспользоваться шаблоном.
Переменные которые имеют по несколько значений в строке и имеют несколько строк в шаблоне обозначаются $3-2 .
$ говорит программе что здесь будет переменная, следующая цифра говорит номер переменной, следующая цифра говорит номер столбца.
Количество столбцов ограничено здравым смыслом. Количество сложных переменным ограничено только максимальным количеством генерацций для программы, в моем случае это было 18. Шаблон с 18-ю табличными переменными использующийся в реальной программе я придумать не смог, так что тут все ок.
Если увидите сообщение "Generation Limi Reached", нужно сохранить шаблон если не сохранен и перезапустить программу.
Шаблоны можно хранить в файлах и копипастить, можно загружать и выгружать в файлы,
правильный вариант хранить в базе. Если нужные таблицы не созданы то появится подсказка какие таблицы с какими полями типами и ключами нужно создать.
подобные по уровню сложности примеры
перенос значения из старой в новую структуру
LOOP AT mt_alv_fieldcat INTO ls_alv_fieldcat WHERE tech EQ space
AND no_out EQ space.
CASE ls_alv_fieldcat-fieldname.
WHEN 'A38'.
lv_string = ls_totals-a38.
set_shift.
WHEN 'A39'.
lv_string = ls_totals-a39.
set_shift.
WHEN 'A40'.
lv_string = ls_totals-a40.
set_shift.
WHEN 'A41'.
lv_string = ls_totals-a41.
set_shift.
WHEN 'A42'.
lv_string = ls_totals-a42.
set_shift.
WHEN 'A43'.
lv_string = ls_totals-a43.
set_shift.
WHEN 'A44'.
lv_string = ls_totals-a44.
set_shift.
WHEN 'A45'.
lv_string = ls_totals-a45.
set_shift.
ENDCASE.
ADD ls_alv_fieldcat-outputlen TO lv_len.
ADD 1 TO lv_len.
ENDLOOP.
шаблон
Code:
LOOP AT mt_alv_fieldcat INTO ls_alv_fieldcat WHERE tech EQ space
AND no_out EQ space.
CASE ls_alv_fieldcat-fieldname.
>1
WHEN 'A$1-1'.
lv_string = ls_totals-a$1-1.
set_shift.
<1
ENDCASE.
ADD ls_alv_fieldcat-outputlen TO lv_len.
ADD 1 TO lv_len.
ENDLOOP.
До этого мы рассмотрели шаблоны нулевой и первой размерности. Перейдем к второй и высшей, все остальные примерно как второй.
Вот таким шаблоном можно посторить набор всех возможных комбинаций значений.
что желаем получить
Code:
0 X A
0 X B
0 X C
0 _ A
0 _ B
0 _ C
1 X A
1 X B
1 X C
1 _ A
1 _ B
1 _ C
шаблон
Code:
$1-1 $2-1 $3-1
Допустим вы пишете тесты для своего кода. Генерация тестов утомительная процедура, с шаблонами все просто.
Вот таким шаблоном можно сгенерировать тесты для проверки нескольких логических функций на всех возможных наборах значений.
что желаем получить
Code:
perform logic_or using 'X' 'X' 'X' changing lv_result.
write :/ ' or on v1=X v2=X v3=X ' , lv_result .
perform logic_or using 'X' 'X' '' changing lv_result.
write :/ ' or on v1=X v2=X v3= ' , lv_result .
perform logic_or using 'X' '' 'X' changing lv_result.
write :/ ' or on v1=X v2= v3=X ' , lv_result .
perform logic_or using 'X' '' '' changing lv_result.
write :/ ' or on v1=X v2= v3= ' , lv_result .
perform logic_or using '' 'X' 'X' changing lv_result.
write :/ ' or on v1= v2=X v3=X ' , lv_result .
perform logic_or using '' 'X' '' changing lv_result.
write :/ ' or on v1= v2=X v3= ' , lv_result .
perform logic_or using '' '' 'X' changing lv_result.
write :/ ' or on v1= v2= v3=X ' , lv_result .
perform logic_or using '' '' '' changing lv_result.
write :/ ' or on v1= v2= v3= ' , lv_result .
perform logic_and using 'X' 'X' 'X' changing lv_result.
write :/ ' and on v1=X v2=X v3=X ' , lv_result .
perform logic_and using 'X' 'X' '' changing lv_result.
write :/ ' and on v1=X v2=X v3= ' , lv_result .
perform logic_and using 'X' '' 'X' changing lv_result.
write :/ ' and on v1=X v2= v3=X ' , lv_result .
perform logic_and using 'X' '' '' changing lv_result.
write :/ ' and on v1=X v2= v3= ' , lv_result .
perform logic_and using '' 'X' 'X' changing lv_result.
write :/ ' and on v1= v2=X v3=X ' , lv_result .
perform logic_and using '' 'X' '' changing lv_result.
write :/ ' and on v1= v2=X v3= ' , lv_result .
perform logic_and using '' '' 'X' changing lv_result.
write :/ ' and on v1= v2= v3=X ' , lv_result .
perform logic_and using '' '' '' changing lv_result.
write :/ ' and on v1= v2= v3= ' , lv_result .
perform logic_xor using 'X' 'X' 'X' changing lv_result.
write :/ ' xor on v1=X v2=X v3=X ' , lv_result .
perform logic_xor using 'X' 'X' '' changing lv_result.
write :/ ' xor on v1=X v2=X v3= ' , lv_result .
perform logic_xor using 'X' '' 'X' changing lv_result.
write :/ ' xor on v1=X v2= v3=X ' , lv_result .
perform logic_xor using 'X' '' '' changing lv_result.
write :/ ' xor on v1=X v2= v3= ' , lv_result .
perform logic_xor using '' 'X' 'X' changing lv_result.
write :/ ' xor on v1= v2=X v3=X ' , lv_result .
perform logic_xor using '' 'X' '' changing lv_result.
write :/ ' xor on v1= v2=X v3= ' , lv_result .
perform logic_xor using '' '' 'X' changing lv_result.
write :/ ' xor on v1= v2= v3=X ' , lv_result .
perform logic_xor using '' '' '' changing lv_result.
write :/ ' xor on v1= v2= v3= ' , lv_result .
perform logic_magic using 'X' 'X' 'X' changing lv_result.
write :/ ' magic on v1=X v2=X v3=X ' , lv_result .
perform logic_magic using 'X' 'X' '' changing lv_result.
write :/ ' magic on v1=X v2=X v3= ' , lv_result .
perform logic_magic using 'X' '' 'X' changing lv_result.
write :/ ' magic on v1=X v2= v3=X ' , lv_result .
perform logic_magic using 'X' '' '' changing lv_result.
write :/ ' magic on v1=X v2= v3= ' , lv_result .
perform logic_magic using '' 'X' 'X' changing lv_result.
write :/ ' magic on v1= v2=X v3=X ' , lv_result .
perform logic_magic using '' 'X' '' changing lv_result.
write :/ ' magic on v1= v2=X v3= ' , lv_result .
perform logic_magic using '' '' 'X' changing lv_result.
write :/ ' magic on v1= v2= v3=X ' , lv_result .
perform logic_magic using '' '' '' changing lv_result.
write :/ ' magic on v1= v2= v3= ' , lv_result .
Строки размножаются согласно порядка встречаемости переменных в коде. Если нужно изменить порядок обхода переменных или включить несколько строк в шаблон то нужно использовать открывающие и закрывающие теги.
>1 - открывающий тег для первой переменной
<1 – закрывающий тег для первой переменной
программа автоматически проверяет что все открытые теги закрыты, и то что теги закрыты в правильном порядке. Поддерживается прицип LIFO Last In First Out. Если вы знакомы с тегами HTML, то все как у них.
Для автоматической генерации целочисленных переменных можно исрользовать следующий шаблон $1-5 сгенерирует 5 строк с цифрами от 1 до 5.
Шаблон $01-15 сгенерирует строки с цифрами от 01 до 15 с ведущими нулями.
_15-3 сгенерирует 3 строки с цифрами от 15 до 17
Собственно все.
P.S.
В качестве бонуса спомощью этой программы можно выстрелить себе в ногу, достаточно указать в качестве значения переменных значения которые можно интерпритировать как переменные.
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
All product names are trademarks of their respective companies. SAPNET.RU websites are in no way affiliated with SAP AG. SAP, SAP R/3, R/3 software, mySAP, ABAP, BAPI, xApps, SAP NetWeaver and any other are registered trademarks of SAP AG. Every effort is made to ensure content integrity. Use information on this site at your own risk.