Enterprise Resource Planning Blogs by Members
Gain new perspectives and knowledge about enterprise resource planning in blog posts from community members. Share your own comments and ERP insights today!
cancel
Showing results for 
Search instead for 
Did you mean: 
MarekTurczynski
Contributor

Introduction


In first part of the Own DMEE Tree Type series I presented how to create own DMEE Tree Type and set up a new tree of own type.

Second part is concerned on triggering the own DME Tree via custom program and showing which standard functions can be used for that.

The definition created for usage of this blog will be an extraction of invoice data – header, lines and deliveries.

Each section of this post will show which part of the report is called and which DME functions are used. At the end whole report with all includes is presented so you can easily download it and implement in your system.

You can download the whole code from Github for free now!

You can use it as template for your solutions. It supports both DMEE and DMEEX (available in S/4 HANA only) tools.

How does it work


To run DMEE basically 3 function modules are needed:



















Function Module What it does
DMEE_START starts DME Engine and provides back sort fields
DMEE_PUT_ITEM adds item into opened DME Engine
DMEE_END closes DME and fills in the DME output table

There are however other useful functions that are available in standard.

When triggering DMEE start an output table needs to be passed ( parameter ‘file_output’) this is filled in internally in DMEE Engine every time DMEE_PUT_ITEM is used. Do not be afraid that you do not see any line in output table after that FM is called – it is stored as global data (it_output_file) of function pool DMEE2.

After calling DMEE_END function the output table is delivered with parameter ‘file_output’.

What else to consider


Besides these 3 function modules also others should be considered:















Function Module What it does
DMEE_NEW_FILE Evaluates if, based on the DMEE Tree key, a new file should be created. If returned parameter ‘xnew_file’ is set then current DME processing should be closed and new started
TAX_REP_SORT_DMEE_TABLE If output type is based on simple table (not hierarchical like invoice to line and to delivery) then this FM can be used to sort DMEE data before calling DMEE_PUT_ITEM. It makes sense to use it when all key fields are without sorting – then calling application should be provide sorted data already

Downloading / saving of file


After file is generated it can be displayed/ downloaded to local disc / saved on application server using:























Function Module What it does
DMEE_HANDLE_XML_DOC_PC Displays XML file generated by DMEE or lets saving it as local file
FI_PAYM_FILE_OPEN Opens dataset where logical file name will be set as FI_DME_CREATE_FILE (as introduced by OSS Note 1865372)
FI_PAYM_FILE_WRITE Saves DME file output to dataset
FI_FILE_CLOSE Closes dataset

In case of downloading a non-XML file there is no designated standard FM but it can be archived by simply looping over output lines and saving as TXT file.

Report


In the below-presented report data of invoices are extracted and displayed or downloaded.

Report output data in the same way as XML file:



Data will be presented as ALV Grid in hierarchical form using class CL_XX_ALV_TRANSFORMER and CL_XX_ALV_DISPLAY.

These classes are not widely known so I took this opportunity to show how to create hierarchical ALV Grid with their usage (normally you would use CL_SALV_TREE or CL_GUI_ALV_TREE).

If you do not have these classes in your system please implement OSS notes 2239078 (announcement note 2412784 - Shared Application and Business Services – Announcement) and all related ones (+ make cleanup afterwards as the implementation of these notes will most probably end up in syntax errors ).

If you cannot do that, then simply change the part of ALV coding to simple display of header data using SALV to see any output.

Report Structure


Report is written in the way to display XML/ flat or download it showing an ALV at the end.

Report consists of 4 includes:



























Include What it contains
Z_DMEE_INVOICE_EXTRACT_LCL00 Top with class containing constants and commonly used data definitions
Z_DMEE_INVOICE_EXTRACT_SSC Selection screen
Z_DMEE_INVOICE_EXTRACT_LCL01 Local class LCL_SCREEN for processing of selection screen and saving its variables as class attributes
Z_DMEE_INVOICE_EXTRACT_LCL02 ALV processing routines in local class LCL_ALV_DISPLAY
Z_DMEE_INVOICE_EXTRACT_LCL03 Main report handler stored in class LCL_REPORT

REPORT z_dmee_invoice_extract.

"Custom DMEE Tree Type handling
INCLUDE z_dmee_invoice_extract_lcl00."Tools and data types
INCLUDE z_dmee_invoice_extract_ssc. "Selection Screen
INCLUDE z_dmee_invoice_extract_lcl01."Screen processing class
INCLUDE z_dmee_invoice_extract_lcl02."ALV processing
INCLUDE z_dmee_invoice_extract_lcl03."Main report processing

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_vari.
lcl_screen=>call_f4( lcl_tools=>c_f4_var ).

START-OF-SELECTION.
lcl_screen=>get_instance( )->initialize( ).
lcl_report=>get_instance( )->process( ).

Method process of class LCL_REPORT controls whole processing of report in submethods:
  METHOD process.

select_data( ). "Data selection
generate_dmee( ). "Handling of all DMEE functions
display_alv( ). "Call LCL_ALV_DISPLAY class

ENDMETHOD.

SELECT_DATA --> Selects invoices/ lines + deliveries

GENERATE_DMEE --> For data selected opens/ closes DME Engine Tool

DISPLAY_ALV --> calls method SETUP_ALV of class LCL_ALV_DISPLAY

In next part shortly methods will be presented and at the end whole report with example will be shown.

Data selection using SELECT_DATA method


It calls 3 methods which do actual data selection:



















Method What it does
SELECT_INVOCES selects invoice headers from VBRK – values are saved in global attribute MT_INVOICE_HEADER
SELECT_INVOICE_LINES selects invoice lines from VBRP – values are saved in global attribute MT_INVOICE_LINES
SELECT_DELIVERIES selects delivery data from LIKP and LIPS – values are saved in global attribute MT_INVOICE_DELIVERIES

As stated in first part of own DMEE series the output of DME is generated out of 3 structures:

  • ZDMEE_INVOICE_HEADER represented in program by attribute MT_INVOICE_HEADER of class LCL_REPORT

  • ZDMEE_INVOICE_LINE represented in program by attribute MT_INVOICE_LINES of class LCL_REPORT

  • ZDMEE_DELIVERY_LINE represented in program by attribute MT_INVOICE_DELIVERIES of class LCL_REPORT


 

DMEE handling via GENERATE_DMEE method


This method processes the data selected in following way:

For each invoice header (MT_INVOICE_HEADER) evaluate if DMEE should be started using method START_DMEE_ENGINE.

Then add item to DMEE for each processed line item (MT_INVOICE_LINES) passing invoice header, invoice line and optionally delivery information. All that information is passed to method ADD_DMEE_ITEM where importing parameters are mapped to communication structure.

At the end, once all invoices have been processed, DME file is closed using CLOSE_ENGINE method.

Display (controlled by selection screen parameter) or download of file is handled in DOWNLOAD_FILE method.
METHOD generate_dmee.

"for each invoice process DMEE
LOOP AT mt_invoice_header ASSIGNING FIELD-SYMBOL(<l_s_invoice_header>).

