2020 May 13 9:22 AM
My ALV report, once double click on header, the line item will show.
When i tried to sort by header, once double clicked (on header), it is not showing correct line item (image).
Form SORT.
DATA: NO TYPE I VALUE 1.
IF G_GRID_LEFT IS NOT INITIAL. <<<< value for SPOS FIELDNAME was showing
CLEAR gt_sort.
GS_SORT-SPOS = NO.
GS_SORT-FIELDNAME = 'EBELN'.
GS_SORT-DOWN = 'X'.
APPEND GS_SORT TO GT_SORT.
ELSEIF g_grid_right IS NOT INITIAL. <<< during debug it skips this part, as ebeln is key field
CLEAR gt_sort.
GS_SORT-SPOS = NO.
GS_SORT-FIELDNAME = 'EBELN'.
GS_SORT-DOWN = 'X'.
APPEND GS_SORT TO GT_SORT.
ENDIF.
ENDFORM.
The purchasing doc number (between header and line item) are sharing the same key, when double clicked by right line item should show relevant purchasing document item details (as shown before perform SORT was added into the program)
Program: https://www.mediafire.com/file/v0tlqnarkogm1ov/ALV_Program.docx/file
Hi arnold92
Yes, you're not able to do it, because an instance variable requires an object instance to exits. If you don't have an instance of an object, then instance variable defined for this object (in the class) won't exist either.
However, in your case, you can define the AT_ZHEADER and AT_ZITEMS attributes as static and it will be fine.
I urge to read about instance and static attributes/methods, for example this article: https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-us/abenclass_attributes.htm
regards,
Mateusz
2020 May 13 10:11 AM
Please attach file inside SAP forum, otherwise it may disappear in the future.
2020 May 13 10:46 AM
2020 May 13 10:57 AM
Create method
value( IT_ZHEADER ) TYPE ZEKKO03_TT PO Header Table Type - importing
value( IT_ZITEMS ) TYPE ZEKPO03_TT PO Item Table Type - importing
value( ES_BAPIRET2 ) TYPE BAPIRET2 Return Parameter - exporting
METHOD CREATE_PURCHASE_ORDERS.
DATA: ls_zheader LIKE LINE OF it_zheader,
ls_zitems LIKE LINE OF it_zitems.
append ls_zheader TO IT_ZHEADER.
modify zekko03 FROM TABLE it_zheader .
IF SY-SUBRC = 0.
COMMIT WORK.
ES_BAPIRET2-TYPE = 'S'.
ES_BAPIRET2-MESSAGE = 'Successfully updated for table ZEKKO03'.
ELSE.
ROLLBACK WORK.
ES_BAPIRET2-TYPE = 'E'.
ES_BAPIRET2-MESSAGE = 'Error updating table ZEKKO03'.
ENDIF.
append ls_zitems TO IT_ZITEMS.
modify zekpo03 FROM TABLE it_zitems.
IF SY-SUBRC = 0.
COMMIT WORK.
ES_BAPIRET2-TYPE = 'S'.
ES_BAPIRET2-MESSAGE = 'Successfully updated for table ZEKKO03'.
ELSE.
ROLLBACK WORK.
ES_BAPIRET2-TYPE = 'E'.
ES_BAPIRET2-MESSAGE = 'Error updating table ZEKKO03'.
ENDIF.
ENDMETHOD.
delete method
value( IV_IS_DELETE_ALL ) TYPE BOOLEAN OPTIONAL Purchasing Document Number - impoting
value( IT_ZHEADER ) TYPE ZEKKO03_TT PO Header Table Type - importing
value( IT_ZITEMS ) TYPE ZEKPO03_TT PO Item Table Type - importing
value( ES_BAPIRET2 ) TYPE BAPIRET2 Return Parameter - exporting
METHOD DELETE_PURCHASE_ORDERS.
DATA: LS_ZHEADER TYPE ZEKKO03,
LS_ZITEMS TYPE ZEKPO03,
LV_COUNT_HDR TYPE I,
LV_COUNT_ITEMS TYPE I.
IF IV_IS_DELETE_ALL = 'X' OR IV_IS_DELETE_ALL = 'x' .
DELETE FROM ZEKKO03.
DELETE FROM ZEKPO03.
IF SY-SUBRC = 0.
ES_BAPIRET2-TYPE = 'S'.
ES_BAPIRET2-MESSAGE = 'All records deleted'.
ENDIF.
ELSE.
LOOP AT IT_ZHEADER INTO LS_ZHEADER.
SELECT COUNT(*) INTO LV_COUNT_HDR FROM ZEKPO03
WHERE EBELN = LS_ZHEADER-EBELN.
ENDLOOP.
IF LV_COUNT_HDR = 1.
DELETE FROM ZEKPO03 WHERE EBELN EQ LS_ZHEADER-EBELN.
DELETE FROM ZEKKO03 WHERE EBELN EQ LS_ZHEADER-EBELN.
IF SY-SUBRC = 0.
ES_BAPIRET2-TYPE = 'S'.
ES_BAPIRET2-MESSAGE = 'Record successfully deleted'.
ELSE.
ES_BAPIRET2-TYPE = 'E'.
ES_BAPIRET2-MESSAGE = 'Error deleting record'.
ENDIF.
ENDIF.
ENDIF.
ENDMETHOD.
select method
value( IV_KEY ) TYPE ZEBELN_EMNT OPTIONAL Purchasing Document Number - importing
value( IV_MAX_ROWS ) TYPE I DEFAULT 0 0 - means load ALL - importing
value( IT_ZHEADER ) TYPE ZEKKO03_TT PO Header - exporting
value( IT_ZITEMS ) TYPE ZEKPO03_TT PO Line Item - exporting
value( ES_BAPIRET2 ) TYPE BAPIRET2 Return Parameter - exporting
DATA: LS_ZHEADER TYPE ZEKKO03.
IF IV_KEY IS INITIAL .
SELECT MANDT EBELN BEDAT BSART LIFNR WAERS KNUMV
INTO TABLE IT_ZHEADER
FROM ZEKKO03
WHERE EBELN EQ IV_KEY.
IF SY-SUBRC = 0.
IF IV_MAX_ROWS GT 0.
SELECT MANDT EBELN BEDAT BSART LIFNR WAERS KNUMV
FROM ZEKKO03 INTO TABLE IT_ZHEADER
UP TO IV_MAX_ROWS ROWS.
SELECT MANDT EBELN EBELP BUKRS WERKS MATNR MENGE MEINS NETPR
FROM ZEKPO03 INTO TABLE IT_ZITEMS UP TO IV_MAX_ROWS ROWS
WHERE EBELN EQ IV_KEY.
ES_BAPIRET2-TYPE = 'S'.
ES_BAPIRET2-MESSAGE = 'Record with input rows found'.
ELSEIF IV_MAX_ROWS EQ 0.
SELECT MANDT EBELN EBELP BUKRS WERKS MATNR MENGE MEINS NETPR
FROM ZEKPO03 INTO TABLE IT_ZITEMS
WHERE EBELN EQ IV_KEY.
ES_BAPIRET2-TYPE = 'S'.
ES_BAPIRET2-MESSAGE = 'All records found'.
ELSE .
ES_BAPIRET2-TYPE = 'E'.
ES_BAPIRET2-MESSAGE = 'No record found'.
ENDIF.
ELSE. "this statement belongs to sy-subrc (all above are fulfilled)
SELECT MANDT EBELN BEDAT BSART LIFNR WAERS KNUMV
FROM ZEKKO03 INTO TABLE IT_ZHEADER
UP TO IV_MAX_ROWS ROWS.
LOOP AT IT_ZHEADER INTO LS_ZHEADER. ""join line item to header
SELECT MANDT EBELN EBELP BUKRS WERKS MATNR MENGE MEINS NETPR
FROM ZEKPO03 APPENDING TABLE IT_ZITEMS
WHERE EBELN EQ LS_ZHEADER-EBELN.
ENDLOOP.
ENDIF.
ELSE.
SELECT MANDT EBELN EBELP BUKRS WERKS MATNR MENGE MEINS NETPR """added for ALV program
INTO TABLE IT_ZITEMS
FROM ZEKPO03
WHERE EBELN EQ IV_KEY.
SELECT MANDT EBELN BEDAT BSART LIFNR WAERS KNUMV """" added for ALV program
INTO TABLE IT_ZHEADER
FROM ZEKKO03
WHERE EBELN EQ IV_KEY.
ENDIF.
reload method
METHOD RELOAD_PURCHASE_ORDERS.
DATA: IT_EKKO TYPE TABLE OF ZEKKO03,
IT_EKPO TYPE TABLE OF ZEKPO03.
SELECT MANDT EBELN BEDAT BSART LIFNR WAERS KNUMV
FROM EKKO INTO CORRESPONDING FIELDS OF TABLE IT_EKKO.
INSERT ZEKKO03 FROM TABLE IT_EKKO ACCEPTING DUPLICATE KEYS.
IF SY-SUBRC = 0.
ES_BAPIRET2-TYPE = 'S'.
ES_BAPIRET2-ID = 'HDRSuccess'.
ES_BAPIRET2-MESSAGE = 'Data with specified row reloaded into tables'.
ENDIF.
SELECT MANDT EBELN EBELP BUKRS WERKS MATNR MENGE MEINS NETPR
FROM EKPO INTO CORRESPONDING FIELDS OF TABLE IT_EKPO.
INSERT ZEKPO03 FROM TABLE IT_EKPO ACCEPTING DUPLICATE KEYS.
IF SY-SUBRC = 0.
ES_BAPIRET2-TYPE = 'S'.
ES_BAPIRET2-ID = 'LINESucces'.
ES_BAPIRET2-MESSAGE = 'Data with specified row reloaded into tables'.
ENDIF.
ENDMETHOD.
2020 May 13 2:02 PM
In fact, I don't understand what symptom you have, how to reproduce, and what you expect.
Let me rephrase:
Note that I don't understand your double click handler method, why do you use the method GET_SELECTED_ROWS instead of using the parameter E_ROW which contains the number of the double-clicked line? Why do you call the method select_purchase_orders 5 times? Why do you need to refresh the left ALV of headers? (only the right ALV of details needs to be refreshed - keep things simple)
2020 May 13 6:51 PM
1. Yes
2. Attached image, it is showing the wrong line item (wrong-line-item.png)
3. once performed double click on header, it should show relevant line item
why do you use the method GET_SELECTED_ROWS
im get_selected_rows has ET_ROW_NO with allows to read row_id, read by index is not applicable for double click in pmy program previously
didnt manage to find a good sample for double click that is applicable to my program
Why do you call the method select_purchase_orders 5 times?
Here is the debug result for delete method - debug 1 through 4 images
Refresh left ALV is needed for the delete record to reflect at runtime. If removed the refresh, it will not reflect at runtime but only removed the record in database table zekko03
2020 May 13 6:54 PM
2020 May 13 6:56 PM
2020 May 13 7:05 PM
So it's not a sorting issue. It's just that you don't select the right line. Why don't you use the parameter E_ROW instead of GET_SELECTED_ROWS? (NB: in debug, you should find out the reason why the wrong line is retrieved, we can't do that for you)
Don't refresh left ALV of headers if one of its lines is double clicked. Refresh left ALV only if a line from database table ZEKKO03 is actually deleted. I advise to not reload the whole internal table, just delete the corresponding line of the internal table.
2020 May 14 5:24 AM
Yes im not refreshing the left grid (for double click) and I made changes to E_ROW as well, still the same result as previous one (with get_selected_row) where it retrieved the wrong line
METHOD HANDLE_DOUBLE_CLICK.
* define local data
DATA:
LT_ZHEADER TYPE TABLE OF ZEKKO03,
LT_ZITEMS2 TYPE TABLE OF ZEKPO03,
LS_ZHEADER TYPE ZEKKO03,
LS_ZITEMS2 LIKE LINE OF LT_ZITEMS2. """ like line of applicable to structure for ztables
IF e_row-index gt 0.
CALL METHOD ZCL_03_DATA_MODEL=>SELECT_PURCHASE_ORDERS """ PO selection to get total number of record on header in the db table
EXPORTING
* IV_KEY =
IV_MAX_ROWS = IV_MAX_ROWS
IMPORTING
IT_ZHEADER = LT_ZHEADER .
READ TABLE LT_ZHEADER INDEX e_row-index INTO LS_ZHEADER.
CALL METHOD ZCL_03_DATA_MODEL=>SELECT_PURCHASE_ORDERS """""select line items based on header
EXPORTING
IV_KEY = LS_Zheader-EBELN
* IV_MAX_ROWS =
IMPORTING
* IT_ZHEADER =
IT_ZITEMS = LT_ZITEMS2
* ES_BAPIRET2 =
.
ENDIF.
GT_ZITEMS = LT_ZITEMS2.
G_GRID_RIGHT->REFRESH_TABLE_DISPLAY( ). <br>I already have a key LS_Zheader-EBELN
CLASS-METHODS:
HANDLE_DOUBLE_CLICK FOR EVENT DOUBLE_CLICK OF CL_GUI_ALV_GRID
IMPORTING
E_ROW
E_COLUMN.<br>With e_row and e_column defined, what else have i missed?
2020 May 14 5:28 AM
The debug result shown as retrieved the wrong line (deb1.png to deb3.png3)
2020 May 14 7:13 AM
With E_ROW-INDEX, why do you access another internal table than the one of the left ALV? It's then normal that the line which is read doesn't correspond to the one in the left ALV.
READ TABLE GT_ZHEADER INDEX e_row-index INTO LS_ZHEADER.
2020 May 14 7:30 AM
Hi arnold92
The issue is that you're reading data from DB again into the LT_ZHEADER internal table. When you do that, you're losing the sorting that was done in ALV, thus reading record with index gives you an incorrect results.
Make an instance variable in your class called for example AT_ZHEADER (a for attribute) and read the PO data into the table only once, when you're loading your program.
Do the same for items.
This way your program will work faster (no multiple DB reads) and you won't have to refresh the data in every method.
When you remove the DB refresh you should also have a proper result of your HANDLE_DOUBLE_CLICK method.
Hope this helps.
regards,
Mateusz
2020 May 14 9:20 AM
Hi Mateusz,
Sorry im still new to this and worth learning, do you mean doing it in this way? Meaning i have to change all method to instance method? im using static method
CLASS LCL_EVENTHANDLER DEFINITION." class definition
PUBLIC SECTION.
CLASS-METHODS:
HANDLE_DOUBLE_CLICK FOR EVENT DOUBLE_CLICK OF CL_GUI_ALV_GRID
IMPORTING
E_ROW
E_COLUMN
ES_ROW_NO
SENDER.
DATA: AT_ZHEADER TYPE ZEKKO03.
ENDCLASS. <br>
CLASS LCL_EVENTHANDLER IMPLEMENTATION." implementation
METHOD HANDLE_DOUBLE_CLICK.
* define local data
DATA:
LT_ZHEADER TYPE TABLE OF ZEKKO03,
LT_ZITEMS2 TYPE TABLE OF ZEKPO03,
LS_ZHEADER TYPE ZEKKO03,
LS_ZITEMS2 LIKE LINE OF LT_ZITEMS2. """ like line of applicable to structure for ztables
IF e_row-index gt 0.
READ TABLE AT_ZHEADER INDEX e_row-index INTO LS_ZHEADER. """use ALV internal table to perform read data
CALL METHOD ZCL_03_DATA_MODEL=>SELECT_PURCHASE_ORDERS """""select line items based on header
EXPORTING
IV_KEY = LS_Zheader-EBELN
* IV_MAX_ROWS =
IMPORTING
* IT_ZHEADER =
IT_ZITEMS = LT_ZITEMS2
* ES_BAPIRET2 =
.
ENDIF.<br>
2020 May 14 9:25 AM
Hi arnold92
No worries. 🙂 We've all been there some time ago.
Sure, you can make it an instance attribute and change the methods to instance. You can also make the attributes static and keep on using the static methods.
It really depends on the requirements and logic of the report you're working on. As this is a test report, as far as I understand, then keep everything static, just to save time and not change everything.
regards,
Mateusz
2020 May 14 10:00 AM
Ive been using static method since the beginning for this test report, so what you are suggesting "instance variable " only applicable to instance method and not static?
2020 May 14 10:05 AM
Yes, you need to have an instance to be able to use an instance variable. Since you only have static methods, then I don't think you have an instance of your object.
In this case just make the attributes static, for the purpose of this learning exercise it will be just fine.
regards,
Mateusz
2020 May 14 10:53 AM
arnold92 Refactoring the code so that it's coded according to best practice is maybe not the priority for you, because you should first make the program work.
But of course, in the end, Mateusz is right. If you write object-oriented code, you should also write the whole "view" part inside a class. Currently you only defined a "model" class to work with the database. But be careful to not mix information from the view and from the model. AT_ZHEADER is part of the "view". Note that LCL_EVENTHANDLER should be merged into the view class.
In the Model-View-Control design, you also have the controller class to control what view is to be displayed and so on.
Finally, your report should just have one line of code to invoke the controller class.
2020 May 14 10:53 AM
Sorry to ask again, if im using static method, then im not able to do what you are saying as below?
" Make an instance variable in your class called for example AT_ZHEADER (a for attribute) and read the PO data into the table only once, when you're loading your program.
Do the same for items.
This way your program will work faster (no multiple DB reads) and you won't have to refresh the data in every method."
2020 May 14 11:02 AM
Hi arnold92
Yes, you're not able to do it, because an instance variable requires an object instance to exits. If you don't have an instance of an object, then instance variable defined for this object (in the class) won't exist either.
However, in your case, you can define the AT_ZHEADER and AT_ZITEMS attributes as static and it will be fine.
I urge to read about instance and static attributes/methods, for example this article: https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-us/abenclass_attributes.htm
regards,
Mateusz
2020 May 14 9:21 AM
| User | Count |
|---|---|
| 3 | |
| 2 | |
| 2 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 |