cmd_ei_api=>maintain_bapi to update kna1 table field (ICMSTAXPAY) - abap

I have a requirement to update this field ICMSTAXPAY in KNA1 table using my custom report. So, I tried using cmd_ei_api=>maintain_bapi to update the table. But once I run the program, that particular field is not updated and I don't get any error messages too.
My logic:
Read the KNA1 entries.
Edit the required field to my value.
Pass mandatory data to HEADER for update.
Pass my new KNA1 entries to CENTRAL_DATA.
Read data from table:
CALL METHOD cmd_ei_api_memory=>get_global_kna1
EXPORTING
iv_kunnr = <lfs_final>-kunnr
IMPORTING
es_kna1_old = ls_old.
Change the value of field:
ls_old-icmstaxpay = 9.
MOVE-CORRESPONDING ls_old TO ls_customer-central_data-central-data.
Assign header data:
ls_customer-header-object_instance-kunnr = <lfs_final>-kunnr.
ls_customer-header-object_task = 'U'.
Add all the above to the master data structure:
APPEND ls_customer TO lt_customers[].
ls_master_data-customers = lt_customers[].
Pass the data and update to table:
cmd_ei_api=>initialize( ).
LOOP AT lt_customers INTO ls_customer.
cmd_ei_api=>lock( iv_kunnr = ls_customer-header-object_instance-kunnr ).
ENDLOOP.
" Update Customer with CMD_EI_API
CALL METHOD cmd_ei_api=>maintain_bapi
EXPORTING
iv_test_run = space
is_master_data = ls_master_data
IMPORTING
es_message_defective = ls_message_defective.
IF ls_message_defective IS INITIAL.
BREAK-POINT.
COMMIT WORK.
ELSE.
BREAK-POINT.
ENDIF.
LOOP AT lt_customers INTO ls_customer.
cmd_ei_api=>unlock( iv_kunnr = ls_customer-header-object_instance-kunnr ) .
ENDLOOP.
When I debug, I can see that the entry that is being fetched for update is the old entry that is present in the current memory.
Please let me know if i am doing something wrong while passing the value to the table.

You need including DATAX with X for all fields that you need change.
DATA: ls_datax TYPE cmds_ei_vmd_central_data_xflag.
ls_datax-icmstaxpay = 'X'.
MOVE ls_datax TO ls_customer-central_data-central-datax.
And thanx for your question, helped me with find this methody :)

Related

Fill arbitrary column in dynamic itab?