"start DME engine for invoice or keep it running if DME is already running
start_dmee_engine( <l_s_invoice_header> ).

"loop over each invoice item for currently processed invoice
LOOP AT mt_invoice_lines ASSIGNING FIELD-SYMBOL(<l_s_invoice_line>) WHERE vbeln = <l_s_invoice_header>-vbeln.

"loop over each delivery connected to invoice line or simply output invoice line if no delivery exists
IF line_exists( mt_invoice_deliveries[ vbeln = <l_s_invoice_line>-vgbel posnr = <l_s_invoice_line>-vgpos ] ).
LOOP AT mt_invoice_deliveries ASSIGNING FIELD-SYMBOL(<l_s_invoice_delivery>) WHERE vbeln = <l_s_invoice_line>-vgbel.
"delivery-based-billing
add_dmee_item( EXPORTING i_v_invoice_header = <l_s_invoice_header>
i_v_invoice_line = <l_s_invoice_line>
i_v_invoice_delivery = <l_s_invoice_delivery> ).
ENDLOOP.
ELSE.
"order-based-billing
add_dmee_item( EXPORTING i_v_invoice_header = <l_s_invoice_header>
i_v_invoice_line = <l_s_invoice_line> ).
ENDIF.

ENDLOOP.
ENDLOOP.

"at the very end close DME engine
close_engine( ).
"and process display or download
download_file( ).

ENDMETHOD.

Starting DMEE creation via START_DMEE_ENGINE method


To start DME engine function module DMEE_START needs to be called. It controls opening an writing to one DMEE file.

Important part here is that, based on key fields definition in DMEE Tree, for one set of data multiple files can be created. This can be archived by settings in Levels + Sort Key Fields in DMEE Tree.

As a consequence it must be evaluated if DMEE was already started and if a new start is needed.

Therefore global attribute was introduced: MV_DMEE_FIRST_STARTED which is set once DMEE Engine is started for the first time.

A local parameter L_V_NEW_FILE_NEEDED returned by method CHECK_IF_NEW_FILE_NEEDED is populated if DMEE_NEW_FILE returns information that new file is needed.

When calling function DMEE_START information about Tree Type / Tree ID needs to be passed.

It is also required to pass the communication structure but there not all information needs to be passed (like in example where only invoice header data is provided).

Empty MT_DMEE_OUTPUT which holds output generated by DME needs to be provided as well.

Additionally global additional parameters available in global structure MS_DMEE_ADDITIONAL_DATA (representing ZDMEE_ADD_PARAMS from DMEE Tree Type settings).

Starting of DME also returns DMEE Tree sort fields which can be used for sorting of data passed to DMEE if it should happen outside of DMEE Engine.
METHOD start_dmee_engine.
DATA: l_s_dmee_item TYPE zdmee_invoice_data,
l_t_dmee_sort_fields TYPE STANDARD TABLE OF dmee_tree_sort.

l_s_dmee_item-zdmee_invoice_header = i_s_invoice.

IF mv_dmee_first_started EQ abap_true.
DATA(l_v_new_file_needed) = check_if_new_file_needed( l_s_dmee_item ).
ENDIF.

IF mv_dmee_first_started IS INITIAL
OR l_v_new_file_needed IS NOT INITIAL.

CALL FUNCTION 'DMEE_START'
EXPORTING
i_tree_type = lcl_tools=>c_dmee_tree_type
i_tree_id = m_o_screen->mv_dmee_tree
item = l_s_dmee_item
param = m_o_screen->ms_dmee_additional_data
* uparam = i_format_params
TABLES
file_output = mt_dmee_output
sort_fields = l_t_dmee_sort_fields.

IF mv_dmee_first_started IS INITIAL.
mv_dmee_first_started = abap_true.
ENDIF.
ENDIF.

ENDMETHOD.

As described before method CHECK_IF_NEW_FILE_NEEDED is calling DMEE_NEW_FILE function module so that DME Engine can evaluate if new file is needed or not.
  METHOD check_if_new_file_needed.

CALL FUNCTION 'DMEE_NEW_FILE'
EXPORTING
item = i_s_dmee_data
CHANGING
xnew_file = r_v_new_file_needed.

IF r_v_new_file_needed IS NOT INITIAL.

close_engine( ).
download_file( ).

ENDIF.

ENDMETHOD.

If DMEE determined that new file is needed then currently processed file needs to be closed / downloaded/ saved to application server.

Add DMEE line via ADD_DMEE_ITEM method


After whole communication structure is filled with data ( at least invoice header / line item + optionally delivery information) it can be passed to DME Engine to be added to file output.
  METHOD add_dmee_item.
DATA: l_s_dmee_item TYPE zdmee_invoice_data.

l_s_dmee_item-zdmee_invoice_header = i_v_invoice_header.
l_s_dmee_item-zdmee_invoice_line = i_v_invoice_line.
l_s_dmee_item-zdmee_delivery_line = i_v_invoice_delivery.

CALL FUNCTION 'DMEE_PUT_ITEM'
EXPORTING
item = l_s_dmee_item
param = m_o_screen->ms_dmee_additional_data
* uparam = params
TABLES
* item_tab = tab_item
file_output = mt_dmee_output.

ENDMETHOD.

Function Module DMEE_PUT_ITEM passed the data to DMEE internal table processing. Do not be afraid that after it is called table file_output is empty – it is meant to be so. Only after closing DMEE whole output data will be visible.

Close DMEE file via CLOSE_ENGINE method


At the moment when DMEE file should be finished (also if a new one should be opened) function module DMEE_END should be called. This is happening here. It outputs all possible errors which can be listed but generally if something is wrong in DMEE it results in two types or errors - at activation of DMEE or a dump in processing of it.
  METHOD close_engine.
DATA: l_t_error_output TYPE STANDARD TABLE OF fimsg.
DATA: l_t_fpm_fields TYPE STANDARD TABLE OF dmee_fpm_fields.

CALL FUNCTION 'DMEE_END'
TABLES
file_output = mt_dmee_output
error_output = l_t_error_output
fpm_fields = l_t_fpm_fields.

ENDMETHOD.

Download/ Display DMEE file via DOWNLOAD_FILE method


Preparation for download vary depending if output file is meant to be XML file or Flat File.
  METHOD download_file.

CASE m_o_screen->mv_dmee_is_xml.
WHEN abap_true.
download_xml_file( ).
WHEN abap_false.
download_flat_file( ).
WHEN OTHERS.
ENDCASE.

ENDMETHOD.

Therefore this method was split into two different ones:

Download / Display XML file


Handling of XML files is quite easy because there is standard function DMEE_HANDLE_XML_DOC_PC which needs to be called.

In our case method DOWNLOAD_XML_FILE checks if file should be displayed only (then no popup for file name comes up) or downloaded.

At the end XML_FILE_START_DOWNLOAD method is called where the FM mentioned above is called.
METHOD download_xml_file.
CONSTANTS: l_c_xml TYPE string VALUE 'XML'.
DATA:
l_v_filename TYPE string,
l_v_fullpath TYPE string,
l_v_result TYPE i,
l_v_path TYPE string.

