Back to the Future – Part 04
http://scn.sap.com/community/abap/blog/2012/05/01/back-to-the-future–part-01
http://scn.sap.com/community/abap/blog/2012/05/09/back-to-the-future–part-02
http://scn.sap.com/community/abap/blog/2012/05/30/back-to-the-future–part-03
I talked about the historical background that caused me to want to re-write an application in a modern way, steps I have already taken to try and make custom programs more “portable” between SAP systems, and how I am going about building the new “modern” version of the example application, the latter being the subject of this and all subsequent blogs in this series. I think about twelve should do it.
I am giving a tie-in speech on this subject at the SAP Australian User Group annual conference in Melbourne on the afternoon of August 23rd 2012, and I really hope I won;t be talking to any emprty room. Maybe I will have to resort to giving out free beer, I saw someone make that tactic work really well at the SAP Inside Track in Eindhoven in the Netherlands last year.
OK, off we go.
Thomas the Rules Engine
Now I am back in Australia there are so many new things to try it is difficult to know where to start. In an earlier blog I mentioned BRF plus as a possible solution to something, and was advised against using it in that specific scenario, but I couldn’t;t stop myself having a look at it anyway, just to see how easy (or not) it was to use.
Just as a test, instead of creating a new Z table to do some value mapping, I thought I would try BRF plus to see how it goes. This example is a very basic use f the tool, it can do all sorts of fancy things like decision trees and the like. In this case I use a “decision table” which looks like a spread sheet, and indeed is designed for the rules to be uploaded from a spread sheet. In our German system there is a similar custom tool designed to stop the constant creation of loads of new Z customising tables. In the below example there is only one input column (table key) and three results columns.
The idea is that the functional experts design the rules on a spread sheet – which is how I usually get them anyway – and I design a template in the same format within the tool and then upload the spread sheet into BRF plus. In a simple example like this there is no apparent advantage over using a Z table and a maintenance view, this tool only comes into it’s own when you have much more complex rules e.g. instead of 03 I could say “between 3 and 6, but not 4”, or have a custom ABAP function module, or even another embedded object like a decision tree. The results columns can have a function instead of a single value also.
In the ABAP code, when you call the decision rule the worst thing is that you need a 32 digit hexadecimal code. I declare this as a constant to make the actual code more readable. This is the BRF equivalent of calling a function module. Within SAP, BRF objects all have a name containing “FDT” which I presume was the original name of the product.
The problem of course is that you set up the rules in BRF in a web based application as opposed to the SAP GUI. In our system we have a really fast Internet connection when looking at sites like Google or SCN, but in BRF plus you spend half your time looking at a little circle whirling around waiting for the system to react to the input you just sent.
It also has an alarming tendency to freeze, and you end up not being able to edit a given object because it is locked by yourself, and then logging out and back in again is the answer. The other trouble with SAP web based applications is that you have to keep entering your user name and password all day long which reminds me of working with PI. BW configuration (of reports) used to be like this also.
Setting up a domain with multiple values within BRF plus takes a hundred times longer than the equivalent task in SE11. Just so I wouldn’t have to waste the whole day, I ended up creating the domain first and then referencing it in BRF plus, which rather defeats the point. I would love someone to jump up and say, not thatthings ae BETTER in BRF+, clearly they are, but they are EASIER, both for the developer ane end user … that would make it a killer application…
On the plus side, this BRF+ product is still at the stage where loads of OSS notes come out each week, so it is getting better.
In space, no one can create a Screen
Moving back to the problem at hand, the application I am to rebuild is in essence an ALV report with the million functions hanging off it. So, first things first, it was time to get my head around the new ALV model.
I had heard a rumour that in the new ALV world you no longer have to declare a DYNPRO screen in order to have a pop up box with an ALV grid inside it.
As I had to change a certain function module anyway, to add in some improvements I had made in Germany, I thought this was an ideal opportunity to see if this was in fact the case.
After much heartbreak, and roping in some colleagues who were already familiar with the new model (i.e. the told me what to do) I have got his working.
So in my function module there is no longer any DYNPRO screen and yet a pop up screen still appears.
The important part is as follows:-
In the clearing stands a dialog box
That was good as a start, the next step was to create a generic re-usable class ZCL_BC_DIALOG_BOX based on the many examples I found on the internet. This was I would have a tool for the task at hand and also for the many times in the future I would need this.
Firstly I use the CL_SALV_TABLE in its normal usage in a report – that is to create a full screen display of an ALV table.
The handler method is fired when the user does a drill down on the CARRID field. This is just an example, so I will generate some nonsense data.
I am just filling up a table with some random data. I then create an instance f my global ZCL_BC_DIALOG_BOX class. If I wanted to change the attributes of some columns such as making them hotspots or whatever in the grid that is to appear in the dialog box, I would make a local copy of the class and redefine the SET_COLUMN_ATTRIBUTES method.
Anyway, once I have my internal table filled with data I want to display in a dialog box, then I finish off the drill down event handler method as follows:-
SAP will automatically analyse the internal table being passed in and create an ALV grid based upon it.
So, I run the test program and the ever popular SFLIGHT data appears.
I then double click on the CARRID field and a lovely dialog box appears.
I can drag the box all around the screen, and re-size it, all is good. So now every time I want to call up an ALV grid from an ALV report in response to a user-command I do not have to re-invent the wheel.
Doing an impossible thing before breakfast
Next, what I wanted to do was thus:-
- create an ALV grid using class CL_SALV_TABLE so I do not have to mess about creating a field catalouge etc
- have extra buttons at the top of the screen for my user defined functions
- not to have to create a PF_STATUS – I want the model to dynamically say what extra user commands it can handle, and the buttons at the top to be added programmatically by the view.
According to SAP documentation, and everyone on the internet, this is impossible. In full screen mode with CL_SALV_TABLE you get a short dump if you add functions (buttons) to the toolbar programmatically. Always the suggestion was to copy the standard STATUS and then add your own buttons to this.
The reason IMHO copying standard ALV statuses to custom reports is no good is because periodically SAP changes all the ICONS on the standard reports, and then all your custom reports look different to the standard SAP ones.
I spent ages updating the ICONS foe Excel, and changing and saving a variant, and assorted other things in all our custom programs with extra buttons, when we went from 4.5 to 4.7
This approach (adding your own status) also means that CL_SALV_TABLE seems to be not as compatible witn the MVC model as might be desired. Going back to the book “Design Patterns in Object Orientated ABAP” the section on the MVC model has a model that was used by both CL_GUI_ALV_GRID and Web Dynpro and in both cases the model sent out a list of extra buttons, and the relevant GUI technology decided how to add them. A “classic” DYNPRO screen could not do this as you had to manually create the status. It just seemed plain wrong that CL_SALV_TABLE appeared to be a backward step from CL_GUI_ALV_GRID in this regard.
Luckily a colleague found an example program SALV_BS_ADMIN_MAINTAIN, which did not get a mention in the internet in the places I looked at least. I copied over the appropriate bits to my program and everything was fine. This is really complicated, but here’s how we do it.
There is a mysterious interface called IF_SALV_CSQT_CONTENT_MANAGER which has the description “manages the content” as well it might. It turns out we have to add this interface into the definition of our controller class.
The other important thing is that we have to have the IMPORTING parameter above to ur display data method. The reason will become clear.
OK, off we go. We start the report as normal.
Nothing unusual as yet….
Hello, what’s all this? We are calling a function module, and passing in to it the instance of the controller class that is running.
What the function does is to create a screen for us, and a container, and then call method FILL_CONTAINER_CONTENT of interface IF_SALV_CSQT_MANAGER. This is why we had to add the interface to our controller class. Naturally we need an implementation of that method in our program.
Now we can create the CL_SALV_TABLE using the container we have just got back….
… and then add our own functions …
Hooray! I did not have to create a screen. I did not have to create a PF-STATUS. Naturally I am never satisfied, and the next problem is that you cannot ave separators – rumoured to have been fixed in EHP3 but if so I can’t see it – and the grid cannot be editable, but those are problems for another day.
I just voted for SAP to implement this functionality – to allow you to make CL_SALV_TABLE editable – as per an “idea” on “idea place” put forward by Uwe Fetzer and I hope you will too:-
https://cw.sdn.sap.com/cw/ideas/8349
Not Only, But Also
Whilst I was building up a library of re-usable functions it occurred to me that my application had two ALV grids that were displayed at once, a list of unprocessed items, and a list of processed items. So we need two docking containers, one at the top, one at the bottom, each holding a grid. In the book “Design Patterns in Object Orientated ABAP” which I keep plugging (I have no connection to the author, I just think it’s a good book) he explains how to create a re-usable class to neatly arranges containers. In my case I only have two – never more, never less – so this is using a sledgehammer to crack a nut, but I end up with a re-usable tool for when I run into more complicated scenarios.
I also copied over another class he describes to wrap the function modules for reading and updating standard texts into the OO world. Since I use those function modules all over the place I am going to get a lot of re-use out of this.
I shall break off here, next time I will get back on track and deal with the following matters:-
- a way to get around the problem that when you double click on a local class definition, it does not automatically generate a skeleton implementation in the same way FORM routines do
- finally getting around to experimenting with filter BADIS to have different logic for different countries
Cheersy Cheers from the Lucky Country
Paul
Subsequent blogs:-
http://scn.sap.com/community/abap/blog/2012/08/06/back-to-the-future–part-05
http://scn.sap.com/community/abap/blog/2012/08/17/back-to-the-future–part-06
http://scn.sap.com/community/abap/blog/2012/08/31/back-to-the-future–part-06
Other OO Blogs:-
http://scn.sap.com/community/abap/blog/2012/09/08/design-by-contract-in-abap
http://scn.sap.com/community/abap/blog/2013/01/08/domain-specific-language-in-abap
http://scn.sap.com/community/abap/blog/2013/03/02/oo-design-patterns–decorator–in-abap
http://scn.sap.com/community/abap/blog/2013/04/18/are-you-writing-evil-abap-code
http://scn.sap.com/community/abap/blog/2013/06/17/are-you-writing-dirty-filthy-abap-code
http://scn.sap.com/community/abap/blog/2013/07/04/abap-objects–i-want-to-believe
http://scn.sap.com/community/abap/blog/2013/08/09/abap-objects–i-want-to-believe–part-02
http://scn.sap.com/community/abap/blog/2013/10/03/abap-objects-is-the-way-forward–part-03
http://scn.sap.com/community/abap/blog/2013/11/17/dark-is-the-sun-bright-the-sky
Hi Paul,
It looks very interesting what you are doing. I just want to remind you another very good thing that can be used with objects - the serialization. It's acchived using the interface IF_SERIALIZABLE_OBJECT. It can be a good option to store all those settings from your application for example by storing directly the object content in the database in XML format.
Cheers,
Valentin
Hi,
Thank you for the blog post. It is very interesting.
Just a tought. You don't have to necessarly use the interface IF_SALV_CSQT_CONTENT_MANAGER to create the container. You could use the attribute Screen0 of CL_GUI_CONTAINER instead.
So when creating the SALV Object just pass
cl_gui_container=>screen0 to the r_container and everything else should work fine (including adding of new functions).
-
Andrei
I would be very grateful if you could tell me that you have got the above working - passing in CL_GUI_CONTAINER=>SCREEN0 to the R_CONTAINER parameter, and even more grateful for a code sample.
Whenever I try doing this the ALV grid appears fine, but my extra function ICONS don't appear at the top of the screen, I get the exact same result as if I had not passed in a container at all.
I can live without a code sample, but just knowing someone has actually got this working would be useful information.
Cheersy Cheers
Paul
I would be very grateful if you could tell me that you have got the above working - passing in CL_GUI_CONTAINER=>SCREEN0 to the R_CONTAINER parameter, and even more grateful for a code sample.
Whenever I try doing this the ALV grid appears fine, but my extra function ICONS don't appear at the top of the screen, I get the exact same result as if I had not passed in a container at all.
I can live without a code sample, but just knowing someone has actually got this working would be useful information.
Cheersy Cheers
Paul
I always used to wonder why sometimes people posted the same reply three times, now I know. If you post a reply on SCN sometimes pressing the "comment" button appears to have no effect at all.
In fact your reply has been posted but you have no way of knowing this. So you think "oh I must not have pressed the button" so you press it again, and still there is no response, so you press it yet again.
Actually I can get the ICONS to appear, the problem comes when trying to go into editable mode, the GET_GLOBALS_FROM_SLVC_FULLSCR does not return an instance of the underlying ALV grid object.
Hi Paul,
Originally me entire code to display an ALV by using SALV was written inside a Z Class method. So I can confirm that it worked there to use cl_gui_container=>screen0.
Additionally I also tried your method of making the table editable and it didn't work for me either. The function returned a null object.
Now, i tried to move the code from my Z class to an ABAP Program, and ouput an ALV using SALV class and cl_gui_container=>screen0 but it does not work. So far I don't know what I'm doing wrong or what's the trick, but I'll get to the bottom of this.
-
Andrei
Just tried with cl_gui_container=>screen0, and I got a blank screen.
It's never worked for me either!
So I am sticking with my good old function module to create the container. Really for editing data the SALV is an "epic fail" and wrapping CL_ALV_GUID_GRID with methods to auto-generate the container and the field catalogue is the way forward.
Whilst I am here, it is elephant in the room time, to quote a famous TV show, done by Bob Monkhouse in the UK in the seventies, and now a huge thing in Australia in a current incarnation.
We asked one hundred users, which is the easiest way to input data in a table format in an SAP environment?
The contestants (IT staff, who never have to enter such data all day long) said:-
WEB = 80%
ALV Grid = 20%
The survey (users who have to deal with this) said:-
DYNPRO Table Control = 95%
WEB = 5%
Those table controls look horrible but the squares are nice and big, you always know where you cursor is, and you do not have to remove a value like zero before entering your actual value. Admittedly the average age of my user base is rather high.
The first time I replaced a table control with an editable ALV gird I though I was going to get a medal and be paraded abounded the office on the backs of the grateful users, in a ticker tape parade. Instead I got tarred and feathered and I could hear the six guns sound, as they chased me out of town.
cl_gui_container=>screen0 works only if it's done in the PBO of an existing dynpro; it works like any other container, its peculiarity being it's an implicit container which overlaps the whole screen area.
For using it with SALV, it must be instantiated via a parent container, so it won't be a full screen ALV and consequently the application toolbar will not contain any ALV button, instead it will be displayed right below in the main screen area above the ALV grid (same thing as Paul said on Mar 11, 2013 9:06 AM in response to Andrei Sosea).
I often use screen0 with dummy selection screens for little demo applications with GUI controls so that to not create a dynpro. I also define additional buttons using SELECTION-SCREEN FUNCTION KEY 1 (up to 5). Of course with an ALV, there would be a large toolbar occupying 2 rows. It's very simple to distribute/execute the code.
(PS: screen0 is for the popup level 0 i.e. main dynpro, no popup, while screen1 is to be used for popup of first level, screen2 for second popup level...)
Also for me, when using r_container = cl_gui_container=>screen0 , screen displays empty, unless I add statement write ‘.’.
example code:
Anyone sees issues with using write statement?
Hi Space One
While calling the factory method, you are exporting the value “cl_gui_container=>screen0″ for “r_container” parameter, This is causing a problem for you and so you need to write the
“WRITE ‘.’.” statement. Might be that, it is not able to get screen0 so it is behaving weird,
If you do not export any parameter for this method, that is fine and it will solve your problem,
and no longer you would need to write “WRITE ‘.’.”
Thanks.