Sunday, December 28, 2008

ABAP Proper Case Regex

I need to pull full user names from ADRP for an audit report, but the case is all over the place. This piece of code converts a character string to proper case (first letter uppercase). I wanted to handle Mc and Mac too, but ABAP implements the Posix regex syntax, which has no support for back referencing. If anyone knows a regular expression to catch the first character after Mac then please post a response.

report zzzzzzzz.

data:
li_ofs type i,
lv_name(30).

lv_name = 'PETER CHAPMAN'.

write: / lv_name.

translate lv_name to lower case.
while sy-subrc = 0.
translate lv_name+li_ofs(1) to upper case.
find regex '\b[a-z]' in lv_name match offset li_ofs.
endwhile.

write: / lv_name.

Tuesday, December 16, 2008

Efficiency versus Effort - The Eff Debate

A lot of inefficient code is developed from ignorance and laziness. This is so good for hardware vendors that they have established a school of thought that says it's easier to upgrade than to make the code faster. If users really cared about performance, we wouldn't have the explosion of internet applications, or the idea that Office running on the internet ala Googledocs is an improvement.

In spite of all this evidence, I still have a deep abhorrance of needlessly wasted processor cycles. In the world of custom SAP development, most sites can easily double the performance of their custom code by simply having an expert tune it. Even (especially?) SAP developed code can appear to prefer obfuscation over efficiency. It is a tough place for people who see coding as a minimilst artform, constantly striving for irreducible perfection.

There are times, though, when elegance trumps efficiency. In the code below, I have preferred unnecessary calls to LAST_DAY_IN_PERIOD_GET to preserve the integrity of the case statement as the sole logic to determine intervals. Do you agree? It would also be possible to put the periods into a table (array for any non-SAP people reading this, shocked that COBOL is making a comeback - we call it ABAP). But for such a small number of intervals it is more readable like this.


*&---------------------------------------------------------------------*
*& Form SET_AGE
*&---------------------------------------------------------------------*
form set_age
using p_end type d
changing p_agerq type ysd_agerq.

constants:
c_periv type tkel-periv value 'G1'.

statics:
ld_age0003 type d,
ld_age0406 type d,
ld_age0709 type d,
ld_age1012 type d.

data:
lv_enddate type d,
lv_horizon type i,
lv_period type jahrper.

*-- set up static dates
if ld_age0003 is initial.

lv_period = p_per.

do 12 times.

lv_horizon = sy-index.

call function 'RKE_GET_NEXT_PERIOD'
exporting
perio = lv_period
periv = c_periv
importing
nextperio = lv_period
exceptions
i_error = 1
i_perflag_invalid = 2
i_periv_notfound = 3
others = 4.
if sy-subrc <> 0.
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
endif.

call function 'LAST_DAY_IN_PERIOD_GET'
exporting
i_gjahr = lv_period+0(4)
i_periv = c_periv
i_poper = lv_period+4(3)
importing
e_date = lv_enddate
exceptions
input_false = 1
t009_notfound = 2
t009b_notfound = 3
others = 4.

if sy-subrc <> 0.
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
endif.

case lv_horizon.
when 3.
ld_age0003 = lv_enddate.
when 6.
ld_age0406 = lv_enddate.
when 9.
ld_age0709 = lv_enddate.
when 12.
ld_age1012 = lv_enddate.
endcase.
enddo.
endif.

*-- Allocate this date to a period range
if p_end le ld_age0003.
p_agerq = '00-03'.
elseif p_end le ld_age0406.
p_agerq = '04-06'.
elseif p_end le ld_age0709.
p_agerq = '07-09'.
elseif p_end le ld_age1012.
p_agerq = '10-12'.
else.
p_agerq = '12+'.
endif.

endform. " SET_AGE

Monday, December 1, 2008

ALV grid control in 3 lines

Here is some code inspired by Dany Charbonneau (link). It creates an ALV grid control with just 3 lines of ABAP. You should not be using REUSE_ALV_GRID_DISPLAY or REUSE_ALV_GRID_DISPLAY_LVC function modules any more - these are superseded by programming the objects directly. As you move over to ABAP Web Dynpro you will need those object skills anyway...

I like the elegance of well designed and documented classes. But I hate abstraction for its own sake - simple structured programs and reports are quicker to develop and easier to maintain. If you are not expecting to reuse the class then there is a strong argument for not writing it in the first place.

Fortunately CL_GUI_ALV_GRID is one of the well designed and documented ones. Here is the program.



report zzzzzzz1.

data:
lo_alv type ref to cl_gui_alv_grid,
lt_tab type table of t001.

selection-screen begin of screen 1100.
selection-screen end of screen 1100.

select * from t001 into table lt_tab.

*-- Line 1 - instantiate the alv object in the required screen
create object lo_alv
exporting
i_parent = cl_gui_container=>screen0.

*-- Line 2 - specify the data structure and content
call method lo_alv->set_table_for_first_display
exporting
i_structure_name = 'T001'
changing
it_outtab = lt_tab.

*-- Line 3 - display the screen
call selection-screen 1100.