IF m_o_screen->mv_display_only EQ abap_true.

xml_file_start_download( EXPORTING i_v_display_only = abap_true
i_v_filename = l_v_filename ).
ELSE.
CALL METHOD cl_gui_frontend_services=>file_save_dialog
EXPORTING
default_extension = l_c_xml
CHANGING
filename = l_v_filename
path = l_v_path
fullpath = l_v_fullpath
user_action = l_v_result.

IF l_v_result IS INITIAL.

xml_file_start_download( EXPORTING i_v_display_only = abap_false
i_v_filename = l_v_filename ).

ENDIF.
ENDIF.

ENDMETHOD.

Only a file name needs to be provided (in case it should be displayed only an empty variable can be passed) + additionally information if it should be displayed only  (parameter I_DISPLAY)  or saved (parameter I_SAVE). Combining display and save will enable saving from XML display.
  METHOD xml_file_start_download.

CALL FUNCTION 'DMEE_HANDLE_XML_DOC_PC'
EXPORTING
i_filename = i_v_filename
i_save = COND xfeld( WHEN i_v_display_only EQ abap_true THEN space
ELSE abap_true )
i_display = i_v_display_only.

ENDMETHOD.

Download / Display Flat file


Flat files do not have dedicated standard DMEE function module and are handled as normal TXT files.

The download just needs to build a table of string type and move the DMEE output there. In this example I have programmed it to be an TXT file but it can easily be a CSV or any other as well.
METHOD download_flat_file.
CONSTANTS c_file_txt TYPE string VALUE 'TXT'.

DATA:
l_v_filename TYPE string,
l_v_path TYPE string,
l_v_fullpath TYPE string,
l_v_result TYPE i.
DATA: l_v_codepage TYPE cpcodepage.
DATA: l_t_file_data TYPE STANDARD TABLE OF string WITH EMPTY KEY.

IF m_o_screen->mv_display_only IS NOT INITIAL.

"display only
CALL FUNCTION 'POPUP_WITH_TABLE_DISPLAY'
EXPORTING
endpos_col = 30
endpos_row = lines( mt_dmee_output )
startpos_col = 10
startpos_row = 1
titletext = text-004
* IMPORTING
* choise = l_v_choice
TABLES
valuetab = mt_dmee_output
EXCEPTIONS
break_off = 1
OTHERS = 2.

ELSE.
"download
LOOP AT mt_dmee_output ASSIGNING FIELD-SYMBOL(<l_s_dme_line>).

APPEND <l_s_dme_line>-line TO l_t_file_data.

ENDLOOP.

"get default encoding by language
CALL FUNCTION 'NLS_GET_FRONTEND_CP'
EXPORTING
langu = CONV spras( sy-langu ) ##OPERATOR
* FETYPE = 'MS'
IMPORTING
frontend_codepage = l_v_codepage
EXCEPTIONS
illegal_syst_codepage = 1
no_frontend_cp_found = 2
internal_or_db_error = 3
OTHERS = 4.
IF sy-subrc NE 0.
l_v_codepage = '4110'.
ENDIF.
CONDENSE l_v_codepage NO-GAPS.

CALL METHOD cl_gui_frontend_services=>file_save_dialog
EXPORTING
default_extension = CONV string( c_file_txt )
CHANGING
filename = l_v_filename
path = l_v_path
fullpath = l_v_fullpath
user_action = l_v_result.

IF l_v_result IS INITIAL.

CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
filename = l_v_filename
codepage = CONV abap_encoding( l_v_codepage )
TABLES
data_tab = l_t_file_data
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ELSE.
MESSAGE i427(fr) WITH l_v_filename.
ENDIF.
ENDIF.

ENDIF.
ENDMETHOD.

This part concludes the DMEE handling. In next part output is shortly presented as well as whole report in a ready-to-download format.

ALV Creation using CL_XX_ALV_TRANSFORMER


Data selected by report will be presented in form of a hierarchical ALV Grid.

Class LCL_ALV_DISPLAY is called from main report passing the data:
  METHOD display_alv.

NEW lcl_alv_display( i_t_invoice_headers = mt_invoice_header
i_t_invoice_lines = mt_invoice_lines
i_t_invoice_deliveries = mt_invoice_deliveries )->setup_alv( ).

ENDMETHOD.

Method SETUP_ALV is split into 2 submethods where SETUP_ALV_NODES creates the DMEE-like output and the DISPLAY simply displays it.
  METHOD setup_alv.

setup_alv_nodes( ).
display( ).

ENDMETHOD.

DMEE-like ALV output: Nodes setup


With setup of nodes we want to archive DMEE-like display of data to be able to easily compare the nodes of XML file with ALV output.

This can be archived using methods of interface IF_XX_ALV_TRANSFORMER or via class CL_XX_ALV_TRANSFORMER.

Method ADD_VIEW controls each view which can be setup as:

  • Header

  • Tree Folder

  • Simple tree node


The expected output is:

For each invoice a folder needs to be created.

If invoice line has a delivery assigned it must be created as a folder that is nested under its invoice folder. If invoice line has no delivery assigned then it must be output as simple tree node.

Each delivery assigned to invoice line must be presented as simple tree node.

Controlling if node is a folder or tree is done using parameters:

  • IV_IS_TREE_FOLDER

  • IV_IS_TREE


Setting both at the same time will work out in an error so choose only one.

Each node/ folder will have own internal table showing data which is stored in it.

Transforming the concept from paper to code gives following output:
 METHOD setup_alv_nodes.
DATA: l_v_header_title TYPE sytitle.
DATA: l_v_title TYPE char30.

l_v_header_title = text-001.

"inform user what is happening now
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
text = text-i01.

TRY.
"add single invoice ALV header
mo_alv_transformer->add_alv_view( iv_is_header = abap_true
iv_header_title = l_v_header_title ).

"Folder for each invoice
LOOP AT mt_headers ASSIGNING FIELD-SYMBOL(<l_s_invoice_header>).
WRITE <l_s_invoice_header>-vbeln TO l_v_title.

DATA(l_t_headers_alv) = VALUE lcl_tools=>tt_invoice_header_alv( ( <l_s_invoice_header> ) ).

mo_alv_transformer->add_alv_view( iv_structure_name = lcl_tools=>c_structure_header
iv_default_variant = m_o_screen->mv_layout
it_outtab = l_t_headers_alv
iv_is_tree_folder = abap_true
iv_tree_folder_title = l_v_title ).

LOOP AT mt_lines ASSIGNING FIELD-SYMBOL(<l_s_invoice_line>) WHERE vbeln = <l_s_invoice_header>-vbeln.

DATA(l_t_lines_alv) = VALUE lcl_tools=>tt_invoice_lines_alv( ( <l_s_invoice_line> ) ).

l_v_title = |{ <l_s_invoice_line>-posnr ALPHA = OUT }|.

"If delivery exists for a line - make a folder
"If not - just output items as subnodes
IF line_exists( mt_deliveries[ vbeln = <l_s_invoice_line>-vgbel ] ).
DATA(l_v_delivery_exists) = abap_true.
ELSE.
CLEAR l_v_delivery_exists.
ENDIF.