I am currently trying to create a report with a dynamically created internal table (the number of columns can be different every time).
Is there a way how I can address the generated columns while filling the structure of the given table?
Here is the code I am working with:
FIELD-SYMBOLS: <fcat> TYPE lvc_s_fcat,
<fcat_aus> TYPE ANY TABLE.
IF so_datum-high <> ''.
DATA(lv_month_diff) = so_datum-high - so_datum-low.
ELSE.
DATA(lv_month) = so_datum-low.
ENDIF.
APPEND INITIAL LINE TO gt_fcat ASSIGNING <fcat>.
<fcat>-fieldname = 'MATNR'.
<fcat>-tabname = 'GZ_TABLE'.
<fcat>-ref_field = 'MATNR'.
<fcat>-ref_table = 'MAKT'.
APPEND INITIAL LINE TO gt_fcat ASSIGNING <fcat>.
<fcat>-fieldname = 'MAKTX'.
<fcat>-tabname = 'GZ_TABLE'.
<fcat>-ref_field = 'MAKTX'.
<fcat>-ref_table = 'MAKT'.
DATA(lv_counter) = 1.
DO 10 TIMES.
DATA(lv_fieldname_qt) = 'MOQ' && lv_counter.
DATA(lv_fieldname_fqt) = 'MFQ' && lv_counter.
lv_counter = lv_counter + 1.
APPEND INITIAL LINE TO gt_fcat ASSIGNING <fcat>.
<fcat>-fieldname = lv_fieldname_qt.
<fcat>-tabname = 'GZ_TABLE'.
<fcat>-ref_field = 'MNG01'.
<fcat>-ref_table = 'MDEZ'.
APPEND INITIAL LINE TO gt_fcat ASSIGNING <fcat>.
<fcat>-fieldname = lv_fieldname_fqt.
<fcat>-tabname = 'GZ_TABLE'.
<fcat>-ref_field = 'MNG01'.
<fcat>-ref_table = 'MDEZ'.
ENDDO.
CALL METHOD cl_alv_table_create=>create_dynamic_table
EXPORTING
it_fieldcatalog = gt_fcat
IMPORTING
ep_table = gz_table
EXCEPTIONS
generate_subpool_dir_full = 1
OTHERS = 2.
ASSIGN gz_table->* to <fcat_aus>.
Maybe one of you has an idea.
Thanks in advance!
Use the ASSIGN COMPONENT statement to access a structure component dynamically. Check the ABAP documentation (F1) for further details. You can specify the component by index or by field name.
Here is an example to complete Thomas answer (note that I don't explain how to create a table dynamically with CREATE DATA as it's not your question, here it's created statically with 2 components, I only explain how to fill an internal table by referring to it dynamically):
TYPES: BEGIN OF ty_line,
comp1 TYPE i,
text_component TYPE string,
END OF ty_line,
ty_itab TYPE STANDARD TABLE OF ty_line WITH DEFAULT KEY.
DATA r_itab TYPE REF TO DATA.
DATA r_line TYPE REF TO DATA.
FIELD-SYMBOLS <itab> TYPE STANDARD TABLE.
FIELD-SYMBOLS <line> TYPE ANY.
FIELD-SYMBOLS <component> TYPE ANY.
" create an internal table, here it's the static way, but you may also use CREATE DATA
" to create it dynamically
CREATE DATA r_itab TYPE ty_itab.
ASSIGN r_itab->* TO <itab>.
" now let's fill it dynamically, first define a line
CREATE DATA r_line LIKE LINE OF <itab>.
ASSIGN r_line->* TO <line>.
ASSIGN COMPONENT 1 OF <line> TO <component>. " access to COMP1 component
IF sy-subrc = 0.
<component> = 30.
ENDIF.
ASSIGN COMPONENT 'TEXT_COMPONENT' OF <line> TO <component>.
IF sy-subrc = 0.
<component> = 'text'.
ENDIF.
" now add the line
INSERT <line> INTO TABLE <itab>.
Note that it's possible to access the whole line with ASSIGN COMPONENT 0 ... (especially useful if the internal table has none component).
More information:
ASSIGN
->* (dereferencing operator)
CREATE DATA

I don't understand how READ TABLE inside LOOP works

In my code I need to iterate inside a loop, and for each iteration in the loop I have to fill in the data whose values ​​are different in certain cells.
Reading the sap documentation I have come to the conclusion that what I need is to use a read table to fill for each iteration into a working area that later I'll treat.
I have declarated the following tables:
it_sap with the content of a join from VBRK and VBRP tables
wa_sap as working area
it_ext with content from an another join from an external database
wa_ext as working area.
This is how my loop looks actually like:
LOOP AT it_sap INTO wa_sap.
wa_sap-tipo_documento = wa_sap-xblnr+2(1). " Linea
tiket = wa_sap-xblnr+9(7).
creationyear = wa_sap-fkdat+0(4).
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = tiket
IMPORTING
output = tiket.
CONCATENATE creationyear '/' wa_sap-vkorg wa_sap-xblnr+7(2) '/' tiket INTO wa_sap-codalb.
"CLEAR position.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_OUTPUT'
EXPORTING
input = wa_sap-posnr
IMPORTING
output = position.
READ TABLE it_ext INTO wa_ext
WITH KEY codalb = wa_ext-codalb
tipo_documento = wa_ext-tipo_documento.
IF sy-subrc = 0.
wa_sap-import_total = wa_ext-import_total.
wa_sap-import = wa_ext-import.
wa_sap-price = wa_ext-price.
wa_sap-price_total = wa_ext-price_total.
wa_sap-disccount = wa_ext-disccount.
wa_sap-quantity = wa_ext-quantity.
MODIFY it_sap FROM wa_sap.
IF wa_sap-importe_total <> wa_sap-netwr. "AND position = 1 .
APPEND wa_sap TO it_results.
ENDIF.
ENDIF.
ENDLOOP.
How does it work? I understand that by using the conditional sy-subrc = 0 I can see if the previous statement gives true or false but I don't quite understand how it works by using READ instead SELECT steament.
Thank you guys!
LOOP AT iterates over all rows of an internal table.
READ TABLE retrieves at most one row from an internal table.
sy-subrc provides you details about how well the previous statement worked. Its values differ with the statement. In case of READ TABLE, it tells you whether a row was found (= 0) or not (<> 0). The IF sy-subrc = 0 after your READ TABLE thus means "if you found such a row".
It's hard to understand what your code is supposed to do and whether it does that correctly without some helpful sample data. As József Szikszai points out in the comments to your question, the READ TABLE's conditions rely on wa_ext, which is never filled in your sample code, so at first glance this looks like it's not working at all or your sample does not include some initialisation code.

Map key-value to structure

I have a key-value internal table and want to fill an existing structure with it.
Example: 1st I get a key-value table that I create by reading data from two existing tables.
SELECT vals~attr_value, names~attr_name
FROM atst_attr AS vals
INNER JOIN tc_attr AS names
ON vals~tc_attr_id = names~tc_attr_id
WHERE vals~atst_id = #lv_atst_id
INTO TABLE #DATA(itab)
.
Now my itab looks like this:
itab:
name value
1. "field_a" "value_a"
2. "field_c" "value_c"
And my local structure (or workingarea as it is often called) is empty:
l_struc:
field_a: ""
field_b: ""
field_c: ""
Now I want to fill the structure, which is where I need help - I want the result to be:
l_struc:
field_a: "value_a"
field_b: ""
field_c: "value_c"
How can I automatically make the mapping from the name property to the name of the structure component happen and setting its value?
something like:
FIELD-SYMBOLS lv_field TYPE ANY.
LOOP AT itab
ASSIGNING FIELD-SYMBOL(<ls_itab>).
ASSIGN COMPONENT <ls_itab>-name
OF STRUCTURE l_struc
TO <lv_field>.
IF sy-subrc EQ 0.
<lv_field> = <ls_itab>-value.
ENDIF.
ENDLOOP.

Create dynamic ABAP internal table

On selection screen, the user needs to insert a table name, and I need to get first 3 fields from that table and display them in an ALV for the output. What I understand from reading tutorials is that I need to call method cl_alv_table_create=>create_dynamic_table, but I don't know how to create the fieldcatalog.
DATA: t_newtable TYPE REF TO data,
t_fldcat TYPE lvc_t_fcat,
CALL METHOD cl_alv_table_create=>create_dynamic_table
EXPORTING
it_fieldcatalog = t_fldcat
IMPORTING
ep_table = t_newtable.
I assume that the table name which user enters is a data dictionary table (like SFLIGHT). If yes, then you can generate the field catalog as follows.
data : it_tabdescr type abap_compdescr_tab,
wa_tabdescr type abap_compdescr.
data : ref_table_descr type ref to cl_abap_structdescr.
ref_table_descr ?= cl_abap_typedescr=>describe_by_name( p_table ).
it_tabdescr[] = ref_table_descr->components[].
loop at it_tabdescr into wa_tabdescr.
clear wa_fieldcat.
wa_fieldcat-fieldname = wa_tabdescr-name .
wa_fieldcat-datatype = wa_tabdescr-type_kind.
wa_fieldcat-inttype = wa_tabdescr-type_kind.
wa_fieldcat-intlen = wa_tabdescr-length.
wa_fieldcat-decimals = wa_tabdescr-decimals.
append wa_fieldcat to it_fieldcat.
endloop.
Here, "p_table" is the selection screen parameter containing the table
name.

Disable Column in VA01

I have a requirement where I need to disable the full column in Sales Order Line item. Fields are VBAP-ARKTX and VBAP-KDMAT.
I've found the way to disable columns with data in them, but not the whole column.
I used USEREXIT_FIELD_MODIFICATION to achieve this using the following code;
IF sy-TCODE = 'VA02'.
IF screen-name = 'VBAP-KDMAT' .
screen-INPUT = 0.
modify screen.
ENDIF.
ENDIF.
Is there a way to disable the whole column?
Adjusting table control which contains items is the easiest and the most recommended way. It can be done for single user or for group of users.
Otherwise, try to create a screen variant in SHD0. It allows easily hide any column of any table and any field on the screen.
The specific problem I faced was how to disable two fields, but let standard mapped data to be displayed in them.
To cater this requirement I used the following;
Include: MV45AFZZ
User Exit Name: USEREXIT_FIELD_MODIFICATION
Enhancement Name: -Any name you want-
I created an Enhancement and wrote the following code;
"Specify the condition
IF VBAK-VKORG = '1234' AND ( sy-TCODE = 'VA02' OR sy-TCODE = 'VA01' ) AND ( screen-name = 'VBAP-KDMAT' OR screen-name = 'VBAP-ARKTX' ).
screen-input = 0."disable input
MODIFY SCREEN.
DATA: i_tab_mara TYPE TABLE OF MARA WITH HEADER LINE.
DATA: l_maktx TYPE MAKT-MAKTX.
DATA: WA_MARA LIKE LINE OF i_tab_mara.
DATA: i_tab_vbap TYPE TABLE OF VBAP WITH HEADER LINE.
DATA: wa_vbap LIKE LINE OF i_tab_vbap.
IF sy-TCODE = 'VA01' .
SELECT SINGLE * from MARA INTO WA_MARA WHERE MATNR eq VBAP-MATNR.
SELECT MAKTX FROM MAKT INTO l_maktx WHERE MATNR eq VBAP-MATNR.
ENDSELECT.
VBAP-KDMAT = WA_MARA-KDMAT.
VBAP-ARKTX = l_maktx.
MODIFY SCREEN.
ELSEIF sy-TCODE = 'VA02' .
SELECT SINGLE * FROM VBAP INTO WA_VBAP WHERE VBELN eq VBAK-VBELN AND POSNR eq VBAP-POSNR.
IF WA_VBAP-ARKTX eq ''." Check if the fileds are empty, otherwise old data is overwritten
SELECT MAKTX FROM MAKT INTO l_maktx WHERE MATNR eq VBAP-MATNR.
ENDSELECT.
VBAP-ARKTX = l_maktx.
MODIFY SCREEN.
ENDIF.
IF WA_VBAP-KDMAT eq ''." Check if the fileds are empty, otherwise old data is overwritten
SELECT SINGLE * from MARA INTO WA_MARA WHERE MATNR eq VBAP-MATNR.
VBAP-KDMAT = WA_MARA-KDMAT.
MODIFY SCREEN.
ENDIF.
ENDIF.
ENDIF.
There is one thing, that You can do in the dynpro-designer. There You can modify the sap-standard-dynpro as a dynpro-modification.
Nevertheless, this might be overwritten with the next release. Is this also an option for You ?