Generate a Report with Customer Master Long Texts
Because of the cumbersome way that SAP stores long texts, it is not possible to access them with a custom query, with nested select statements or even with complex joins. The only way to access the long texts for the purpose of a report is through the READ_TEXT
function.
Unlike the report for Material Master long texts, this provides a list of long text types related to Customer Masters instead of a radio button backed by custom ABAP code. Once selected, the report then knits together the parameters that are passed to the READ_TEXT
function.
The first step is to create a selection screen that allows for the selection of which Customer Masters should appear in the report along with the type long text to be included. In this case the screen will be relatively complex with SELECT-OPTIONS
and a drop down menu. It is important to note that the tables KNA1
, KNB1
, KNVV
and T002
are declared and cannot be used in User Defined Routines.
TYPE-POOLS: vrm. DATA: gt_list TYPE vrm_values. DATA: gwa_list TYPE vrm_value. DATA: gt_values TYPE TABLE OF dynpread, gwa_values TYPE dynpread. DATA: gv_selected_value(10) TYPE c. data: lTTXID like TTXID, lTTXIT like TTXIT. tables: kna1, knb1, knvv, T002. SELECTION-SCREEN BEGIN OF BLOCK B1 WITH FRAME TITLE btext1. PARAMETERS: p_list(10) TYPE c AS LISTBOX VISIBLE LENGTH 20. SELECT-OPTIONS: s_KUNNR FOR KNA1-KUNNR, "Customer Number s_BUKRS for KNB1-BUKRS, "Company Code s_vkorg FOR KNVV-vkorg, "Sales Organization s_vtweg FOR KNVV-vtweg, "Distribution Channel s_SPART for KNVV-SPART, "Division s_SPRAS for T002-SPRAS. SELECTION-SCREEN END OF BLOCK B1. SELECTION-SCREEN BEGIN OF BLOCK B2 WITH FRAME TITLE btext2. parameters p_break as checkbox. SELECTION-SCREEN END OF BLOCK B2. selection-screen begin of block bfile with frame title bfile1. selection-screen begin of line. PARAMETERS : P_RAD1 RADIOBUTTON GROUP RB1 default 'X'. selection-screen comment 3(20) coscreen. selection-screen end of line. selection-screen begin of line. PARAMETERS : P_RAD2 RADIOBUTTON GROUP RB1. selection-screen comment 3(14) cofile. parameters: p_filenm type string. selection-screen end of line. selection-screen begin of line. PARAMETERS : P_RAD3 RADIOBUTTON GROUP RB1. selection-screen comment 3(16) coexcel. parameters: p_friend as checkbox default 'X'. selection-screen comment 23(30) cofriend. selection-screen end of line. selection-screen end of block bfile.
Once the selection screen is complete, it is time to populate the drop down list with all of the possible long texts that exist in the system--including the custom ones! This turns out to be easier than one might think as they are all stored in the table TTXID
and described in table TTXIT
.
There is no guarantee that a description exists in the user's language, so the code loops through the TTXIT
table once for any available language and then again to see if the user's language is available. That record containing the concatenated TDOBJECT
and TDID
value, along with the associated description, are then appended to the gt_list
internal table where it can be associated with the parameter P_LIST
by the VRM_SET_VALUES
function.
initialization. select * from TTXID into lTTXID where TDOBJECT eq 'KNA1' or TDOBJECT eq 'KNB1' or TDOBJECT eq 'KNVV'. concatenate lTTXID-TDOBJECT lTTXID-TDID into gwa_list-key. select * from TTXIT into lTTXIT where TDOBJECT eq lTTXID-TDOBJECT and TDID eq lTTXID-TDID. concatenate lTTXID-TDOBJECT lTTXIT-TDTEXT into gwa_list-text separated by space. endselect. select * from TTXIT into lTTXIT where TDOBJECT eq lTTXID-TDOBJECT and TDID eq lTTXID-TDID and TDSPRAS eq SY-LANGU. "Use user's language if possible. concatenate lTTXID-TDOBJECT lTTXIT-TDTEXT into gwa_list-text separated by space. endselect. append gwa_list to gt_list. endselect. CALL FUNCTION 'VRM_SET_VALUES' EXPORTING id = 'P_LIST' values = gt_list EXCEPTIONS id_illegal_name = 1 OTHERS = 2.
The last part of building the selection screen is adding some text and removing the frame and parameters that LSMW expects. These aren't use as this LSMW object is being used as a framework for reporting and there are no incoming records to handle.
loop at screen. "Clean up screen by removing unwanted lines. if g_cnt_records_read_progress lt 7. screen-invisible = 1. screen-active = 0. modify screen. endif. add 1 to g_cnt_records_read_progress. endloop. btext1 = 'Report parameters'. btext2 = 'Testing tools'. bfile1 = 'Export to file'. coscreen = 'Write to screen.'. cofile = 'Write to file:'. coexcel = 'Present in Excel.'. cofriend = 'Friendly field names.'.
The next step is to create an internal table to hold a list of Customer Masters and related data that will be looped through to find long texts. The KNVV structure was chosen in this case as it can be used to hold Customer Master number, Customer Master number and Company Code or Customer Master Number, Sales Org, Division and Distribution Channel information effectively.
Additionally, the code is sped up considerably by reading the contents of the STXH
table into an internal table where the records have information related to the long texts chosen in the selection screen. This obviates the need to call READ_TEXT
function for every combination of Customer Master and language, but instead calls the function only when a long text record exists.
data: it_KNVV type standard table of KNVV initial size 0. data: lKNVV like KNVV, lT002 like T002, lKNA1 like KNA1, it_KNA1 type standard table of KNA1 initial size 0, lKNB1 like KNB1, lTDNAME like THEAD-TDNAME, it_TLINE type standard table of TLINE, wa_TLINE type TLINE, lText type string. "Folliwing lines added to severely optimize code. data: wa_STXH like STXH, it_STXH type standard table of STXH initial size 0. types: begin of i_Report, KUNNR(10) type c, NAME1 like KNA1-NAME1, VKORG(5) type c, VTWEG(5) type c, SPART(5) type c, SPRAS(2) type c, Text type string, end of i_Report. data: wa_Report type i_Report, it_Report type standard table of i_Report initial size 0. data: cID(4) type c, cObject(10) type c. cObject = p_List+0(4). cID = p_List+4(4). "Speeding things up to shave hours off of runtime. select * from STXH into table it_STXH where TDOBJECT eq cObject and TDID eq cID and TDSPRAS in s_SPRAS. select * from KNA1 into table it_KNA1 where KUNNR in s_KUNNR.
Now the it_KNVV
table is populated with the desired Customer Master data based on the type of long text chosen in the selection screen. Where the long text is based on the Company Code data, the it_KNVV-VKORG
field is populated with the LFB1-BUKRS
for use later in the program.
if cObject eq 'KNVV'. select * from KNVV into table it_KNVV where KUNNR in s_KUNNR and VKORG in s_VKORG and VTWEG in s_VTWEG and SPART in s_SPART. elseif cObject eq 'KNB1'. select * from KNB1 into lKNB1 where KUNNR in s_KUNNR and BUKRS in s_BUKRS. lKNVV-KUNNR = lKNB1-KUNNR. lKNVV-VKORG = lKNB1-BUKRS. "Stored in wrong field, but moot. append lKNVV to it_KNVV. endselect. else. loop at it_KNA1 into lKNA1. lKNVV-KUNNR = lKNA1-KUNNR. append lKNVV to it_KNVV. endloop. endif.
Next, a header line is added to the report for convenience. The fields of wa_Report
are simply populated with their own names and then that record is appended to the it_Report
internal table.
wa_Report-KUNNR = 'KUNNR'. wa_Report-NAME1 = 'NAME1'. if cObject eq 'KNVV'. wa_Report-VKORG = 'VKORG'. wa_Report-VTWEG = 'VTWEG'. wa_REPORT-SPART = 'SPART'. elseif cObject eq 'KNB1'. wa_Report-VKORG = 'BUKRS'. "Company code. =P else. "Leave these headers blank. endif. wa_Report-SPRAS = 'SPRAS'. wa_Report-Text = 'Text'. append wa_Report to it_Report.
Now the work begins. The code loops through the it_KNVV
and it_STXH
internal tables and, where they meet, calls the READ_TEXT function using the values from the tables as parameters.
loop at it_KNVV into lKNVV. perform CheckRuntime. "Prevent 'Uninterrupted Runtime' error. if cObject eq 'KNVV'. concatenate lKNVV-KUNNR lKNVV-VKORG lKNVV-VTWEG lKNVV-SPART into lTDNAME. elseif cObject eq 'KNB1'. concatenate lKNVV-KUNNR lKNVV-VKORG into lTDNAME. else. lTDNAME = lKNVV-KUNNR. endif. loop at it_STXH into wa_STXH where TDNAME eq lTDNAME. CALL FUNCTION 'READ_TEXT' EXPORTING CLIENT = SY-MANDT ID = cID LANGUAGE = wa_STXH-TDSPRAS NAME = lTDNAME OBJECT = cObject TABLES LINES = it_TLINE EXCEPTIONS ID = 1 OTHERS = 8. IF SY-SUBRC EQ 0. loop at it_KNA1 into lKNA1 where KUNNR = lTDNAME+0(10). wa_Report-KUNNR = lKNA1-KUNNR. wa_Report-NAME1 = lKNA1-NAME1. wa_Report-VKORG = lKNVV-VKORG. wa_Report-VTWEG = lKNVV-VTWEG. wa_Report-SPART = lKNVV-SPART. wa_Report-SPRAS = wa_STXH-TDSPRAS. LOOP AT it_TLINE INTO wa_TLINE. wa_Report-TEXT = wa_TLINE-TDLINE. append wa_Report to it_Report. ENDLOOP. endloop. ENDIF. endloop. endloop.
Finally, the it_Report
internal table is populated with all of the long text values related to the Customer Masters selected on the selection screen of the type selected on the selection screen. The final step is to loop through the table and display the records on the screen, export the records to a text file or to display the records in Excel based on the options from the selection screen.
if p_Rad1 eq 'X'. "Write to screen... loop at it_Report into wa_Report. write: / wa_Report-KUNNR, wa_Report-NAME1, wa_Report-VKORG, wa_Report-VTWEG, wa_Report-SPART, wa_Report-SPRAS, wa_Report-Text. endloop. elseif p_Rad2 eq 'X'. "Write to file... if p_Filenm ne ''. "Export to file! CALL FUNCTION 'GUI_DOWNLOAD' EXPORTING FILENAME = p_filenm FILETYPE = 'ASC' APPEND = '' * CODEPAGE = 'IBM' WRITE_FIELD_SEPARATOR = 'X' HEADER = '00' TRUNC_TRAILING_BLANKS = 'X' TABLES DATA_TAB = it_Report EXCEPTIONS FILE_WRITE_ERROR = 1 OTHERS = 2. endif. else. "Show in Excel... if p_friend eq 'X'. wa_STXH-TDSPRAS = sy-langu. else. wa_STXH-TDSPRAS = ''. "No friendly lables. endif. perform InternalTableToExcel using it_Report 1 wa_STXH-TDSPRAS. endif.
Download this tool
This tool, along with many others are included in Jimbo's LSMW Toolbox. It's free and much easier than trying to copy-paste this into a new LSMW object. Additionally, all of the required subroutines are included, so there's that, too.