mo_alv_transformer->add_alv_view( iv_structure_name = lcl_tools=>c_structure_line
it_outtab = l_t_lines_alv
iv_is_tree_folder = COND xfeld( WHEN l_v_delivery_exists EQ abap_true THEN abap_true
ELSE abap_false )
iv_tree_folder_title = COND char30( WHEN l_v_delivery_exists EQ abap_true THEN l_v_title
ELSE space )
iv_is_tree = COND xfeld( WHEN l_v_delivery_exists EQ abap_true THEN abap_false
ELSE abap_true )
iv_tree_title = COND char30( WHEN l_v_delivery_exists EQ abap_true THEN space
ELSE l_v_title )
iv_tree_level = COND int2( WHEN l_v_delivery_exists EQ abap_true THEN 1
ELSE 0 )
iv_is_tabstrip = abap_true
).

LOOP AT mt_deliveries ASSIGNING FIELD-SYMBOL(<l_s_invoice_delivery>) WHERE vbeln = <l_s_invoice_line>-vgbel AND posnr = <l_s_invoice_line>-vgpos.

DATA(l_t_deliveries_alv) = VALUE lcl_tools=>tt_invoice_deliveries_alv( ( <l_s_invoice_delivery> ) ).

l_v_title = |{ <l_s_invoice_delivery>-vbeln ALPHA = OUT }{ <l_s_invoice_delivery>-posnr ALPHA = OUT }|.

"If deliveries exist - output them as subnodes of items
mo_alv_transformer->add_alv_view( iv_structure_name = lcl_tools=>c_structure_delivery
it_outtab = l_t_deliveries_alv
iv_tree_title = l_v_title
iv_is_tree = abap_true
iv_tree_level = 1 ).

ENDLOOP.

ENDLOOP.
ENDLOOP.

CATCH cx_xx_shared_exception. "#EC NO_HANDLER
ENDTRY.

ENDMETHOD.

Once nodes are setup ALV just needs to be run using class CL_XX_ALV_DISPLAY
  METHOD display.

TRY .
"Adding of this class as ALV transformer module
mo_alv_display->add_alv_transformer( mo_alv_transformer ).

"Displays ALV
mo_alv_display->display_alv( ).

CATCH cx_xx_shared_exception. "#EC NO_HANDLER
ENDTRY.

ENDMETHOD.

Example of usage


For demonstration purposes I have created report Z_DMEE_INVOICE_EXTRACT that comprises all classes mentioned above.

I prepared 3 invoices with deliver and without delivery to present data in XML and in ALV:



As you see DMEE Tree Type is not available on selection screen but it is defined as NO-DISPLAY parameter with default value ‘ZZIV’. The great thing is that it is enough for Search Help for DMEE Tree to be restricted only to trees that are created under this type!

I let ‘Display Only’ marked as I first wanted to present the XML and do not need to download it.

Running report produces first an XML view and as expected there are 3 headers because of sorting in my DMEE Tree type that tells to generate one Header for each invoice.



Expanded it shows each line as desired:



Creator is as well filled in but just cut out in screenshot.

In DMEE Tree there was a condition that ‘Delivery’ XML node should not be output if the Delivery number is empty – so for sales-order-based billing this node is not expected and exactly this is output in XML:



Next screen after going through XML will present report output in hierarchy based on DME:



On the left side hierarchy of invoices is visible:



And on the right side the data of each line is visible for each hierarchy node which was selected:



That would be it in case of own DMEE creation – I hope you enjoyed it and see the potential in this solution to get rid of unnecessary mapping tables / mapping in ABAP which can simply be replaced by any mapping done in DMEE.

Full report code


For those who want to try out the whole solution and see how it works here is the full report code ready to copy and upload to SAP. Please note that some part of the code is written in ABAP 7.4 so if you get syntax errors then just change this parts of coding to normal data declaration.
REPORT z_dmee_invoice_extract.

"Custom DMEE Tree Type handling
INCLUDE z_dmee_invoice_extract_lcl00."Tools and data types
INCLUDE z_dmee_invoice_extract_ssc. "Selection Screen
INCLUDE z_dmee_invoice_extract_lcl01."Screen processing class
INCLUDE z_dmee_invoice_extract_lcl02."ALV processing
INCLUDE z_dmee_invoice_extract_lcl03."Main report processing

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_vari.
lcl_screen=>call_f4( lcl_tools=>c_f4_var ).

START-OF-SELECTION.
lcl_screen=>get_instance( )->initialize( ).
lcl_report=>get_instance( )->process( ).

Include Z_DMEE_INVOICE_EXTRACT_LCL00:
CLASS lcl_tools DEFINITION FINAL ABSTRACT.

PUBLIC SECTION.

"main processing types
TYPES: tt_invoice_header TYPE SORTED TABLE OF zdmee_invoice_header WITH UNIQUE KEY primary_key COMPONENTS vbeln.
TYPES: tt_invoice_lines TYPE SORTED TABLE OF zdmee_invoice_line WITH UNIQUE KEY primary_key COMPONENTS vbeln posnr.
TYPES: tt_invoice_deliveries TYPE SORTED TABLE OF zdmee_delivery_line WITH UNIQUE KEY primary_key COMPONENTS vbeln posnr.

"ALV display is using only standard tables so need to convert data before adding to ALV
TYPES: tt_invoice_header_alv TYPE STANDARD TABLE OF zdmee_invoice_header WITH KEY primary_key COMPONENTS vbeln.
TYPES: tt_invoice_lines_alv TYPE STANDARD TABLE OF zdmee_invoice_line WITH KEY primary_key COMPONENTS vbeln posnr.
TYPES: tt_invoice_deliveries_alv TYPE STANDARD TABLE OF zdmee_delivery_line WITH KEY primary_key COMPONENTS vbeln posnr.

CONSTANTS: c_structure_header TYPE tabname VALUE 'ZDMEE_INVOICE_HEADER'.
CONSTANTS: c_structure_line TYPE tabname VALUE 'ZDMEE_INVOICE_LINE'.
CONSTANTS: c_structure_delivery TYPE tabname VALUE 'ZDMEE_DELIVERY_LINE'.

CONSTANTS c_f4_var TYPE fieldname VALUE 'VARIANT'.
CONSTANTS: c_dmee_tree_type TYPE dmee_treetype VALUE 'ZZIV'.
CONSTANTS: c_act_disp TYPE c LENGTH 2 VALUE '03' ##NO_TEXT.

"for selection screen options
CLASS-DATA: l_v_sccr_sdbil TYPE vbrk-vbeln.
CLASS-DATA: l_v_sccr_sddate TYPE fkdat.
CLASS-DATA: l_v_sccr_sdtype TYPE rv60a-fkart.
CLASS-DATA: l_v_sccr_sdorg TYPE vkorg.

ENDCLASS.

Include Z_DMEE_INVOICE_EXTRACT_SSC:
SELECTION-SCREEN BEGIN OF BLOCK b01 WITH FRAME TITLE text-fb1.

