Skip processing of a logical database? - abap

In case a user sets a parameter to skip the processing of the logical database it should be skipped. But unfortunately, I can't find a way, since whatever I try the reports ends completly. Example of what I tried:
REPORT zxxxx.
TABLES: pernr.
NODES peras.
PARAMETERS: p_skip AS CHECKBOX.
START-OF-SELECTION.
IF p_skip = abap_true.
RETURN. " Also tried EXIT.
ENDIF.
GET peras.
WRITE 'ABC'.
end-of-selection.
WRITE 'test'.
My expectation was that the Report jumps directly to "END-OF-SELECTION", but it doesn't.
What statement do I need to use here? Or is there a workaround? (Otherwise I have to write the logic for the LDB myself)

The STOP statement has to be used, if you want to jump directly to END-OF-SELECTION.
IF p_skip = abap_true.
STOP.
ENDIF.
https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abapstop.htm
It might be worth mentioning that logical databases are already obsolete.

Related

Side by side structure values comparison?

How to compare structure values component-wise and display the differences?
Now I do it in a very primitive way:
DATA: tkomp TYPE komp,
tkomp2 TYPE komp.
WRITE: `Field differences: `.
DO 500 TIMES.
ASSIGN COMPONENT sy-index OF STRUCTURE tkomp TO FIELD-SYMBOL(<fld>).
IF sy-subrc = 0.
CHECK <fld> IS NOT INITIAL AND CONV string( <fld> ) CN ' 0,.'.
ENDIF.
ASSIGN COMPONENT sy-index OF STRUCTURE tkomp2 TO FIELD-SYMBOL(<fld2>).
IF sy-subrc <> 0.
EXIT.
ENDIF.
IF <fld> <> <fld2>.
WRITE: / `Component ` && sy-index && ` differs: ` && <fld>.
ENDIF.
ENDDO.
Maybe there is more beautiful way? Maybe there is something like CL_ABAP_CORRESPONDING or something newer?
I found oldie threads, where they say The Debugger uses the class CL_TPDA_TOOL_DIFF for analyzing differences, hence is my follow-ip question: is it something that we can achieve in debugger?
I've never seen an applet in ABAP debugger that allows comparing structures against each other.
Your solution is actually quite okay. You might want to add CL_ABAP_STRUCTDESCR to get the names of the components for nicer output. It would also enable you to compare and analyze the types of the component's fields as well.
Unfortunately, there is no reusable class, function, or built-in method for that.
You will find the most precise comparison implementation in the class CL_ABAP_UNIT_ASSERT, method ASSERT_EQUALS. More precisely, the local class DATA_DIFF, method DIFF_STRUCTS, shows how to compare structures in a type- and nesting-tolerant way.
I can't speak for the class CL_TPDA_TOOL_DIFF. I've heard it mentioned before but we actually do not even have it in our SAP NW 7.52 systems.
I have also never seen a debugger view or plugin that would compare structures and display the differences. No idea where that comment comes from.
There are code snippets at below, you can pass the structure in cl_abap_typedescr=>describe_by_data.
DATA: lo_struct TYPE REF TO cl_abap_structdescr,
        lt_comp   TYPE abap_component_tab,
        ls_comp   TYPE abap_componentdescr.
 CLEAR lo_struct.
  lo_struct ?= cl_abap_typedescr=>describe_by_data( p_data = lt_list_sum  ).
  REFRESH lt_comp.
  lt_comp = lo_struct->get_components( ).
  MOVE-CORRESPONDING gt_mov_grp TO gt_mov_grp_std.
  LOOP AT lt_comp INTO ls_comp.
    CLEAR lv_numeric.
    IF ls_comp-name(4) EQ cx_move.
      lv_numeric = ls_comp-name+5(2).
      READ TABLE gt_mov_grp_std REFERENCE INTO lr_mov_grp WITH KEY report_order = lv_numeric.
      IF sy-subrc EQ 0 AND
         lr_mov_grp IS BOUND.
        APPEND INITIAL LINE TO et_data REFERENCE INTO DATA(lr_data).
        MOVE-CORRESPONDING lr_mov_grp->* TO lr_data->*.
        IF <fs> IS ASSIGNED.
          UNASSIGN <fs>.
        ENDIF.
        ASSIGN COMPONENT ls_comp-name OF STRUCTURE lt_list_sum TO <fs>.
        IF sy-subrc EQ 0 AND
           <fs> IS ASSIGNED.
          lr_data->amount = <fs>.
        ENDIF.
        IF <fs> IS ASSIGNED.
          UNASSIGN <fs>.
        ENDIF.
        ASSIGN COMPONENT cx_currency OF STRUCTURE lt_list_sum TO <fs>.
        IF sy-subrc EQ 0 AND
           <fs> IS ASSIGNED.
          lr_data->currency = <fs>.
        ENDIF.
        lr_data->datum = iv_datum.
        lr_data->werks = iv_werks.
        lr_data->kunnr = iv_kunnr.
      ENDIF.
    ENDIF.
  ENDLOOP.

