ABAP Coding

Home / SAP / Archive by category "ABAP Coding"

ABAP – Screen Design – adding a checkbox to a table control

So while building my new territory manager, I ran into a small piece that I forgot about.  Adding a checkbox to a table control.  Turns out, it’s pretty easy, but not exactly intuitive.  So, make sure you have a character based column, that is only 1 char in length.  Once you have that, you can do the following.

Right click on the column, select convert->checkbox-> either left or Right button.

it will then convert your character column to a checkbox.

Thanks for reading,

ABAP – S/4 – If Line_exists

Here’s another new one I discovered.  How often you do write a few lines of code to check if something exists?  For example, a common thing I do is look for an entry in a table?  If it’s there, I need to do something, if not, I move on. For example:

read table Lt_test transporting no lines with key key1 = val1 key2 = val2.

if sy-subrc = 0.

else.

endif.

Well, in S/4, that has been condensed.

if line_exists( lt_test[key1 = val1 key2 = val2]).

else.

endif.

you get to skip the read statement.  Now, if you need the contents, this might not help as much, since you would need to extract that line anyway, but if you are purely looking for the existence, then it’s a lot cleaner.

Thanks for reading,

ABAP – S/4 Concatenate

Here’s another fun little tidbit for the new coding in S/4.  If you want to concatenate a string together you used need to do:

CONCATENATE ‘X’ ‘Y’ into lv_var.

now you can do:

lv_var = ‘X’ && ‘Y’.

Even better, you don’t run into type mismatches either.  For example, if you have a time stamp, the value is in a packed format.  This means that you must first concatenate things into a string, then copy them to the final value.  with the &&, you can skip all that and do it in a simple one line statement.

ABAP really is getting better 🙂

Thanks for reading,

SAP – Coding in S/4 – Data Statements

I recently had the opportunity to see some code in S/4.  While the old code works, there are certainly some new things that simplify coding life.  One of the fun ones I learned is how you do a smarter data statement.  Here is my first example.  You take in a customer number in the internal format, but you want to convert it to the external format.  Here’s how I do it today:

DATA: lv_kunnr_out TYPE char10.
CALL FUNCTION ‘CONVERSION_EXIT_ALPHA_OUTPUT’
EXPORTING
input = i_kunnr
IMPORTING
output = lv_kunnr_out.

Here’s how you can do it in S/4.

* DATA(lv_kunnr_out) = |{ i_kunnr ALPHA = OUT }|.

Pretty slick.  it’s not gonna change the world, but it nice to make things more readable 🙂

Thanks for reading,

ABAP – Code Inspector Results

I must say, I was pretty happy with the results of the code inspector.  I was fearing I would have a LOT of rework, but it turned out to be a manageable number of errors/warnings/information.

The only errors I had were all the same message:

Large table X: No WHERE condition

And these revolved around some search help functions that I built for my UI5 applications.  So it was a simple matter of finding an appropriate field to include in the WHERE statement.

Aside from that, all of my warnings/information messages were the same as well:

Possible use of <internal table> without prior content check.

This is the more important one for me.  This is an instance where I populated an internal table, but didn’t check to make sure it was populated before using it in a select statement FOR ALL ENTRIES IN.

I’ve run into this before, and it’s caused crazy long run times before it reads the entire table.  Short story… BAD.  So this is a great way to make sure that I fix any outstanding issues.  It’s a very simple fix.  Add an IF statement around the Select statement to check that it is NOT INITIAL.  Problem solved 🙂

I highly encourage running this, even if you don’t plan to upgrade to HANA anytime soon.  It’s a good method to make sure your code is following some simple standards.

Thanks for reading,

SAP – Preparing your Code for S/4

I recently listened to a presentation from some developers that talked about preparing your development objects to move to S/4.  This obviously got my attention, since I want to move my add-ons to be on S/4.  Here’s what I learned.

Apply OSS Note:  2185390

For me, this was a bit more time consuming that I expected.  Because my system is behind the times, it means I had to apply a lot of notes before I could finally apply this one.  So it took me a few hours to gather up all the notes I needed, get them applied.