PARAMETERS: p_comp TYPE bukrs OBLIGATORY DEFAULT '1000'.

SELECT-OPTIONS: so_sddoc FOR lcl_tools=>l_v_sccr_sdbil.
SELECT-OPTIONS: so_sddat FOR lcl_tools=>l_v_sccr_sddate.

SELECTION-SCREEN END OF BLOCK b01.

SELECTION-SCREEN BEGIN OF BLOCK b02 WITH FRAME TITLE text-fb2.

SELECT-OPTIONS: so_sdorg FOR lcl_tools=>l_v_sccr_sdorg.
SELECT-OPTIONS: so_sdtyp FOR lcl_tools=>l_v_sccr_sdtype.

SELECTION-SCREEN END OF BLOCK b02.

SELECTION-SCREEN BEGIN OF BLOCK b03 WITH FRAME TITLE text-fb3.

PARAMETERS: p_disp TYPE xtest DEFAULT 'X'.
PARAMETERS: tree_typ TYPE dmee_tree_head-tree_type DEFAULT lcl_tools=>c_dmee_tree_type NO-DISPLAY.
PARAMETERS: p_tree TYPE dmee_tree_head-tree_id OBLIGATORY.
PARAMETERS: p_vari TYPE slis_vari.

SELECTION-SCREEN END OF BLOCK b03.

Include Z_DMEE_INVOICE_EXTRACT_LCL01:
CLASS lcl_screen DEFINITION FINAL CREATE PRIVATE.

PUBLIC SECTION.

CLASS-METHODS get_instance RETURNING VALUE(r_o_screen) TYPE REF TO lcl_screen.
CLASS-METHODS call_f4 IMPORTING i_v_field TYPE fieldname.
CLASS-METHODS ask_for_variants.
METHODS: initialize. "saves all selection-screen parameters for internal processing

CLASS-DATA: mt_billing_docs TYPE RANGE OF vbeln_vf.
CLASS-DATA: mt_billing_date TYPE RANGE OF fkdat.
CLASS-DATA: mt_billing_types TYPE RANGE OF fkart.
CLASS-DATA: mt_sales_org TYPE RANGE OF vkorg.
CLASS-DATA: mv_dmee_tree TYPE dmee_treeid.
CLASS-DATA: ms_dmee_additional_data TYPE zdmee_invoice_add_data.
CLASS-DATA: mv_company_code TYPE bukrs.
CLASS-DATA: mv_dmee_is_xml TYPE xfeld.
CLASS-DATA: mv_display_only TYPE xfeld.
CLASS-DATA: mv_layout TYPE char12.

PRIVATE SECTION.
CLASS-DATA m_o_screen TYPE REF TO lcl_screen.

METHODS auth_company_code_single IMPORTING VALUE(i_v_company_code) TYPE bukrs
RETURNING VALUE(r_v_authority_ok) TYPE boolean.
METHODS get_additional_dme_params RETURNING VALUE(r_s_additional_data) TYPE zdmee_invoice_add_data.
METHODS check_dmee_format RETURNING VALUE(r_v_is_xml) TYPE xfeld.

ENDCLASS.

CLASS lcl_screen IMPLEMENTATION.

METHOD get_instance.

IF m_o_screen IS INITIAL.
CREATE OBJECT m_o_screen.
ENDIF.
r_o_screen = m_o_screen.

ENDMETHOD.

METHOD call_f4.

CASE i_v_field.
WHEN lcl_tools=>c_f4_var.

ask_for_variants( ).

WHEN OTHERS.
"do nothing
ENDCASE.

ENDMETHOD.

METHOD ask_for_variants.
DATA: l_v_exit TYPE c LENGTH 1.
DATA: l_s_layout TYPE disvariant.

"in case of ALV used in this report it will always be structure name + report name
l_s_layout-report = |{ lcl_tools=>c_structure_header }{ sy-repid }|.
l_s_layout-username = sy-uname.
CALL FUNCTION 'LT_F4_FOR_VARIANTS'
EXPORTING
is_variant = l_s_layout
i_display_via_grid = 'X'
IMPORTING
e_exit = l_v_exit
es_variant = l_s_layout
EXCEPTIONS
not_found = 1
OTHERS = 2.
IF sy-subrc NE 0.
MESSAGE text-002 TYPE 'S'. "no layout found
ELSE.
IF l_v_exit IS INITIAL.
p_vari = l_s_layout-variant.
ENDIF.
ENDIF.

ENDMETHOD.

METHOD initialize.

IF auth_company_code_single( p_comp ) NE abap_true.
MESSAGE e060(f0) WITH p_comp.
ENDIF.
me->mv_company_code = p_comp.
me->mt_billing_docs = so_sddoc[].
me->mt_billing_date = so_sddat[].
me->mt_billing_types = so_sdtyp[].
me->mt_sales_org = so_sdorg[].
me->mv_dmee_tree = p_tree.
me->mv_display_only = p_disp.
me->mv_layout = p_vari.
me->ms_dmee_additional_data = get_additional_dme_params( ).
me->mv_dmee_is_xml = check_dmee_format( ).

ENDMETHOD.

METHOD auth_company_code_single.

AUTHORITY-CHECK OBJECT 'F_BKPF_BUK'
ID 'BUKRS' FIELD i_v_company_code
ID 'ACTVT' FIELD lcl_tools=>c_act_disp.
IF sy-subrc EQ 0.
r_v_authority_ok = abap_true.
ELSE.
r_v_authority_ok = abap_false.
ENDIF.

ENDMETHOD.

METHOD get_additional_dme_params.
DATA: l_s_company_address TYPE szadr_addr1_complete.

SELECT SINGLE bukrs butxt ort01 land1 waers stceg adrnr
FROM t001
INTO r_s_additional_data
WHERE bukrs = mv_company_code.

CALL FUNCTION 'ADDR_GET_COMPLETE'
EXPORTING
addrnumber = r_s_additional_data-adrnr
IMPORTING
addr1_complete = l_s_company_address
EXCEPTIONS
parameter_error = 1
address_not_exist = 2
internal_error = 3
wrong_access_to_archive = 4
address_blocked = 5
OTHERS = 6.
IF sy-subrc EQ 0.
READ TABLE l_s_company_address-addr1_tab ASSIGNING FIELD-SYMBOL(<l_s_company_address>) INDEX 1.
IF sy-subrc EQ 0.
r_s_additional_data-post_code1 = <l_s_company_address>-data-post_code1.
r_s_additional_data-street = <l_s_company_address>-data-street.
r_s_additional_data-house_num1 = <l_s_company_address>-data-house_num1.
ENDIF.
ENDIF.

ENDMETHOD.

METHOD check_dmee_format.

SELECT SINGLE xml_tree
FROM dmee_tree
INTO r_v_is_xml
WHERE tree_type = lcl_tools=>c_dmee_tree_type
AND tree_id = mv_dmee_tree.

ENDMETHOD.

ENDCLASS.

Include Z_DMEE_INVOICE_EXTRACT_LCL02:
CLASS lcl_alv_display DEFINITION FINAL CREATE PUBLIC.


