SAP BI
Thoughts and ideas.
четверг, 28 апреля 2022 г.
четверг, 26 августа 2021 г.
Когда надо что-то сделать с запросом загрузки (удалить, активировать), который уже архивирован, а файла с архивом нет
Например у вас древнющая DSO, и что-то, типа, такой ошибки:
ARCHIVE_READ_OBJECT: Sy-Subrc:: 4
Запускаем программу RSREQARCH_FAKE_MONITORENTRIES, указываем нужный RECU ID, который на REQU_* называется, и по имени программу догадываемся, что она сделает :)
понедельник, 27 января 2020 г.
Отключение элементов управления в GUI-статусе ABAP-экранов
set pf-status '1001_STATUS' excluding 'SAVE'.
воскресенье, 29 декабря 2019 г.
Сравнение изменённых записей, внесённых через ракурс ведения таблицы, с записями в БД
Ок, с тем, как отловить момент сохранения записей в таблице разобрались.
Теперь парни хотят каким-то образом отловить к те записи, которые были добавлены\изменены пользователем до момента сохранения в БД (и такой кейс имеет место быть).
Берём гугл (ох, есть у меня знакомый коллега, который ужасно любит сарказмы про поиск в гугле), вытаскиваем из него немного абапа для нашего кода обработки события (см. верхнюю ссылку), и получаем что-то вроде этого:
DATA:
wa_lines TYPE zpsb_bwa_obj,
lt_tab TYPE STANDARD TABLE OF zpsb_bwa_obj,
lt_tab_mod LIKE lt_tab,
lv_string_db TYPE string,
lv_string_it TYPE string.
FIELD-SYMBOLS:
<fs_tab> LIKE LINE OF lt_tab.
BREAK-POINT.
SELECT
*
FROM zpsb_bwa_obj
INTO CORRESPONDING FIELDS OF TABLE lt_tab.
LOOP AT total.
CLEAR wa_lines.
IF <vim_total_struc> IS ASSIGNED.
MOVE-CORRESPONDING <vim_total_struc> TO wa_lines.
APPEND wa_lines TO lt_tab_mod.
ENDIF.
** IF <action> IS NOT INITIAL AND add CHECKS here .
**
** IF wa_lines-<field 1> ne '<VALUE>'.
** MESSAGE 'XX' TYPE 'S' DISPLAY LIKE 'E'.
** vim_abort_saving = 'X'.
** EXIT.
**
** ELSEIF wa_lines-<field 2> ne '<VALUE>'
**
** message 'XX' type 'S' display like 'E'.
**
** vim_abort_saving = 'X'.
**
** EXIT.
**
** ENDIF.
** ENDIF.
ENDLOOP.
SORT: lt_tab_mod, lt_tab.
LOOP AT lt_tab ASSIGNING <fs_tab>.
READ TABLE lt_tab_mod INTO wa_lines
WITH KEY dso_name = <fs_tab>-dso_name.
IF sy-subrc NE 0.
CONTINUE.
ENDIF.
lv_string_db = <fs_tab>.
lv_string_it = wa_lines.
IF lv_string_db NE lv_string_it.
CONCATENATE `Строка различается: ` lv_string_it INTO lv_string_it.
MESSAGE lv_string_it TYPE 'I'.
ENDIF.
ENDLOOP.
п.с.: Не забыть бы переписать код, чтобы в динамике определять имя и структуру таблиц.
п.п.с: Для обновления полей - 01 и 05. Тут гайд.
FORM _new.
GET TIME STAMP FIELD zdbtab-timestamp.
zdbtab-chng_user = sy-uname.
ENDFORM.
FORM _update.
FIELD-SYMBOLS: <fs_field> TYPE any.
LOOP AT total.
CHECK <action> EQ aendern.
ASSIGN COMPONENT 'TIMESTAMP' OF STRUCTURE <vim_total_struc> TO <fs_field>.
IF sy-subrc EQ 0.
GET TIME STAMP FIELD <fs_field>.
ENDIF.
ASSIGN COMPONENT 'CHNG_USER' OF STRUCTURE <vim_total_struc> TO <fs_field>.
IF sy-subrc EQ 0.
<fs_field> = sy-uname.
ENDIF.
READ TABLE extract WITH KEY <vim_xtotal_key>.
IF sy-subrc EQ 0.
extract = total.
MODIFY extract INDEX sy-tabix.
ENDIF.
IF total IS NOT INITIAL.
MODIFY total.
ENDIF.
ENDLOOP.
ENDFORM.
Теперь парни хотят каким-то образом отловить к те записи, которые были добавлены\изменены пользователем до момента сохранения в БД (и такой кейс имеет место быть).
Берём гугл (ох, есть у меня знакомый коллега, который ужасно любит сарказмы про поиск в гугле), вытаскиваем из него немного абапа для нашего кода обработки события (см. верхнюю ссылку), и получаем что-то вроде этого:
DATA:
wa_lines TYPE zpsb_bwa_obj,
lt_tab TYPE STANDARD TABLE OF zpsb_bwa_obj,
lt_tab_mod LIKE lt_tab,
lv_string_db TYPE string,
lv_string_it TYPE string.
FIELD-SYMBOLS:
<fs_tab> LIKE LINE OF lt_tab.
BREAK-POINT.
SELECT
*
FROM zpsb_bwa_obj
INTO CORRESPONDING FIELDS OF TABLE lt_tab.
LOOP AT total.
CLEAR wa_lines.
IF <vim_total_struc> IS ASSIGNED.
MOVE-CORRESPONDING <vim_total_struc> TO wa_lines.
APPEND wa_lines TO lt_tab_mod.
ENDIF.
** IF <action> IS NOT INITIAL AND add CHECKS here .
**
** IF wa_lines-<field 1> ne '<VALUE>'.
** MESSAGE 'XX' TYPE 'S' DISPLAY LIKE 'E'.
** vim_abort_saving = 'X'.
** EXIT.
**
** ELSEIF wa_lines-<field 2> ne '<VALUE>'
**
** message 'XX' type 'S' display like 'E'.
**
** vim_abort_saving = 'X'.
**
** EXIT.
**
** ENDIF.
** ENDIF.
ENDLOOP.
SORT: lt_tab_mod, lt_tab.
LOOP AT lt_tab ASSIGNING <fs_tab>.
READ TABLE lt_tab_mod INTO wa_lines
WITH KEY dso_name = <fs_tab>-dso_name.
IF sy-subrc NE 0.
CONTINUE.
ENDIF.
lv_string_db = <fs_tab>.
lv_string_it = wa_lines.
IF lv_string_db NE lv_string_it.
CONCATENATE `Строка различается: ` lv_string_it INTO lv_string_it.
MESSAGE lv_string_it TYPE 'I'.
ENDIF.
ENDLOOP.
п.с.: Не забыть бы переписать код, чтобы в динамике определять имя и структуру таблиц.
п.п.с: Для обновления полей - 01 и 05. Тут гайд.
FORM _new.
GET TIME STAMP FIELD zdbtab-timestamp.
zdbtab-chng_user = sy-uname.
ENDFORM.
FORM _update.
FIELD-SYMBOLS: <fs_field> TYPE any.
LOOP AT total.
CHECK <action> EQ aendern.
ASSIGN COMPONENT 'TIMESTAMP' OF STRUCTURE <vim_total_struc> TO <fs_field>.
IF sy-subrc EQ 0.
GET TIME STAMP FIELD <fs_field>.
ENDIF.
ASSIGN COMPONENT 'CHNG_USER' OF STRUCTURE <vim_total_struc> TO <fs_field>.
IF sy-subrc EQ 0.
<fs_field> = sy-uname.
ENDIF.
READ TABLE extract WITH KEY <vim_xtotal_key>.
IF sy-subrc EQ 0.
extract = total.
MODIFY extract INDEX sy-tabix.
ENDIF.
IF total IS NOT INITIAL.
MODIFY total.
ENDIF.
ENDLOOP.
ENDFORM.
пятница, 13 декабря 2019 г.
7.5 Когда вам нужно передать значения выборочных столбцов из одной таблицы в другую
Да, если вам повезло работать с 7.5 и выше. Есть мега-шаманский класс, который облегчит задачу.
Вообще, он умеет разными способами столбцы передавать, почитайте справку о нём.
cl_abap_corresponding=>create(
source = result_package
destination = lt_value_tab
mapping = VALUE cl_abap_corresponding=>mapping_table(
( level = 0
kind = 1
srcname = lv_name
dstname = 'FIELD' )
)
)->execute( EXPORTING source = result_package
CHANGING destination = lt_value_tab ).
Вообще, он умеет разными способами столбцы передавать, почитайте справку о нём.
cl_abap_corresponding=>create(
source = result_package
destination = lt_value_tab
mapping = VALUE cl_abap_corresponding=>mapping_table(
( level = 0
kind = 1
srcname = lv_name
dstname = 'FIELD' )
)
)->execute( EXPORTING source = result_package
CHANGING destination = lt_value_tab ).
вторник, 19 ноября 2019 г.
Вызов события по добавлению/изменению записей в таблице
Интересная настройка - при создании ракурса ведения для таблиц, можно привязать выполнение любый действий (ибо АБАП) к основным операциям с данными в этой таблице.
Генератор ведения таблиц (se54)-Среда-Модификация-События. но перед этим ставишь точку прерывания в ***INCLUDE MSVIMF30 .на строке 39, и подменяешь значение SY-SUBRC на 0, если нет прав на ведение:
Главное правильно описать логику в форме, которую нужно создать с указанным именем в нужно инклюде.
FORM save_record.
CALL FUNCTION 'TH_POPUP'
EXPORTING
client = sy-MANDT
user = sy-uname
MESSAGE = 'Внести изменения в таблицу'
* MESSAGE_LEN = 0
* CUT_BLANKS = ' '
* EXCEPTIONS
* USER_NOT_FOUND = 1
* OTHERS = 2
.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
ENDFORM. "SAVE_RECORD
Генератор ведения таблиц (se54)-Среда-Модификация-События. но перед этим ставишь точку прерывания в ***INCLUDE MSVIMF30 .на строке 39, и подменяешь значение SY-SUBRC на 0, если нет прав на ведение:
Главное правильно описать логику в форме, которую нужно создать с указанным именем в нужно инклюде.
FORM save_record.
CALL FUNCTION 'TH_POPUP'
EXPORTING
client = sy-MANDT
user = sy-uname
MESSAGE = 'Внести изменения в таблицу'
* MESSAGE_LEN = 0
* CUT_BLANKS = ' '
* EXCEPTIONS
* USER_NOT_FOUND = 1
* OTHERS = 2
.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
ENDFORM. "SAVE_RECORD
вторник, 12 ноября 2019 г.
Управление цепочкой загрузки из АБАПа, продолжение
Ок, парни, в прошлой серии мы с вами пытались управлять цепочкой загрузки через перепланирование следующего запуска. Справедливо было замечено, что если мы делаем это шаманство из текущего прогона, он зависает или прерывается, так как CALL FUNCTION 'RSPC_API_CHAIN_SCHEDULE'.
Ниже код, который находит задание, шаманит с его временем следующего запуска, и ни разу не мешает текущему прогону:
DATA:
lt_processlist TYPE STANDARD TABLE OF rspc_s_processlist,
wa_processlist LIKE LINE OF lt_processlist,
lv_variant TYPE rspc_variant,
wa_jobhead LIKE tbtcjob,
it_steplist TYPE STANDARD TABLE OF tbtcstep,
lt_joblist TYPE STANDARD TABLE OF tbtcjob,
text TYPE string.
BREAK-POINT.
*" Имя варианта процесса запуска
CALL FUNCTION 'RSPC_API_CHAIN_GET_PROCESSES'
EXPORTING
i_chain = 'USEM_CR_RETAIL'
TABLES
e_t_processlist = lt_processlist.
IF sy-subrc <> 0.
text = `Сбой при поиске варианта запуска по цепочке`.
MESSAGE text TYPE 'E'.
ENDIF.
READ TABLE lt_processlist INTO wa_processlist
WITH KEY chain_id = 'USEM_CR_RETAIL'
type = 'TRIGGER'.
lv_variant = wa_processlist-variante.
*" Параметры следующего задания по нашей цепочке
CALL FUNCTION 'RSPC_API_PROCESS_GET_JOBS'
EXPORTING
i_chain = 'USEM_CR_RETAIL'
i_type = 'TRIGGER' "тип процесса запуска в цепочке
i_variant = lv_variant
i_event = '' "можно не заполнять
i_eventp = '' "можно не заполнять
TABLES
e_t_joblist = lt_joblist.
IF sy-subrc <> 0.
text = `Сбой при поиске запланированного задания по цепочке`.
MESSAGE text TYPE 'E'.
ENDIF.
IF lt_joblist IS INITIAL.
text = `Сбой при поиске запланированного задания по цепочке`.
MESSAGE text TYPE 'E'.
ENDIF.
READ TABLE lt_joblist INDEX 1 INTO wa_jobhead.
*" Теперь джобу надо считать
CALL FUNCTION 'BP_JOB_READ'
EXPORTING
job_read_jobcount = wa_jobhead-jobcount
job_read_jobname = wa_jobhead-jobname
job_read_opcode = '20'
IMPORTING
job_read_jobhead = wa_jobhead
TABLES
job_read_steplist = it_steplist
EXCEPTIONS
invalid_opcode = 1
job_doesnt_exist = 2
job_doesnt_have_steps = 3
OTHERS = 4.
IF sy-subrc <> 0.
text = `Сбой при считывании запланированного задания`.
MESSAGE text TYPE 'E'.
ENDIF.
wa_jobhead-sdlstrtdt = wa_jobhead-sdlstrtdt + 1.
wa_jobhead-sdlstrttm = '050000'.
*" Изменить
CALL FUNCTION 'BP_JOB_MODIFY'
EXPORTING
dialog = 'N'
jobcount = wa_jobhead-jobcount
jobname = wa_jobhead-jobname
new_jobhead = wa_jobhead
opcode = '16'
IMPORTING
modified_jobhead = wa_jobhead
TABLES
new_steplist = it_steplist.
IF sy-subrc <> 0.
text = `Сбой при изменении запланированного задания`.
MESSAGE text TYPE 'E'.
ENDIF.
*" И закрыть назад
CALL FUNCTION 'JOB_CLOSE'
EXPORTING
jobcount = wa_jobhead-jobcount
jobname = wa_jobhead-jobname.
IF sy-subrc <> 0.
text = `Сбой при закрытии джобы`.
MESSAGE text TYPE 'E'.
ENDIF.
Ниже код, который находит задание, шаманит с его временем следующего запуска, и ни разу не мешает текущему прогону:
DATA:
lt_processlist TYPE STANDARD TABLE OF rspc_s_processlist,
wa_processlist LIKE LINE OF lt_processlist,
lv_variant TYPE rspc_variant,
wa_jobhead LIKE tbtcjob,
it_steplist TYPE STANDARD TABLE OF tbtcstep,
lt_joblist TYPE STANDARD TABLE OF tbtcjob,
text TYPE string.
BREAK-POINT.
*" Имя варианта процесса запуска
CALL FUNCTION 'RSPC_API_CHAIN_GET_PROCESSES'
EXPORTING
i_chain = 'USEM_CR_RETAIL'
TABLES
e_t_processlist = lt_processlist.
IF sy-subrc <> 0.
text = `Сбой при поиске варианта запуска по цепочке`.
MESSAGE text TYPE 'E'.
ENDIF.
READ TABLE lt_processlist INTO wa_processlist
WITH KEY chain_id = 'USEM_CR_RETAIL'
type = 'TRIGGER'.
lv_variant = wa_processlist-variante.
*" Параметры следующего задания по нашей цепочке
CALL FUNCTION 'RSPC_API_PROCESS_GET_JOBS'
EXPORTING
i_chain = 'USEM_CR_RETAIL'
i_type = 'TRIGGER' "тип процесса запуска в цепочке
i_variant = lv_variant
i_event = '' "можно не заполнять
i_eventp = '' "можно не заполнять
TABLES
e_t_joblist = lt_joblist.
IF sy-subrc <> 0.
text = `Сбой при поиске запланированного задания по цепочке`.
MESSAGE text TYPE 'E'.
ENDIF.
IF lt_joblist IS INITIAL.
text = `Сбой при поиске запланированного задания по цепочке`.
MESSAGE text TYPE 'E'.
ENDIF.
READ TABLE lt_joblist INDEX 1 INTO wa_jobhead.
*" Теперь джобу надо считать
CALL FUNCTION 'BP_JOB_READ'
EXPORTING
job_read_jobcount = wa_jobhead-jobcount
job_read_jobname = wa_jobhead-jobname
job_read_opcode = '20'
IMPORTING
job_read_jobhead = wa_jobhead
TABLES
job_read_steplist = it_steplist
EXCEPTIONS
invalid_opcode = 1
job_doesnt_exist = 2
job_doesnt_have_steps = 3
OTHERS = 4.
IF sy-subrc <> 0.
text = `Сбой при считывании запланированного задания`.
MESSAGE text TYPE 'E'.
ENDIF.
wa_jobhead-sdlstrtdt = wa_jobhead-sdlstrtdt + 1.
wa_jobhead-sdlstrttm = '050000'.
*" Изменить
CALL FUNCTION 'BP_JOB_MODIFY'
EXPORTING
dialog = 'N'
jobcount = wa_jobhead-jobcount
jobname = wa_jobhead-jobname
new_jobhead = wa_jobhead
opcode = '16'
IMPORTING
modified_jobhead = wa_jobhead
TABLES
new_steplist = it_steplist.
IF sy-subrc <> 0.
text = `Сбой при изменении запланированного задания`.
MESSAGE text TYPE 'E'.
ENDIF.
*" И закрыть назад
CALL FUNCTION 'JOB_CLOSE'
EXPORTING
jobcount = wa_jobhead-jobcount
jobname = wa_jobhead-jobname.
IF sy-subrc <> 0.
text = `Сбой при закрытии джобы`.
MESSAGE text TYPE 'E'.
ENDIF.
Подписаться на:
Сообщения (Atom)