Next up, you need to create an index.  Here’s what the OSS note tells you:

Before Custom Code Analyzer (program SYCM_DOWNLOAD_REPOSITORY_INFO) can analyze your custom code, an up-to-date where-used index for customer objects as well as SAP objects is required in your system. Custom Code Analyzer will check whether the where-used index is up to date as first processing step and will raise an error log entry if it has to be updated.

In order to update the where-used-index for customer and SAP objects, run program SAPRSEUB as background job in the system to be analyzed.

Currently, in my system, I’m running the index.  It’s been going for almost 12 hours now.  Certainly due to my hardware, but regardless, give it some time.  Once that’s done, you can run the download repository (listed above).  It will give you a zip file listing the areas you need to look at.  I’ll be doing a follow up post on some of the common things I need to fix once I can run the program.

Thanks for reading,

 

ABAP – Refresh ALV GRID and keep position and current cell

Since I’ve been rebuilding my Renovation product into the old school Dynpro, it’s meant relearning a few tricks.  Today, my trick was to keep the position, selections and current cell after refreshing the data with new data or updated date.  First off, I need to thank this post for the great info.

Here’s the basics.  Before you refresh the table, you will need to perform the following on your ALV grid.

  dataes_row_no  type lvc_s_roid.
  dataes_row_info  type lvc_s_row.
  dataes_col_info  type lvc_s_col.
  datafes_row_no  type lvc_s_roid.
  datafes_row_id  type lvc_s_row.
  datafes_col_id  type lvc_s_col.
  datamt_cells type lvc_t_ceno.
  datamt_rows type lvc_t_row.

  grid->get_scroll_info_via_id(
  importing
    es_row_no   es_row_no
es_row_info 
es_row_info
es_col_info 
es_col_info
).

  grid->get_current_cell(
    importing
*        e_row     = e_row
*        e_value   = e_value
*        e_col     = e_col
      es_row_id fes_row_id
es_col_id 
fes_col_id
es_row_no 
fes_row_no
).

  grid->get_selected_rows(
  importing
    et_index_rows mt_rows
*            et_row_no     = et_row_no
    ).
  if mt_rows[] is initial.
    grid->get_selected_cells_id(
    importing  et_cells mt_cells ).
  endif.

Now, there are multiple ways to refresh the table, I use set_table_for_first_display, but the post example uses refresh_table_display.  Either way, after you do your refresh, then run the following to set the position and selections.

    if mt_cells[] is not initial.
      grid->set_selected_cells_idit_cells mt_cells   ).
    else.
      grid->set_selected_rows(
      it_index_rows            mt_rows
*        it_row_no                = it_row_no
*        is_keep_other_selections = is_keep_other_selections
      ).
    endif.

  grid->set_scroll_info_via_id(
  is_row_info es_row_info
is_col_info 
es_col_info
is_row_no   
es_row_no
).

    grid->set_current_cell_via_idis_row_id fes_row_id
is_column_id 
fes_col_id
is_row_no 
fes_row_no ).
  refreshmt_rows[]mt_cells[].

Thanks for reading,

Netweaver Gateway – Using Expand

Netweaver Gateway – Using Expand

I’ve recently started to move a new product onto UI5, and of course, that has open up new areas for me to explore.  The most recent was display the notification.  Initially, this sounded so easy.  Unfortunately, when you look at a document, there are many different tables associated with a single notification.

Header, items, tasks, etc.

I wrote my RFC to accept a single input of notification number, but the output consists of header and a bunch of tables.  Of course, for UI5, having a structured OData is far easier to work with, instead of doing a whole bunch of reads to the same RFC and tie them together myself.  Luckily, I found a great blog post that showed me the major things I needed to do:

http://scn.sap.com/community/gateway/blog/2014/07/18/implementing-expand-entityentity-set

Now, of course, this requires some work on the service side as well as in the coding.  So on the service side, you need to tie everything together with associations and navigation to connect the header to each of the individual tables.  Next, you go to the DPC_EXT class, and update the get_expanded_entityset method.  In this method, you need to build your structure.  You can make this as deep as you want, but this will make your service easier to use on the UI5 side.