Why does nested LOOP AT SCREEN cause infinite loop/recursion?

Here is one for you. Although such a language construction does not make much sense I would like to know why the nested LOOP AT SCREEN cause infinite loop (recursion?).
Let us take the following simple program.
REPORT yyy.
PARAMETERS:
p_x1 TYPE abap_bool.
AT SELECTION-SCREEN OUTPUT.
LOOP AT SCREEN.
BREAK-POINT.
ENDLOOP.
The BREAK-POINT statement will be executed only 4 times. This leads to an assumption that such a nested loop would run 16 times. Instead the below mentioned program runs forever and ends with a timeout exception.
REPORT yyy.
PARAMETERS:
p_x1 TYPE abap_bool.
AT SELECTION-SCREEN OUTPUT.
LOOP AT SCREEN.
LOOP AT SCREEN.
ASSERT 1 = 1.
ENDLOOP.
ENDLOOP.
It looks like nesting LOOP AT SCREEN causes either an infinite loop or some kind of an infinite recursion.
Why is it so? Is it documented somewhere? The extended check does not report anything regarding the loop. The same applies to Code Inspector as well.
EDIT
I have also checked whether this is a general problem for internal tables with a header line. It seems not.
REPORT YYY.
DATA: gt_t000 TYPE t000 OCCURS 10 WITH HEADER LINE.
START-OF-SELECTION.
SELECT * FROM t000
INTO TABLE gt_t000[].
LOOP AT gt_t000.
LOOP AT gt_t000.
WRITE / gt_t000-mandt.
ENDLOOP.
ENDLOOP.

SSIS Logging of OnVariableValueChanged with variable value

I am trying to log all changes in variable values in a SSIS generated with BIML.
I managed to create an event handler that writes everytime a variable changes its value.
When I log I use a parameter whose value I set to "System.VariableValue". I pass this parameter (togheter with variableName and PackageName) to a StoredProc and i write in a log table.
My problem is that often (but NOT always) it seems the parameter does not has any value. I see a new line in the DB Log table so this means the evnt is correctly raised and handled BUT it seems the parameter is empty.
The strangest thing is that sometimes values are logged correctly but not always, not for the same variables, not for the same packages, rather, in a quite random fashion.
Could it be a problem the fact that several variables could change value almost at the same time (some contention on the DB) ? I doubt it, because the row itself gets written on the DB. I even tried to write, as a value, something like 'New value = ' + ? that is, appending the parameter value to a fixed string. The fixed part gets written correctly but.. no value.
The name of the variable that changed value is always written correctly.
Any idea what this could be due to?
As a workaround I tried to use the ready-made logging facility of SSIS but in this case in the message column of the SYSSSISLOG table i can just read the name of the variable that changed, not its new value.
thankx
You could use Event Handler to do that. Go to the Variables page, go to Variable Grid Options, check Raise event when variable value changes, and there should be one more option appear for those variables, which is Raise Change Event, default to False, change to True for those variables that you need to track the changes (log). And put a logging task into Event handler
UPDATE
the new line could be the value of parameter has been reset, and that value, most likely equal to blank or whitespace, but still, that is recognized as value change.
if you are not very sure when that happened, you could set a Breakpoint to certain task and add watch window to see how the value change or whether the value will hit blank in the middle of your process

Generation of ABAP report in runtime possible?