PUBLIC SECTION.
METHODS: setup_alv.

METHODS: constructor IMPORTING i_t_invoice_headers TYPE lcl_tools=>tt_invoice_header
i_t_invoice_lines TYPE lcl_tools=>tt_invoice_lines
i_t_invoice_deliveries TYPE lcl_tools=>tt_invoice_deliveries.

PRIVATE SECTION.
CLASS-DATA m_o_screen TYPE REF TO lcl_screen.
DATA: mo_alv_transformer TYPE REF TO cl_xx_alv_transformer.
DATA: mo_alv_display TYPE REF TO cl_xx_alv_display.
DATA: mt_headers TYPE lcl_tools=>tt_invoice_header.
DATA: mt_lines TYPE lcl_tools=>tt_invoice_lines.
DATA: mt_deliveries TYPE lcl_tools=>tt_invoice_deliveries.

"ALV display
METHODS:
setup_alv_nodes,
display.

ENDCLASS.

CLASS lcl_alv_display IMPLEMENTATION.

METHOD constructor.
m_o_screen = lcl_screen=>get_instance( ).
mo_alv_transformer = NEW cl_xx_alv_transformer( ).
mo_alv_display = NEW cl_xx_alv_display( ).
mt_headers = i_t_invoice_headers.
mt_lines = i_t_invoice_lines.
mt_deliveries = i_t_invoice_deliveries.

ENDMETHOD.

METHOD setup_alv.

setup_alv_nodes( ).
display( ).

ENDMETHOD.

METHOD setup_alv_nodes.
DATA: l_v_header_title TYPE sytitle.
DATA: l_v_title TYPE char30.

l_v_header_title = text-001.

"inform user what is happening now
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
text = text-i01.

TRY.
"add single invoice ALV header
mo_alv_transformer->add_alv_view( iv_is_header = abap_true
iv_header_title = l_v_header_title ).

"Folder for each invoice
LOOP AT mt_headers ASSIGNING FIELD-SYMBOL(<l_s_invoice_header>).
WRITE <l_s_invoice_header>-vbeln TO l_v_title.

DATA(l_t_headers_alv) = VALUE lcl_tools=>tt_invoice_header_alv( ( <l_s_invoice_header> ) ).

mo_alv_transformer->add_alv_view( iv_structure_name = lcl_tools=>c_structure_header
iv_default_variant = m_o_screen->mv_layout
it_outtab = l_t_headers_alv
iv_is_tree_folder = abap_true
iv_tree_folder_title = l_v_title ).

LOOP AT mt_lines ASSIGNING FIELD-SYMBOL(<l_s_invoice_line>) WHERE vbeln = <l_s_invoice_header>-vbeln.

DATA(l_t_lines_alv) = VALUE lcl_tools=>tt_invoice_lines_alv( ( <l_s_invoice_line> ) ).

l_v_title = |{ <l_s_invoice_line>-posnr ALPHA = OUT }|.

"If delivery exists for a line - make a folder
"If not - just output items as subnodes
IF line_exists( mt_deliveries[ vbeln = <l_s_invoice_line>-vgbel ] ).
DATA(l_v_delivery_exists) = abap_true.
ELSE.
CLEAR l_v_delivery_exists.
ENDIF.

mo_alv_transformer->add_alv_view( iv_structure_name = lcl_tools=>c_structure_line
it_outtab = l_t_lines_alv
iv_is_tree_folder = COND xfeld( WHEN l_v_delivery_exists EQ abap_true THEN abap_true
ELSE abap_false )
iv_tree_folder_title = COND char30( WHEN l_v_delivery_exists EQ abap_true THEN l_v_title
ELSE space )
iv_is_tree = COND xfeld( WHEN l_v_delivery_exists EQ abap_true THEN abap_false
ELSE abap_true )
iv_tree_title = COND char30( WHEN l_v_delivery_exists EQ abap_true THEN space
ELSE l_v_title )
iv_tree_level = COND int2( WHEN l_v_delivery_exists EQ abap_true THEN 1
ELSE 0 )
iv_is_tabstrip = abap_true
).

LOOP AT mt_deliveries ASSIGNING FIELD-SYMBOL(<l_s_invoice_delivery>) WHERE vbeln = <l_s_invoice_line>-vgbel AND posnr = <l_s_invoice_line>-vgpos.

DATA(l_t_deliveries_alv) = VALUE lcl_tools=>tt_invoice_deliveries_alv( ( <l_s_invoice_delivery> ) ).

l_v_title = |{ <l_s_invoice_delivery>-vbeln ALPHA = OUT }{ <l_s_invoice_delivery>-posnr ALPHA = OUT }|.

"If deliveries exist - output them as subnodes of items
mo_alv_transformer->add_alv_view( iv_structure_name = lcl_tools=>c_structure_delivery
it_outtab = l_t_deliveries_alv
iv_tree_title = l_v_title
iv_is_tree = abap_true
iv_tree_level = 1 ).

ENDLOOP.

ENDLOOP.
ENDLOOP.

CATCH cx_xx_shared_exception. "#EC NO_HANDLER
ENDTRY.

ENDMETHOD.

METHOD display.

TRY .
"Adding of this class as ALV transformer module
mo_alv_display->add_alv_transformer( mo_alv_transformer ).

"Displays ALV
mo_alv_display->display_alv( ).

CATCH cx_xx_shared_exception. "#EC NO_HANDLER
ENDTRY.

ENDMETHOD.

ENDCLASS.

Include Z_DMEE_INVOICE_EXTRACT_LCL03:
CLASS lcl_report DEFINITION FINAL CREATE PRIVATE.

PUBLIC SECTION.

CLASS-METHODS get_instance RETURNING VALUE(r_o_report) TYPE REF TO lcl_report.
"Main processing
METHODS process.

PRIVATE SECTION.
CLASS-DATA: m_o_report TYPE REF TO lcl_report.

DATA: mt_invoice_header TYPE lcl_tools=>tt_invoice_header.
DATA: mt_invoice_lines TYPE lcl_tools=>tt_invoice_lines.
DATA: mt_invoice_deliveries TYPE lcl_tools=>tt_invoice_deliveries.

DATA: mv_dmee_first_started TYPE xfeld.

CLASS-DATA m_o_screen TYPE REF TO lcl_screen.
DATA: mt_dmee_output TYPE tab_dmee_output_file.

METHODS: constructor.
METHODS: select_data.

"selection methods
METHODS:
select_invoices,
select_invoice_lines,
select_deliveries,
get_tax_code_for_item.

"DME handler
METHODS:
generate_dmee,
start_dmee_engine IMPORTING i_s_invoice TYPE zdmee_invoice_header,
add_dmee_item IMPORTING i_v_invoice_header TYPE zdmee_invoice_header
i_v_invoice_line TYPE zdmee_invoice_line
i_v_invoice_delivery TYPE zdmee_delivery_line OPTIONAL,
close_engine,
check_if_new_file_needed IMPORTING i_s_dmee_data TYPE zdmee_invoice_data
RETURNING VALUE(r_v_new_file_needed) TYPE xfeld,
download_file,
download_xml_file,
download_flat_file,
xml_file_start_download IMPORTING i_v_display_only TYPE xfeld
i_v_filename TYPE string.
"ALV display
METHODS: display_alv.