Now, you can use the expand command within UI5 to say what pieces to pull out.  One thing I discovered while doing this, if you manually create each step of the association, my service had difficulties reading the expand.  So make sure you right click on Associations and select create.  This will walk you through 3 steps to make the connections.  For some reason when I manually built the pieces, my service couldn’t expand.  It might be my old version of the Gateway, but keep this in mind.

Thanks for reading,

Code Security? Do you Trust your customers?

I was recently asked “How do you protect your code from someone just copying everything you’ve done?”  I sat there with a straight face, and said… “Well…  I don’t”.  The simple question got me to thinking about this interesting question.  Do you take efforts to make sure (or least make it difficult) no one can copy your code?

Now, if you live in most programming languages, they require a compiler, and your code is instantly safe.  But in ABAP, when you write something, it’s out there for any halfway decent programmer with some time on their hands to pirate everything you’ve painstakingly worked on.  Now of course, there is the legal recourse, disclaimers, contracts, etc.  But at the end of day, many of us are small companies, and a big legal battle is the last thing we want to deal with.  So I started googling.  The general consensus seems to be of two camps.  One, you need to trust your customer and to go through and encrypt/hide/etc your code shows bad etiquette.  Two, why bother because any 1/2 way decent programmer in ABAP could get to it anyway… and by you hiding your code, just makes it even more appealing to crack the code.

Now Google/SCN talks about adding a strange character string:  *@#@@[HOME:SAP] that if you put this in front of code it hides it “forever”.  I haven’t tried it out… but I am tempted to just to see if it works.  But at the end of the day, is it worth it?  can customers be trusted?  can you afford not to trust them?

I’d love to hear your opinions.  And as always, thanks for reading,

Web Dynpro – Setting a Default Select-Option

Well, there are some things I take for granted, and that’s how easy things seem to be inside of standard ABAP programming.  I come realize this whenever I try to do one of these “simple” activities in Web Dynpro.  Take today’s adventure.  I had some select-option fields, and I just wanted to default a value in there.  Sounds so easy.  And eventually it was.  here’s what I finally found.

I had a select option for ERDAT (creation date).  I’m not going to go into the select option creation.  I think I talked about that a while ago, so just search my blog if you need more info.  SERDAT is the ID of my option that I want to default a value for.

*** SET DEFAULT FOR ERDAT
DATA lo_nd_range_erdat TYPE REF TO if_wd_context_node.
DATA lt_range_erdat TYPE wd_this->Elements_range_erdat.
DATA ls_range_erdat TYPE wd_this->Element_range_erdat.
*** here’s the magic ***

FIELD-SYMBOLS<LT_RANGE_ERDAT> TYPE TABLE.
CREATE DATA LT_RANGE TYPE TABLE OF /JVS/SO_ERDAT.
ASSIGN LT_RANGE->TO <LT_RANGE_ERDAT>.

*** end the magic ***

*** this code is just setting the value back to my context node.
* navigate from <CONTEXT> to <RANGE_ERDAT> via lead selection
lo_nd_range_erdat wd_context->get_child_nodename wd_this->wdctx_range_erdat ).
ls_range_erdatsign ‘I’.
ls_range_erdatoption ‘BT’.
ls_range_erdathigh sydatum.
ls_range_erdatlow sydatum 30.
APPEND ls_range_erdat to lt_range_erdat.
lo_nd_range_erdat->bind_tablenew_items lt_range_erdat set_initial_elements abap_true ).
*** back to the default ***
*** notice I needed to set the value to the DATA field symbol.
APPEND ls_range_erdat to <LT_RANGE_ERDAT>.
LR_HELPER->SET_RANGE_TABLE_OF_SEL_FIELD(
EXPORTING
I_ID ‘SERDAT’
IT_RANGE_TABLE LT_RANGE ).

*** end the default code

 

I hope you can find a use for this,
Thanks for reading,