Is there any Function module that can generate ABAP code.
For eg: FM takes tables name and join conditions as input and generate ABAP code corresponding to that.
Thanks
You should consider using SAPQuery. SAP documentation here: https://help.sap.com/saphelp_erp60_sp/helpdata/en/d2/cb3efb455611d189710000e8322d00/content.htm
1. Generic reports are possible.
Your problem is, that You will have to draw a strict frame of what is
generic and what not, this means, some stuff MUST be that generic, that
it will deal with WHATEVER You want to do before ( mostly the selection ) ,
during ( mostly manipulation ---> I would offer a badi for that ), and output.
This means, that there is at least the output-step, which can be valid for ALL
data resulting from the steps before.
Consider a generic ALV-table_output, there are a lot of examples in the repo.
If You want to be the stuff printed out simple as list, this might include
more work, like, how big is the structure, when Dou You wrap a line, and so on, consider using a flag which allows to toggle the type of output .
2. Generic reports are a transportable object.
This refers to point one. Define clear stages and limits. What does the report do, and what is it not able to do. Because, even if it is in customer's namespace, each modification still will be put into transport-layers. Therefore a strict definition of features/limits is necessary so that the amount of transports due to "oh, but we also need that"-statements will not become infinite.
2. Generic reports are strict.
What does that mean ? You might want to parse the passed data ( table names, join-binding, selection-parameter-values ) and throw exceptions, if not properly set. Much work. You should offer a badi for that. If You do not do this, expect a dump. let it dump. In the end the user of Your report-api should know ( by documentation perhaps) how to call it. If not, a dynamic SQL-dump will be the result.
3. Generic reports might benefit from badis/exits.
This is self explanaining, I think. Especially generic/dynamic selection/modification/displaying of data should be extendable in terms of
custom-modifications. When You inspect, what a f4-search-help exit works like, You will understand, what I mean.
4. Generic coding is hard to debug, mostly a blackbox.
Self explaining, in the code-section below I can mark some of those sections.
5. Generic coding has some best prectice examples in the repo.
Do not reinvent the wheel. Check, how the se16n works by debugging it,
check how se11 works by debugging it. Check, what the SQL-Query-builder
looks like in the debugger. You will get the idea very soon,
and the copy-paste should be the most simple part of Your work.
6. That are the basic parts of what You might use.
Where clause determination and setting the params.
data lt_range type rsds_trange.
data ls_range_f type rsds_frange.
data lt_where type rsds_twhere.
data ls_where like line of lt_where.
ls_range_f = value #( sign = _sign
option = _option
low = _low
high = _high ).
.
.
.
append ls_frange to lt_range.
.
.
.
call function 'FREE_SELECTIONS_RANGE_2_WHERE'
exporting
field_ranges = lt_range
importing
where_clauses = lt_where.
You have the parameter, let us create the select-result-table.
data(lt_key) = value abap_keydescr_tab( for line in _joinfields)
( name = fieldname ) ).
data(lo_structdescr) = cast cl_abap_structdescr( cl_abap_structdescr=>describe_by_name( _struct_name ) ).
data(lo_tabledescr) = cl_abap_tabledescr=>create( line_type = lo_structdescr p_key = lt_key ).
create data ro_data type handle lo_tabledescr.
.
.
.
select (sel_st)
from (sel_bind)
into corresponding fields of table t_data
where (dyn_where).
Then assign the seelct-table-result-reference to the generic table of this select.
Do You need more hints ?
Yes, such possibility exists, but not by means of function modules. INSERT REPORT statement allows generating report by populating its code from internal text table:
INSERT REPORT prog FROM itab
[MAXIMUM WIDTH INTO wid]
{ [KEEPING DIRECTORY ENTRY]
| { [PROGRAM TYPE pt]
[FIXED-POINT ARITHMETIC fp]
[UNICODE ENABLING uc] }
| [DIRECTORY ENTRY dir] }.

How to use LOOP AT itab INTO <fieldsymbol>

As I rarely loop into a field symbol, I often forget to use ASSIGNING instead of INTO which will promptly cause an abend. Is there a valid use of INTO with <fieldsymbol> or is this something that the syntax checker really ought to catch?
LOOP...INTO is perfectly valid but it will work differently. LOOP...INTO transports the values to the structure provided but ASSIGNING assigns the field symbol to the actual table rows.
The only difference is if you are going to change the table contents. See the following:
* Changes all entries in the CARRID column of lt_flights to 50.
LOOP AT lt_flights ASSIGNING <flight>.
<flight>-carrid = 50.
ENDLOOP.
* Does not change the entries in lt_flights (MODIFY...FROM would be required).
ASSIGN <flight> TO ls_flight.
LOOP AT lt_flights INTO <flight>.
<flight>-carrid = 50.
ENDLOOP.
LOOP...INTO with a field symbol would be useless unless you had some kind of dynamic programming requirement.
It is valid when <fieldsymbol> was previously assigned to a structure which has the type of the lines of the table you loop over.
It is a perfectly valid statement:
APPEND INITIAL LINE TO lt_foo ASSIGNING <ls_foo>.
READ TABLE lt_bar INTO <ls_foo> INDEX 1.
A field symbol just takes the place of a variable - at almost any point - so the syntax check can't flag this as invalid. It might issue a warning, though...