ENDCLASS.

CLASS lcl_report IMPLEMENTATION.

METHOD get_instance.

IF m_o_report IS NOT BOUND.
CREATE OBJECT m_o_report.
ENDIF.
r_o_report = m_o_report.

ENDMETHOD.

METHOD constructor.

me->m_o_screen = lcl_screen=>get_instance( ).

ENDMETHOD.

METHOD process.

select_data( ). "Data selection
generate_dmee( ). "Handling of all DMEE functions
display_alv( ). "Call LCL_ALV_DISPLAY class

ENDMETHOD.

METHOD select_data.

select_invoices( ). "Select invoice headers- VBRK
select_invoice_lines( )."Select invoice lines - VBRP
select_deliveries( ). "Select delivery data for invoices - LIKP and LIPS

ENDMETHOD.

METHOD select_invoices.

SELECT vkorg vtweg spart bukrs vbeln fkart fktyp waerk
fkdat inco1 kurrf zterm ernam erzet kunrg kunag
stceg fkart_rl bstnk_vf landtx land1 xblnr fksto
kidno zuonr vbtyp knumv
FROM vbrk
INTO TABLE mt_invoice_header
WHERE vbeln IN m_o_screen->mt_billing_docs
AND bukrs EQ m_o_screen->mv_company_code
AND fkdat IN m_o_screen->mt_billing_date
AND fkart IN m_o_screen->mt_billing_types
AND vkorg IN m_o_screen->mt_sales_org.
IF sy-subrc NE 0.

MESSAGE text-003 TYPE 'I'.
LEAVE TO SCREEN 0.

ENDIF.

ENDMETHOD.

METHOD select_invoice_lines.

IF mt_invoice_header IS NOT INITIAL.
SELECT vbeln, posnr, vrkme, meins, fkimg, ntgew, brgew,
gewei, volum, voleh, prsdt, netwr, vgbel, wavwr,
mwsbp, cmpre, vgpos, vgtyp, aubel, aupos, matnr,
arktx, matkl, werks, pstyv, aland, sktof, skfbp,
ernam, ean11, fbuda, paobjnr
FROM vbrp
INTO TABLE @DATA(l_t_invoice_lines)
FOR ALL ENTRIES IN @mt_invoice_header
WHERE vbeln = @mt_invoice_header-vbeln.
IF sy-subrc EQ 0.
MOVE-CORRESPONDING l_t_invoice_lines TO mt_invoice_lines.
ENDIF.

ENDIF.

get_tax_code_for_item( ). "Determine MWZKS from condition lines - KONV

ENDMETHOD.

METHOD select_deliveries.
TYPES: tr_delivery TYPE RANGE OF vbeln_vl.

"get all deliveries as base for selection
DATA(l_t_delivery_reference) = VALUE tr_delivery( FOR ls_delivery IN mt_invoice_lines
WHERE ( vgtyp = 'J' )
LET sign = 'I'
option = 'EQ'
IN sign = sign
option = option
( low = ls_delivery-vgbel )
).

IF l_t_delivery_reference IS NOT INITIAL.
SORT l_t_delivery_reference.
DELETE ADJACENT DUPLICATES FROM l_t_delivery_reference COMPARING low.

SELECT a~vbeln, b~posnr, a~ernam, a~erdat, a~lfart, a~wadat, a~lddat,
a~lfdat, a~kodat, a~ablad, a~kunnr, a~btgew, a~wadat_ist, a~wauhr,
b~matnr, b~matwa, b~matkl, b~werks, b~lgort, b~charg, b~lichn,
b~kdmat, b~prodh, b~lfimg, b~meins, b~vrkme, b~ntgew, b~brgew,
b~gewei, b~lgmng, b~ladgr, b~tragr, b~lgnum, b~bwart, b~mtart,
b~ean11, b~pstyv
FROM likp AS a
JOIN lips AS b ON
a~vbeln = b~vbeln
INTO TABLE @DATA(l_t_deliveries)
WHERE a~vbeln IN @l_t_delivery_reference.
IF sy-subrc EQ 0.
MOVE-CORRESPONDING l_t_deliveries TO mt_invoice_deliveries.
ENDIF.

ENDIF.

ENDMETHOD.

METHOD get_tax_code_for_item.

IF mt_invoice_header IS NOT INITIAL.

"get pricing conditions to determine tax code
SELECT knumv, kposn, mwsk1
FROM konv
INTO TABLE @DATA(l_t_pricing_conditions)
FOR ALL ENTRIES IN @mt_invoice_header
WHERE knumv = @mt_invoice_header-knumv.
IF sy-subrc EQ 0.
SORT l_t_pricing_conditions BY knumv DESCENDING kposn DESCENDING.
DELETE l_t_pricing_conditions WHERE mwsk1 IS INITIAL.
SORT l_t_pricing_conditions BY knumv DESCENDING kposn DESCENDING.
DELETE ADJACENT DUPLICATES FROM l_t_pricing_conditions COMPARING knumv kposn mwsk1.

LOOP AT mt_invoice_header ASSIGNING FIELD-SYMBOL(<l_s_single_invoice>).

LOOP AT mt_invoice_lines ASSIGNING FIELD-SYMBOL(<l_s_invoice_item>) WHERE vbeln = <l_s_single_invoice>-vbeln.

TRY .
<l_s_invoice_item>-mwskz = l_t_pricing_conditions[ knumv = <l_s_single_invoice>-knumv
kposn = <l_s_invoice_item>-posnr ]-mwsk1.

CATCH cx_sy_itab_line_not_found.
CONTINUE.
ENDTRY.

ENDLOOP.

ENDLOOP.
ENDIF.
ENDIF.

ENDMETHOD.

METHOD generate_dmee.

"for each invoice process DMEE
LOOP AT mt_invoice_header ASSIGNING FIELD-SYMBOL(<l_s_invoice_header>).

"start DME engine for invoice or keep it running if DME is already running
start_dmee_engine( <l_s_invoice_header> ).

"loop over each invoice item for currently processed invoice
LOOP AT mt_invoice_lines ASSIGNING FIELD-SYMBOL(<l_s_invoice_line>) WHERE vbeln = <l_s_invoice_header>-vbeln.

"loop over each delivery connected to invoice line or simply output invoice line if no delivery exists
IF line_exists( mt_invoice_deliveries[ vbeln = <l_s_invoice_line>-vgbel posnr = <l_s_invoice_line>-vgpos ] ).
LOOP AT mt_invoice_deliveries ASSIGNING FIELD-SYMBOL(<l_s_invoice_delivery>) WHERE vbeln = <l_s_invoice_line>-vgbel.
"delivery-based-billing
add_dmee_item( EXPORTING i_v_invoice_header = <l_s_invoice_header>
i_v_invoice_line = <l_s_invoice_line>
i_v_invoice_delivery = <l_s_invoice_delivery> ).
ENDLOOP.
ELSE.
"order-based-billing
add_dmee_item( EXPORTING i_v_invoice_header = <l_s_invoice_header>
i_v_invoice_line = <l_s_invoice_line> ).
ENDIF.

ENDLOOP.
ENDLOOP.

"at the very end close DME engine
close_engine( ).
"and process display or download
download_file( ).

ENDMETHOD.

METHOD start_dmee_engine.
DATA: l_s_dmee_item TYPE zdmee_invoice_data,
l_t_dmee_sort_fields TYPE STANDARD TABLE OF dmee_tree_sort.

l_s_dmee_item-zdmee_invoice_header = i_s_invoice.

IF mv_dmee_first_started EQ abap_true.
DATA(l_v_new_file_needed) = check_if_new_file_needed( l_s_dmee_item ).
ENDIF.

IF mv_dmee_first_started IS INITIAL
OR l_v_new_file_needed IS NOT INITIAL.

CALL FUNCTION 'DMEE_START'
EXPORTING
i_tree_type = lcl_tools=>c_dmee_tree_type
i_tree_id = m_o_screen->mv_dmee_tree
item = l_s_dmee_item
param = m_o_screen->ms_dmee_additional_data
* uparam = i_format_params
TABLES
file_output = mt_dmee_output
sort_fields = l_t_dmee_sort_fields.

IF mv_dmee_first_started IS INITIAL.
mv_dmee_first_started = abap_true.
ENDIF.
ENDIF.

ENDMETHOD.

METHOD add_dmee_item.
DATA: l_s_dmee_item TYPE zdmee_invoice_data.

l_s_dmee_item-zdmee_invoice_header = i_v_invoice_header.
l_s_dmee_item-zdmee_invoice_line = i_v_invoice_line.
l_s_dmee_item-zdmee_delivery_line = i_v_invoice_delivery.

CALL FUNCTION 'DMEE_PUT_ITEM'
EXPORTING
item = l_s_dmee_item
param = m_o_screen->ms_dmee_additional_data
* uparam = params
TABLES
* item_tab = tab_item
file_output = mt_dmee_output.

ENDMETHOD.

METHOD close_engine.
DATA: l_t_error_output TYPE STANDARD TABLE OF fimsg.
DATA: l_t_fpm_fields TYPE STANDARD TABLE OF dmee_fpm_fields.

CALL FUNCTION 'DMEE_END'
TABLES
file_output = mt_dmee_output
error_output = l_t_error_output
fpm_fields = l_t_fpm_fields.

ENDMETHOD.

METHOD check_if_new_file_needed.

CALL FUNCTION 'DMEE_NEW_FILE'
EXPORTING
item = i_s_dmee_data
CHANGING
xnew_file = r_v_new_file_needed.

IF r_v_new_file_needed IS NOT INITIAL.

close_engine( ).
download_file( ).

ENDIF.

ENDMETHOD.

METHOD download_file.

CASE m_o_screen->mv_dmee_is_xml.
WHEN abap_true.
download_xml_file( ).
WHEN abap_false.
download_flat_file( ).
WHEN OTHERS.
ENDCASE.

ENDMETHOD.

METHOD download_xml_file.
CONSTANTS: l_c_xml TYPE string VALUE 'XML'.
DATA:
l_v_filename TYPE string,
l_v_fullpath TYPE string,
l_v_result TYPE i,
l_v_path TYPE string.

IF m_o_screen->mv_display_only EQ abap_true.

xml_file_start_download( EXPORTING i_v_display_only = abap_true
i_v_filename = l_v_filename ).
ELSE.
CALL METHOD cl_gui_frontend_services=>file_save_dialog
EXPORTING
default_extension = l_c_xml
CHANGING
filename = l_v_filename
path = l_v_path
fullpath = l_v_fullpath
user_action = l_v_result.

IF l_v_result IS INITIAL.

xml_file_start_download( EXPORTING i_v_display_only = abap_false
i_v_filename = l_v_filename ).

ENDIF.
ENDIF.

ENDMETHOD.

METHOD download_flat_file.
CONSTANTS c_file_txt TYPE string VALUE 'TXT'.

DATA:
l_v_filename TYPE string,
l_v_path TYPE string,
l_v_fullpath TYPE string,
l_v_result TYPE i.
DATA: l_v_codepage TYPE cpcodepage.
DATA: l_t_file_data TYPE STANDARD TABLE OF string WITH EMPTY KEY.

IF m_o_screen->mv_display_only IS NOT INITIAL.

"display only
CALL FUNCTION 'POPUP_WITH_TABLE_DISPLAY'
EXPORTING
endpos_col = 30
endpos_row = lines( mt_dmee_output )
startpos_col = 10
startpos_row = 1
titletext = text-004
* IMPORTING
* choise = l_v_choice
TABLES
valuetab = mt_dmee_output
EXCEPTIONS
break_off = 1
OTHERS = 2.

ELSE.
"download
LOOP AT mt_dmee_output ASSIGNING FIELD-SYMBOL(<l_s_dme_line>).

APPEND <l_s_dme_line>-line TO l_t_file_data.

ENDLOOP.

"get default encoding by language
CALL FUNCTION 'NLS_GET_FRONTEND_CP'
EXPORTING
langu = CONV spras( sy-langu ) ##OPERATOR
* FETYPE = 'MS'
IMPORTING
frontend_codepage = l_v_codepage
EXCEPTIONS
illegal_syst_codepage = 1
no_frontend_cp_found = 2
internal_or_db_error = 3
OTHERS = 4.
IF sy-subrc NE 0.
l_v_codepage = '4110'.
ENDIF.
CONDENSE l_v_codepage NO-GAPS.

CALL METHOD cl_gui_frontend_services=>file_save_dialog
EXPORTING
default_extension = CONV string( c_file_txt )
CHANGING
filename = l_v_filename
path = l_v_path
fullpath = l_v_fullpath
user_action = l_v_result.

IF l_v_result IS INITIAL.

CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
filename = l_v_filename
codepage = CONV abap_encoding( l_v_codepage )
TABLES
data_tab = l_t_file_data
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ELSE.
MESSAGE i427(fr) WITH l_v_filename.
ENDIF.
ENDIF.

ENDIF.
ENDMETHOD.

METHOD xml_file_start_download.

CALL FUNCTION 'DMEE_HANDLE_XML_DOC_PC'
EXPORTING
i_filename = i_v_filename
i_save = COND xfeld( WHEN i_v_display_only EQ abap_true THEN space
ELSE abap_true )
i_display = i_v_display_only.

ENDMETHOD.

METHOD display_alv.

NEW lcl_alv_display( i_t_invoice_headers = mt_invoice_header
i_t_invoice_lines = mt_invoice_lines
i_t_invoice_deliveries = mt_invoice_deliveries )->setup_alv( ).

ENDMETHOD.

ENDCLASS.

Texts used in report:





That would be it in terms of own DMEE Tree Type - I hope that not only you have read through the blog but also will consider using this approach in your designs.

Thank you for reading,

Marek Turczyński
1 Comment
Labels in this area