Quantcast
Channel: SCN : Blog List - ABAP Development
Viewing all 943 articles
Browse latest View live

Concept of Switch Framework in Enhancement

$
0
0

The main purpose of the Switch Framework is to simplify an ABAP-based system landscape by adopting one or more industry solutions in a standard system. The Switch Framework allows you to externally control the visibility of repository objects or their components by means of switches.

By using the Switch Framework, all industry solutions and a restricted list of repository objects are delivered in an inactive state in the system. With minor exceptions, you no longer need to install an industry solution – you can activate it when required.

 

Integration

The Switch Framework is integrated in the ABAP Workbench and works closely together with the Enhancement Framework.

 

Features
The Switch Framework enables you to:

● Switch on industry solutions and Enterprise Add-Ons

● Enhance delivered partner and customer systems

 

Contents of Enhancement Package

● Each enhancement package contains a set of business functions

● Each business function is optionally implemented and activated

 

Optional Installation

● Only install the business functions that are applicable to the business needs

● Post installation process changes will take place only on activation

● No impact on SAP netweaver platform

 

Optional Activation

● Activate components on demand

● End user regression testing by component activation

● SAP provides testing templates for the components

 

Bug finding using Switch Framework

● Use the switch framework to activate/deactivate enhancements to evaulate source of bug

● If bug is gone on deactivation it is part of the enhancement

● If bug is persistent on deactivation it is part of standard

 

Example:

Create at least 1 switch and 1 business function. Assign the switch to the packages containing the enhancement implementations. Use transaction SFW5 to activate/ deactivate the switch.

 

1.JPG

 

Please note that the business function must be reversible. Switching of BC-Sets and DDIC is not allowed.

 

Architecture of Switch Framework

 

2.JPG

After the business function is available, the switching of the business function will be possible using the switch framework.

 

3.JPG

Assignments can be made in both directions:

● Define the assignment in superordinate object if possible.

● Creating the assignment in the subordinate object has less flexibility and is comparable to an enhancement.

 

Switchable Objects by package Assignment:

● Enhancement Implementations

● Appends, SI-, CI- Includes for dictionary structures

● Fixed value appends to domains

● Append search helps

● Secondary Indexes

● Switch Business configuration sets.

 

Example of Switch in Dictionary Index.


 

Example of Switch in Append Structure:

 

 

Switchable objects by Direct Assignment:

● Screen elements and flow logic

● Menu entries

● IMG Nodes

● Easy access menus

● Customizing

 

Example of Switch in Screen Painter

 

 

Switch dependent screen elements in the element list – disabled. Elements are not visible at runtime.

 

Switch Dependent Module in Screen Painter

 

 

Switch in Menu Painter

 

 

Dependent Objects in given business function

 

 

Deactivating Business Functions:

● Reversible Business Functions must not contain dictionary objects or BC-Sets.

● Reversible Business Functions may be deactivated in development or test systems only.

● Do not deactivate a reversible Business Function in a production system to keep data integrity.

 

* Practical example coming soon


Transport Checking Tool (Object level)

$
0
0

Transport Checking Tool (on Object level)

Did you ever get the request to ‘quickly check the transport list’ two days before Go-Live?

Only to discover that the list has hundreds of transports with thousands of objects?

And after going through the first few transports you find out that the list is a mess. Checking one object will indicate other transports that are not in the list, or transports that are ‘not needed anymore’ but with changes that were never rolled back, or emergency transports already in production... Etc. etc.


So how do you check the list? You know that there is no way that this list of transports can go to production without issues. Clearing up the mess is impossible, takes too long or is too costly.

There will be issues, but which? How serious will they be?

The next question you’ll get is ‘What is the risk?’. Do you dare to answer ‘The system could go KABOOOM’?

 

Yes, most issues can be prevented if the responsible user is careful in creating transports and organizing them before releasing them. However, nobody’s perfect. Mistakes will be made and corners will be cut. When the pressure from above increases, strict rules suddenly become flexible.

 

Some possible risks:

  • Loss of functionality in production (if a newer transport is overwritten),
  • Moving untested code to production (if an older transport exists for the same object, that is not included in the transport list),
  • Objects use DDIC objects that are in Development and Acceptance, but NOT in production (causing dumps),
  • Different versions are active in Production and Acceptance.

 

In the past I ran into this problem. I had to check a list of transports for a project that lasted over a year. Multiple developers worked on it and each delivered a list of transports. This I had to check… I encountered so many problems that I decided to write a small program that would check for older and newer transports of all objects used and then give warnings. The program was far from perfect, but it did the trick. The project from hell went live with only minor issues. That was several years ago. Since that time the program has grown. More checks and functions were implemented.

 

I do not have the illusion that it is perfect. I tried to make it as flexible as possible, but there is always room for improvement.

 

Logo3.jpg

But if there are people who may have use for a tool like this, they can check it out and download it from SAP Code Exchange: https://cw.sdn.sap.com/cw/groups/ztct. It is a local program, available as a SAPLINK nugget, that only has program text and documentation.

It does not make changes to the database, but runs as a straightforward report. The only thing the program can create, is transport documentation, if the user decides to do so.

 

I would also like to take the opportunity to point out that there are other initiatives. For example the Transport request dependencies analyzer (https://cw.sdn.sap.com/cw/groups/transport-request-sequencer).

 

You can find that and other projects related to Transport Checking here:  https://cw.sdn.sap.com/cw/codex/projects#/?tags=transport.

 

Description of the Tool

Below is a short description of the tool, input, output and functionality. For more detailed information, please have a look at the User Manual on Code Exchange.

 

Selection Screen

This is what the selection screen looks like:

SelectionScreen.jpg

Output

This screenshot is an example of the output.

ZTCT_Output.jpg

Interesting is the Application toolbar, which has buttons to:

  • Recheck selected rows,
  • Add transports conflicting with selected rows,
  • Add a single transport,
  • Add another saved file (merge lists),
  • Remove selected transports (if you select one row, all rows for that transport will be removed)
  • Mark a transport that is in Production for Re-transport,
  • Jump to the next relevant Conflict,
  • Build a simple list (on header level, unique transport numbers only, no Object information).

 

Transport sequence: order and disorder

The order in which the transports should be moved to production is the order in which they were imported in the Acceptance environment.

This guarantees that the versions in Production will be the same as the versions in Acceptance at the time the User Acceptance Test was performed and signed off.

Determining the transport order is straightforward enough. The complicating factor will be other transports in acceptance, containing one or more objects that are the same as objects in your list.

These conflicting transports may belong to other projects or other people. Maybe those transports cannot yet go to production (code is untested) or may already have been transported to production (as emergency transports).

 

In general it is not the process to determine the transport sequence that will cause problems, but other transports that will cause disruptions to your list.

 

Preventing that these issues and risks arise is always better than trying to solve them. It all starts with a good understanding of which objects should be grouped together in the same transport and which objects should be transported separately.

 

The Developer or Functional consultant should always be very alert for these considerations.

As a rule, User-Exits should always be transported separately. The same rule would apply for DDIC elements that can/will be used in multiple objects.

Other considerations would be if the complete function group needs to be transported or only a single function. Should the complete Class be transported or only the implementation of a method? Should the complete program (including texts and documentation) be transported or only the Report code?

 

Keeping the transport list clean and simple may prevent a lot of hair-pulling later on. 

 

Risks when transporting to Production

When transports are moved to production, there are several possible risks. The chance, severity and impact of issues on the system will increase with the number of transports involved and the number of objects in these transports.

Other complicating factors are the number of developers working on the same project, the runtime of the project, developers working on the same objects, transports being moved in case of production issues (disrupting the alignment) etc. etc.

Frequent problems encountered when NOT using a transport checking tool are described in the next two paragraphs.

 

Objects overwrite newer versions already in Production

Result: loss of recent changes/functionality.

OvershootingATransport.jpg

 

Objects go to Production with previous versions in Acceptance

Result: unwanted (or even incorrect) changes go to Production without being signed off.
Code can also contain data elements that are not yet in production. The used/required data elements might exist in Acceptance, in another transport, but not yet in Production. When developing and testing there will be no syntax error. There will be no warning at all because the data element exists in Development and Acceptance. Only after the transport to production has been done, dumps will occur.

RiskIgnoringPreviousVersions.jpg

Will Code for Food

$
0
0

Yes, I know you've seen it before.

Coder.jpg

But lets go deeper than how funny it is.

 

I love coding!  But the life of a coder is not all that good.  So here's a guy who could choose anything to do for food.  In America, the government will pay him not to work.  But he is such a dedicated coder (I know it's a gag pic, but use your abstract thinking.  Imagine...) that he will write code for free just so long as he gets fed and has the fun of coding.

 

So one of my take homes from this is that if you don't love coding, get out.  There are fun things to do in the world for each person.  If yours isn't coding, find something that you do love.  Life is too short to do anything less.

 

Also, looking at this guy, can't you just see the bad times.  Bad times come and bad times go.  I remember salaries and rates being cut in half a few years back.  But like this guy, I worked right through it.  I never slowed down.

 

So I keep this picture on the wall beside my work desk.  And when I get tired I refresh myself by considering the messages in the picture.

 

I hope your coding goes well,

 

Neal Wilhite

Authorization check for selection option

$
0
0

I want to share AUTHORITY-CHECK OBJECT for selection opting.

 

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-002.
PARAMETERS:p_bukrs type bkpf-bukrs OBLIGATORY.
SELECT-OPTIONS :  so_audat FOR vbak-audat OBLIGATORY,
      so_auart FOR vbak-auart OBLIGATORY,
      so_kunnr FOR vbak-kunnr,
      so_matnr FOR vbap-matnr,
      so_vrkme FOR vbap-vrkme OBLIGATORY,
      so_lgort FOR vbap-lgort,
      so_werks FOR vbap-werks,
      so_vkorg FOR vbak-vkorg,
      so_vtweg FOR vbak-vtweg,
      so_spart FOR vbak-spart.
SELECTION-SCREEN END OF BLOCK b1.

 

Want to check Authorization for so_vkorg, so_vtweg, so_spart.

 

Go to AT SELECTION-SCREEN OUTPUT.

Now AT SELECTION-SCREEN.

Call FM V_VBAK_VKO.

 

Check the code.


SELECT *
FROM  vbak
          INTO TABLE tmp_vbak
         WHERE audat IN so_audat
      AND auart IN so_auart
      AND vkorg IN so_vkorg
      AND vtweg IN so_vtweg
      AND spart IN so_spart
      AND bukrs_vf = p_bukrs.

   LOOP AT tmp_vbak INTO  wa_tmp_vbak.
     AUTHORITY-CHECK OBJECT 'V_VBAK_VKO'
        ID 'VKORG' FIELD  wa_tmp_vbak-vkorg
        ID 'VTWEG' FIELD  wa_tmp_vbak-vtweg
        ID 'SPART' FIELD  wa_tmp_vbak-spart
        ID 'ACTVT' FIELD '03'.
   ENDLOOP.
   IF sy-subrc <> 0.
     MESSAGE 'No authorization' TYPE 'E'.
   ENDIF.

 

Hope it will work

MS Office made easy

$
0
0

Some of us have experience with SapScript, SmartForms and PDF based forms. Nevertheless Customers sometime wish to get an MS Office document as soon as it is ‘more familiar’.

We have some options provided by SAP or third party developers. These are:

OLE, DOI both are standard and couple versions of MS Office tools ZWWW as an example or the tool to work with RTF documents.

But let’s compare these technologies:

OLE becomes incredible slow when operating huge data, but you can do everything with your document. But use of OLE makes you hardcode types of documents. So this is a reason why it’s not flexible.

DOI works fine with huge data due to optimization of flushes. For example, you can made OLE document very fast by using queue of OLE commands and common FLUSH. But DOI provides you with this ‘fast option’ from the box. Furthermore you can still operate with OLE objects getting correspondent reference. But where are disadvantages? Well you need to create additional objects to link your GUI-session with document on a frontend such as container. Then you should know how to be with all those interfaces like I_OI_DOCUMENT_PROXY.

ZWWW is a great tool to get almost everything fast and good. You can create a template either at SMW0 or at OAOR transactions. Then you specifies logic of data mapping. This tool works fast.  Isn’t it a dream? I guess no. Because this tool operates with special files with VBA-macroses and runs it without user’s authorization. So it’s a potential harm to user’s computer.

Tool to operate RTF document works also fine but you need to create a whole document in you program. So there’s a huge question how to provide user with possibility to influence the document?

Why not to have a tool which separates design and content parts like does SmartForms or PDF-based forms?

We have documents repository (t-code OAOR) and we have web-repository (t-code SMW0). Both have possibility to store MS Office documents and templates.

We have DOI and OLE tools to manipulate document.

We want to separate development and design stages to make documents flexible.

Desired result is when developer creates a data-extraction report which includes simple call of MS Office document template. This template filled with data extracted by rules described simply and placed into the document. So a functional consultant without developer-key can manipulate design of this document at any time.

Imagine you’ve created a report that gets FI document with its positions. It’s very simple: get the BKPF record and correspondent positions from BSEG. Here are two types of data: structure (BKPF single line) and table type (BSEG positions). Then report calls document via some tool and this FI document is represented with some layout. On the other side a consultant can instantly change any parameter of the document: field’s order of described BKPF structure and their presence, column order of table content and their presence. So, while you have the simple report to extract data you can have different results with possibility to change layout even at production system directly.

Source code listed below will let you use a simple code to fill complex documents. Example of use is:

DATA: BEGIN OF interface,
bkpf  
TYPE bkpf,
bseg_t
TYPE TABLE OF bseg,
END OF interface,
lref_doi
TYPE REF TO i_oi_document_proxy.

*  Some data extraction
lref_doi
= zcl_bas_utilities=>get_doi_doc_from_so( 'FI_DOC_TEMPLATE' ).
zcl_bas_utilities
=>put_data_by_intf_into_names( ir_doi       = lref_doi
is_interface
= interface ).
message 'Save document before press `OK`!' TYPE 'I'.

 

Fields mapping defined by range names (for MS Excel) or bookmarks (for MS Word). For example: ‘BKPF_1’ to output the first field of structure BKPF or ‘BKPF_STBLG’ to output value of field STBLG of structure BKPF. To create column order for BSEG table we should name range like this: ‘BSEG_2_3_BETRG’. This range name will describe filling table with 3 columns of second, third and BETRG fields of table.

  Here is my code to get this tool

 

 

 

Class ZCL_BAS_UTILITIES.

Common part:

 

class ZCL_BAS_UTILITIES definition
public
final
create public .

public section.
*"* public components of class ZCL_BAS_UTILITIES
*"* do not include other source files here!!!
type-pools CNTL .
type-pools SBDST .
type-pools SLIS .

constants TRUE type CHAR01 value 'X'. "#EC NOTEXT
constants FALSE type CHAR01 value ' '. "#EC NOTEXT
constants ON type CHAR01 value '1'. "#EC NOTEXT
constants OFF type CHAR01 value '0'. "#EC NOTEXT

class-methods GET_DOI_DOC_FROM_SO
importing
!IV_DOCUMENT_NAME
type CLIKE
!IV_HIDE
type CHAR01 optional
returning
value(RR_DOI_DOC) type ref to I_OI_DOCUMENT_PROXY .
class-methods INSERT_TABLE_INTO_NAMED_RANGE
importing
!IR_DOCUMENT
type ref to I_OI_DOCUMENT_PROXY
!IT_TABLE
type STANDARD TABLE
!IV_DICTYPE
type CLIKE optional
!IV_RANGENAME
type CLIKE .
class-methods FILL_VALUE_BY_RANGE_NAME
importing
!IV_RANGE_NAME
type CLIKE
!IS_FIELD
type ZHR_NAMEDESCR_WA optional
!IR_DOCUMENT
type ref to I_OI_DOCUMENT_PROXY
!IV_NEW_VALUE
type ANY
!IV_CONCATENATE
type CHAR01 default 'X' .

  class-methods GET_NAMES_FROM_DOI
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IV_STOR_OLE_OBJ
type CHAR01 default FALSE
returning
value(RT_NAMES) type ZHR_NAMEDESCR_ITAB .
class-methods OLE_FLUSH .
class-methods PUT_DATA_BY_INTF_INTO_NAMES
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IS_INTERFACE
type ANY .
class-methods SAVE_DOI
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IV_FILEPATH
type STRING optional
returning
value(RV_FILEPATH) type STRING .
class-methods OPEN_DOCUMENT
importing
!IV_FILEPATH
type STRING .
class-methods GET_PAGES
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
returning
value(RV_RESULT) type INT4 .

 

Private part:

 

private section.
*"* private components of class ZCL_BAS_UTILITIES
*"* do not include other source files here!!!

class-data FIELDS_TO_UPDATE type SOI_FORM_LIST .
class-data SEPARATOR type CHAR04 .
class-data GO_DOC type CNTL_HANDLE .
class-data GO_RANGE type OBJ_RECORD .
class-data GO_BR_CELL type OBJ_RECORD .
class-data GO_LT_CELL type OBJ_RECORD .
class-data GO_APL type OBJ_RECORD .
class-data GO_NAMES type OBJ_RECORD .
class-data GO_ACTIVESHEET type OBJ_RECORD .
class-data GO_SELECTION type OBJ_RECORD .

class-methods ADD_FIELD_VALUE
importing
!IS_FIELD
type ANY
!IV_VALUE
type ANY
!IV_CONCT
type CHAR01 default 'X' .
class-methods INITIALIZE_FIELD_TO_UPDATE .
class-methods UPDATE_FIELDS
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IT_FIELDS
type ZHR_NAMEDESCR_ITAB .
class-methods HIDE_DOI
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY .
class-methods FILL_VALUE_BY_BOOKMARK
importing
!IO_BOOKMARK
type OBJ_RECORD
!IV_NEW_VALUE
type ANY .
class-methods GET_WORD_TABLES
importing
!IO_DOCUMENT
type OBJ_RECORD
returning
value(RT_TABLES) type ZHR_WORDTABLE_ITAB .
class-methods INSERT_TAB_INTO_WORD_TAB
importing
!IT_TABLE
type STANDARD TABLE
!IR_WORD
type ref to I_OI_WORD_PROCESSOR_DOCUMENT
!IV_TAB_INDX
type ANY .
class-methods PUT_STR_FIELD_INT_BKMRK
importing
!IO_BOOKMARK
type OBJ_RECORD
!IT_FIELDS
type STANDARD TABLE
!IS_SOURCE
type ANY .
class-methods PUT_TABLE_INTO_BKMRK
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IT_FIELDS
type STANDARD TABLE
!IT_SOURCE
type STANDARD TABLE
!IV_TAB_INDX
type ANY .
class-methods PUT_THE_STRUCTURE
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IS_FIELD
type ZHR_NAMEDESCR_WA optional
!IT_FIELDS
type STANDARD TABLE
!IS_SOURCE
type ANY
!IV_FULL_NAME
type CLIKE .
class-methods PUT_THE_TABLE
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IT_FIELDS
type STANDARD TABLE
!IT_SOURCE
type STANDARD TABLE
!IV_FULL_NAME
type CLIKE .
class-methods GET_FORM_FIELDS
importing
!IR_FORM
type ref to I_OI_FORM
changing
!CT_NAMES
type ZHR_NAMEDESCR_ITAB .
class-methods GET_WORD_BOOKMARKS
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
changing
!CT_NAMES
type ZHR_NAMEDESCR_ITAB .
class-methods GET_XLS_FIELDS
importing
!IR_XLS
type ref to I_OI_SPREADSHEET
changing
!CT_NAMES
type ZHR_NAMEDESCR_ITAB .

Method’s code:

method GET_DOI_DOC_FROM_SO.
DATA: ls_bds_conn       TYPE bds_conn00,
lr_container_cont
TYPE REF TO i_oi_container_control,
lr_container     
TYPE REF TO cl_gui_custom_container,
lt_content       
TYPE sbdst_content,
lv_size          
TYPE i.

SELECT SINGLE classname classtype log_system object_key
INTO CORRESPONDING FIELDS OF ls_bds_conn
FROM bds_conn06  "Actually here can be any of bds_connNN DB tables
WHERE object_key = iv_document_name.
CHECK ls_bds_conn IS NOT INITIAL.
* Document exists

* Get document's content
cl_bds_document_set
=>get_with_table(
EXPORTING
logical_system
= ls_bds_conn-log_system
classname     
= ls_bds_conn-classname
classtype     
= ls_bds_conn-classtype
object_key    
= ls_bds_conn-object_key
CHANGING
content       
= lt_content ).

* Prepare control
c_oi_container_control_creator
=>get_container_control(
IMPORTING
control = lr_container_cont ).

CHECK lr_container_cont IS BOUND.

* Create GUI- connection
CREATE OBJECT lr_container
EXPORTING
container_name
= 'TECH_CONTAINER'
EXCEPTIONS
others         = 6.

CHECK lr_container IS BOUND.

*Initialize control
lr_container_cont
->init_control(
r3_application_name
= 'SAP'
parent             
= lr_container ).

* Initialize proxy
CALL METHOD lr_container_cont->get_document_proxy
EXPORTING
document_type 
= ''
IMPORTING
document_proxy
= rr_doi_doc.

*Fill document with data
rr_doi_doc
->open_document_from_table(
document_size
= lv_size
document_table
= lt_content ).

CHECK iv_hide is NOT INITIAL.
hide_doi
( rr_doi_doc ).
endmethod.

METHOD insert_table_into_named_range.
* Last change at 23 March 2012 by Guryanov Alexander
* Optimize rows insert to reduce dependence execution
* time from a size of the input table.
*  I've tried to reduce FLUSH commands but here is
*  the minimum.
DATA: lr_doi TYPE REF TO i_oi_document_proxy,
lr_xls
TYPE REF TO i_oi_spreadsheet,
lv_new_range
TYPE char80,
lt_fields
TYPE TABLE OF rfc_fields,
lv_lines 
TYPE i,
lv_address
TYPE char40,
lv_end_row
TYPE char20,
lv_end_column
TYPE char20,
lv_columns
TYPE i,
lv_cur_row
TYPE char20,
lv_cur_column
TYPE char20.
FIELD-SYMBOLS: <line> TYPE any.

CHECK it_table IS NOT INITIAL.

lr_doi
= ir_document.
lr_doi
->get_spreadsheet_interface( IMPORTING
sheet_interface
= lr_xls ).

CHECK lr_xls IS BOUND.
lr_doi
->get_document_handle( "EXPORTING NO_FLUSH = 'X'
IMPORTING handle = go_doc ).
GET PROPERTY OF go_doc-obj 'Application' = go_apl NO FLUSH"Get an Application object
* Calculate position of the named range
GET PROPERTY OF go_apl 'Range' = go_range
NO FLUSH
EXPORTING #1 = iv_rangename.
CALL METHOD OF go_apl 'GoTo' NO FLUSH  "
EXPORTING
#1    
= iv_rangename.
"Clear the range
GET PROPERTY OF go_range 'Cells' = go_names  "Get the first cell
NO FLUSH                                   "of the named range
EXPORTING
#1
= 1
#2
= 1.

GET PROPERTY OF go_names 'Address' = lv_address   "get its address
EXPORTING
#1
= 'True'              "absolute row address
#2
= 'True'              "absolute column address
#3
= -4150.              "RC format
CHECK lv_address IS NOT INITIAL.
SHIFT lv_address."Remove letter 'R'
SPLIT lv_address AT 'C' INTO lv_cur_row lv_cur_column.

* Calculate if some lines should be added
lv_lines
= lines( it_table ) - 1.
IF lv_lines > 0. "If we have some rows to add
*  Add number of table lines without one
lv_lines
= lv_lines + lv_cur_row - 1.

*  Get the right bottom cell of desired region
GET PROPERTY OF go_apl 'Rows' = go_br_cell
NO FLUSH
EXPORTING
#1
= lv_lines.

*  Calculate the left top cell of desired region
GET PROPERTY OF go_apl 'Rows' = go_lt_cell
NO FLUSH
EXPORTING
#1
= lv_cur_row.

CALL METHOD OF go_lt_cell 'Copy' NO FLUSH. "
*  Here is a range between left top and bottom right cells
GET PROPERTY OF go_apl 'Range' = go_range
NO FLUSH
EXPORTING
#1
= go_lt_cell
#2
= go_br_cell.

*  Insert correspondent lines
CALL METHOD OF go_range 'Insert' "
NO FLUSH
EXPORTING
#1      
= -4121
#2      
= '0'.
SET PROPERTY OF go_apl 'CutCopyMode' = 'False' NO FLUSH.
ENDIF.
GET PROPERTY OF go_apl 'Names' = go_names NO FLUSH.
CONCATENATE '=R' lv_cur_row 'C' lv_cur_column INTO lv_address.

GET TIME.
CONCATENATE iv_rangename sy-timlo
INTO lv_new_range.
CALL METHOD OF go_names 'Add'  "Create a new technical named range
NO FLUSH
EXPORTING
#1      
= lv_new_range    "generated name
#2      
= lv_address      "go_range        "For specified range
#3      
= 'False'.         "User will not see this name
*  Remove an "old" named range
GET PROPERTY OF go_names 'Item' = go_names NO FLUSH "Get named range
EXPORTING
#1
= iv_rangename.
CALL METHOD OF go_names 'Delete'. "Remove named range

CALL FUNCTION 'DP_GET_FIELDS_FROM_TABLE'
TABLES
data             = it_table
fields           = lt_fields
EXCEPTIONS
dp_invalid_table
= 1
OTHERS           = 2.

CALL METHOD lr_xls->insert_one_table
EXPORTING
data_table  
= it_table
fields_table
= lt_fields
rangename   
= lv_new_range
wholetable  
= '1'.

FREE OBJECT: go_selection,
go_names
,
go_apl
,
go_doc
-obj,
go_range
,
go_br_cell
,
go_lt_cell
,
go_activesheet
.
ENDMETHOD.

METHOD fill_value_by_range_name.
DATA: lr_doi TYPE REF TO i_oi_document_proxy,
lr_xls
TYPE REF TO i_oi_spreadsheet,
lv_new_range
TYPE char80,
lv_oldval   
TYPE text452,
lv_newval   
TYPE text452.
FIELD-SYMBOLS: <line> TYPE any.

*  IF is_field IS NOT INITIAL.
*    add_field_value( is_field = is_field
*                     iv_value = iv_new_value
*                     iv_conct = iv_concatenate ).
*    RETURN.
*  ENDIF.

lr_doi
= ir_document.
lr_doi
->get_spreadsheet_interface( IMPORTING
sheet_interface
= lr_xls ).

CHECK lr_xls IS BOUND.
lr_doi
->get_document_handle( "EXPORTING NO_FLUSH = 'X'
IMPORTING handle = go_doc ).
GET PROPERTY OF go_doc-obj 'Application' = go_apl NO FLUSH.
GET PROPERTY OF go_apl 'Range' = go_range
NO FLUSH
EXPORTING
#1
= iv_range_name .
IF iv_concatenate = 'X'.
lv_newval
= iv_new_value.
GET PROPERTY OF go_range 'Value' = lv_oldval.
IF lv_oldval IS NOT INITIAL.
CONCATENATE lv_oldval lv_newval
INTO
lv_oldval
SEPARATED BY space.
ELSE.
lv_oldval
= lv_newval.
ENDIF.

SET PROPERTY OF go_range 'Value' = lv_oldval.
ELSE.
SET PROPERTY OF go_range 'Value' = iv_new_value.
ENDIF.

FREE OBJECT:
go_range
,
go_apl
,
go_doc
-obj.
ENDMETHOD.

method GET_NAMES_FROM_DOI.
DATA: lr_form   TYPE REF TO i_oi_form,
lr_xls   
TYPE REF TO i_oi_spreadsheet,
lr_word  
TYPE REF TO I_OI_WORD_PROCESSOR_DOCUMENT.
*        lt_fields TYPE soi_form_list.
FIELD-SYMBOLS: <field> TYPE LINE OF soi_form_list,
<name> 
LIKE LINE OF rt_names.

CHECK ir_doi IS BOUND.
*  Get form interface (common interface)
ir_doi
->get_form_interface( IMPORTING f_interface = lr_form ).
*  Fill names for common interface
get_form_fields
( EXPORTING ir_form = lr_form
CHANGING ct_names = rt_names ).
*  Get spreadsheet interface
ir_doi
->get_spreadsheet_interface( IMPORTING sheet_interface = lr_xls ).
*  Fill names for Excel document
get_xls_fields
( EXPORTING ir_xls   = lr_xls
CHANGING  ct_names = rt_names ).
*  Get wordprocessor interface
*  ir_doi->get_wordprocessor_interface( IMPORTING wp_interface = lr_word ).
get_word_bookmarks
( EXPORTING ir_doi  = ir_doi
CHANGING  ct_names = rt_names ).

endmethod.

method OLE_FLUSH.
CALL FUNCTION 'FLUSH'
EXCEPTIONS
cntl_system_error
= 1
cntl_error       
= 2
OTHERS            = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
endmethod.

METHOD put_data_by_intf_into_names.
DATA: lt_names      TYPE zhr_namedescr_itab,
lr_typedescr 
TYPE REF TO cl_abap_typedescr,
lr_tabledescr
TYPE REF TO cl_abap_tabledescr,
lr_linedescr 
TYPE REF TO cl_abap_typedescr,
lt_fields    
TYPE TABLE OF string,
ls_field     
type LINE OF zhr_namedescr_itab.

FIELD-SYMBOLS: <name>  LIKE LINE OF lt_names,
<field>
TYPE string,
<any1> 
TYPE any,
<any2> 
TYPE any.
lt_names
= get_names_from_doi( ir_doi ).
CHECK lt_names IS NOT INITIAL.
initialize_field_to_update
( ).
LOOP AT lt_names ASSIGNING <name>
WHERE kind <> 'FLD'.
CLEAR lt_fields.
READ TABLE lt_names
with key kind = 'FLD'
name
= <name>-name
INTO
ls_field
.
IF sy-subrc <> 0.
clear ls_field.
ENDIF.
*    Check if such field exists in interface
ASSIGN COMPONENT <name>-name OF STRUCTURE is_interface TO <any1>.
IF sy-subrc = 0.
APPEND INITIAL LINE TO lt_fields ASSIGNING <field>.
<field>
= <name>-name.
ELSE.
*  Get named range's name for ex. TAB1_1_3_SOMEFIELD
*  And split it into table: TAB1/ 1/ 3/ SOMEFIELD
SPLIT <name>-name AT '_' INTO TABLE lt_fields.
ENDIF.
*  So the first line of this table should be a field of the interface is_interface
READ TABLE lt_fields ASSIGNING <field> INDEX 1.
CHECK <field> is ASSIGNED.
ASSIGN COMPONENT <field> OF STRUCTURE is_interface TO <any1>.
CHECK sy-subrc = 0.
lr_typedescr
= cl_abap_typedescr=>describe_by_data( <any1> ).
DELETE lt_fields INDEX 1.      "Remove structure/table/element name
CASE lr_typedescr->kind.
WHEN cl_abap_typedescr=>kind_elem. "Simple field
IF <name>-kind = 'RNGE'. "Excel Range name
fill_value_by_range_name
( iv_range_name = <name>-name
ir_document  
= ir_doi
is_field     
= ls_field
iv_new_value 
= <any1> ).
ELSEIF <name>-kind = 'BKMRK'"Word bookmark
fill_value_by_bookmark
( io_bookmark  = <name>-ole_obj
iv_new_value
= <any1> ).
ENDIF.

WHEN cl_abap_typedescr=>kind_struct.
IF <name>-kind = 'RNGE'. "Excel Range name
put_the_structure
( ir_doi    = ir_doi
it_fields
= lt_fields
is_source
= <any1>
iv_full_name
= <name>-name ).
ELSEIF <name>-kind = 'BKMRK'"Word bookmark
put_str_field_int_bkmrk
( io_bookmark = <name>-ole_obj
it_fields  
= lt_fields
is_source  
= <any1> ).
ENDIF.

WHEN cl_abap_typedescr=>kind_table.
IF <name>-kind = 'RNGE'. "Excel Range name
put_the_table
( ir_doi    = ir_doi
it_fields
= lt_fields
it_source
= <any1>
iv_full_name
= <name>-name ).
ELSEIF <name>-kind = 'WRDTAB'"Word table
put_table_into_bkmrk
( ir_doi      = ir_doi          "Reference to a document proxy
it_fields  
= lt_fields       "Desired fields from table
it_source  
= <any1>          "A table to transfer into a word table
iv_tab_indx
= <name>-value ). "Table index
ENDIF.
WHEN OTHERS.
ENDCASE.
CLEAR lt_fields.
ENDLOOP.

update_fields
( ir_doi    = ir_doi
it_fields
= lt_names ).
ENDMETHOD.

METHOD save_doi.
DATA: lv_filepath TYPE char255,
lv_sapdir  
TYPE string.
CHECK ir_doi IS BOUND.
IF iv_filepath IS NOT INITIAL.
lv_filepath
= iv_filepath.
ELSE.
cl_gui_frontend_services
=>get_sapgui_workdir( CHANGING sapworkdir lv_sapdir
EXCEPTIONS OTHERS = 4 ).
CALL FUNCTION 'FLUSH'
EXCEPTIONS
OTHERS = 0.

*    CHECK sy-subrc = 0.
IF lv_sapdir IS INITIAL OR sy-subrc <> 0.
cl_gui_frontend_services
=>get_desktop_directory(
CHANGING desktop_directory lv_sapdir ).
*      lv_sapdir = 'C:'.
CALL FUNCTION 'FLUSH'
EXCEPTIONS
OTHERS = 0.
ENDIF.
GET TIME.
ir_doi
->get_document_type( IMPORTING document_type = lv_filepath ).
IF lv_filepath(5) = 'Excel'.
lv_filepath
= lv_sapdir && '\' && sy-uname && sy-datum && sy-timlo && '.xls'.
ELSE.
lv_filepath
= lv_sapdir && '\' && sy-uname && sy-datum && sy-timlo && '.doc'.
ENDIF.
ENDIF.
CHECK lv_filepath IS NOT INITIAL.
ir_doi
->save_as( file_name = lv_filepath ).
rv_filepath
= lv_filepath.
CALL FUNCTION 'FLUSH'
EXCEPTIONS
OTHERS = 0.

ENDMETHOD.

METHOD open_document.
CHECK iv_filepath IS NOT INITIAL.
cl_gui_frontend_services
=>execute(
document 
= iv_filepath
maximized
= 'X' ).
ENDMETHOD.

METHOD get_pages.
DATA: lv_hanler TYPE cntl_handle.
ir_doi
->get_document_handle( EXPORTING no_flush = 'X'
IMPORTING handle   = lv_hanler ).
GET PROPERTY OF lv_hanler-obj 'ActiveSheet' = go_activesheet NO FLUSH.
GET PROPERTY OF go_activesheet 'PageSetup' = go_apl NO FLUSH.
GET PROPERTY OF go_apl 'Pages' = go_range NO FLUSH.
GET PROPERTY OF go_range 'Count' = rv_result.
FREE OBJECT: go_range, go_apl, go_activesheet.
ADD 1 TO rv_result.
ENDMETHOD.

 

METHOD add_field_value.
DATA: ls_field TYPE LINE OF soi_form_list,
lv_field
TYPE char200.
FIELD-SYMBOLS: <field> TYPE LINE OF soi_form_list,
<clike>
TYPE c.

MOVE-CORRESPONDING is_field TO ls_field.
ls_field
-type   = 'T'.
ls_field
-number = '1'.
ls_field
-code   = '0'.
IF iv_conct IS INITIAL.
write iv_value to ls_field-value LEFT-JUSTIFIED.
*    ls_field-value = iv_value.
ELSE.
WRITE iv_value to lv_field LEFT-JUSTIFIED.
*    lv_field = iv_value.
CONCATENATE ls_field-value lv_field INTO ls_field-value SEPARATED BY space.
*    TRY .
*        ASSIGN iv_value TO <clike> CASTING.
*        CONCATENATE ls_field-value <clike> INTO ls_field-value SEPARATED BY space.
*      CATCH cx_sy_assign_cast_illegal_cast .
*        WRITE iv_value TO lv_field LEFT-JUSTIFIED.
*        CONDENSE lv_field.
*        CONCATENATE ls_field-value lv_field INTO ls_field-value SEPARATED BY space.
*    ENDTRY.

ENDIF.
APPEND ls_field TO fields_to_update.
*  MODIFY TABLE fields_to_update FROM ls_field.
ENDMETHOD.

METHOD initialize_field_to_update.
CLEAR fields_to_update.
ENDMETHOD.

METHOD update_fields.
DATA: lr_form TYPE REF TO i_oi_form,
lt_fields
TYPE soi_form_list.
FIELD-SYMBOLS: <field>  TYPE LINE OF soi_form_list,
<update>
LIKE LINE OF fields_to_update.
CHECK fields_to_update IS NOT INITIAL.
*  ir_doi->get_form_interface( EXPORTING no_flush = 'X'
*                              IMPORTING f_interface = lr_form ).
*  lr_form->synchronize_fields( no_flush = 'X' ).
*  lr_form->get_data( IMPORTING fields = lt_fields ).
*  LOOP AT lt_fields ASSIGNING <field>.
*    READ TABLE fields_to_update WITH KEY name = <field>-name ASSIGNING <update>.
*    IF sy-subrc <> 0.
*      APPEND INITIAL LINE TO fields_to_update ASSIGNING <update>.
*      MOVE-CORRESPONDING <field> TO <update>.
*      <update>-type   = 'T'.
*      <update>-number = '1'.
*      <update>-code   = '0'.
*    ENDIF.
*  ENDLOOP.

ir_doi
->get_form_interface( EXPORTING no_flush = 'X'
IMPORTING f_interface = lr_form ).
lr_form
->set_data( fields = fields_to_update
CLEAR = ' ' ).
*  lr_form->synchronize_fields( ).
CLEAR fields_to_update.
ENDMETHOD.

METHOD hide_doi.
DATA: lv_hanler TYPE cntl_handle.
ir_doi
->get_document_handle( EXPORTING no_flush = 'X'
IMPORTING handle   = lv_hanler ).
GET PROPERTY OF lv_hanler-obj 'Application' = go_apl NO FLUSH.
SET PROPERTY OF go_apl 'Visible' = 'False' NO FLUSH.
SET PROPERTY OF go_apl 'DisplayAlerts' = 'False'.
FREE OBJECT go_apl.
ENDMETHOD.

METHOD fill_value_by_bookmark.
GET PROPERTY OF io_bookmark 'Range' = go_range NO FLUSH.
SET PROPERTY OF go_range 'Text' = iv_new_value.

FREE OBJECT: go_range.
ENDMETHOD.

METHOD get_word_tables.
DATA: lv_count TYPE i,
lo_table
TYPE obj_record.
FIELD-SYMBOLS: <table> LIKE LINE OF rt_tables.
GET PROPERTY OF io_document 'Tables' = go_activesheet NO FLUSH.
GET PROPERTY OF go_activesheet 'Count' = lv_count.
DO lv_count TIMES.
APPEND INITIAL LINE TO rt_tables ASSIGNING <table>.
<table>
-indx = sy-tabix.
GET PROPERTY OF go_activesheet 'Item' = lo_table
EXPORTING
#1
= sy-index.
CHECK sy-subrc = 0.
<table>
-ole_obj = lo_table.
ENDDO.
FREE OBJECT: lo_table,
go_activesheet
.
ENDMETHOD.

METHOD insert_tab_into_word_tab.
DATA: lr_str_descr  TYPE REF TO cl_abap_structdescr,
lt_str_fields
TYPE ddfields,
lt_columns   
TYPE soi_colnames_table,
lv_doctab_no 
TYPE i.
FIELD-SYMBOLS: <field> TYPE dfies,
<line> 
TYPE any,
<table_line>
TYPE any.
READ TABLE it_table ASSIGNING <table_line> INDEX 1.
CHECK <table_line> IS ASSIGNED.
lr_str_descr ?= cl_abap_structdescr
=>describe_by_data( <table_line> ).
CHECK lr_str_descr IS BOUND.
lt_str_fields
= lr_str_descr->get_ddic_field_list( ). "Here can be dump due to exceptions section omitted
LOOP AT lt_str_fields ASSIGNING <field>.
APPEND INITIAL LINE TO lt_columns ASSIGNING <line>.
<line>
= <field>-fieldname.
ENDLOOP.
lv_doctab_no
= iv_tab_indx.
ir_word
->insert_table2(
data_table
= it_table
info_col_table 
= lt_columns
lowerbound     
= "Whole table
upperbound     
= " whole table
doctable_number
= lv_doctab_no
clearoption    
= "Clear content
startrow       
= "From the first row
varsize        
= 'X' ). "Any rows number
ENDMETHOD.

method PUT_STR_FIELD_INT_BKMRK.
*  This method will put just one field of a structure
*  into the bookmark
FIELD-SYMBOLS: <field>  type any,
<source>
type any.
LOOP AT it_fields ASSIGNING <field>.
ASSIGN COMPONENT <field> OF STRUCTURE is_source to <source>.
IF <source> is ASSIGNED.
exit. "Here we've found soume field from a list of fields at the source structure
ENDIF.
ENDLOOP.
CHECK <source> is ASSIGNED.
fill_value_by_bookmark
( io_bookmark  = io_bookmark
iv_new_value
= <source> ).
endmethod.

METHOD put_table_into_bkmrk.
*  This method should create a local version of the table if some fields specified
*  Otherwise it should put a whole table into the document
DATA: lr_str_descr TYPE REF TO cl_abap_structdescr,
lt_str_fields
TYPE ddfields,
lv_index     
TYPE i,
lt_target_struct
TYPE zhr_typedescr_itab,
ld_target       
TYPE REF TO data,
lr_word         
TYPE REF TO i_oi_word_processor_document.
FIELD-SYMBOLS: <table_line> TYPE any,
<field>     
TYPE any,
<any>       
TYPE any,
<any1>      
TYPE any,
<any_tab>   
TYPE STANDARD TABLE,
<str_field> 
TYPE dfies,
<target_str>
LIKE LINE OF lt_target_struct.

READ TABLE it_source ASSIGNING <table_line> INDEX 1.
CHECK <table_line> IS ASSIGNED. "No sense to continue if no data to put

ir_doi
->get_wordprocessor_interface( IMPORTING wp_interface = lr_word ). "Get word interface
CHECK lr_word IS BOUND. "No sense to continue without the Word

IF it_fields IS INITIAL. "No fields specified
insert_tab_into_word_tab
( it_table = it_source
ir_word 
= lr_word
iv_tab_indx
= iv_tab_indx ).
ELSE.
*  Create fields list
lr_str_descr ?= cl_abap_structdescr
=>describe_by_data( <table_line> ).
CHECK lr_str_descr IS BOUND.
lt_str_fields
= lr_str_descr->get_ddic_field_list( ). "Here can be dump due to exceptions section omitted
LOOP AT it_fields ASSIGNING <field>.
CHECK <field> IS NOT INITIAL.
READ TABLE lt_str_fields WITH KEY fieldname = <field> ASSIGNING <str_field>.
IF sy-subrc <> 0.
TRY.
MOVE <field> TO lv_index.
CATCH cx_sy_conversion_no_number .
CONTINUE.
ENDTRY.
READ TABLE lt_str_fields ASSIGNING <str_field> INDEX lv_index.
CHECK sy-subrc = 0.
ENDIF.
APPEND INITIAL LINE TO lt_target_struct ASSIGNING <target_str>.
<target_str>
-field_name = <str_field>-fieldname.
CONCATENATE <str_field>-tabname '-' <str_field>-fieldname
INTO <target_str>-field_type.

ENDLOOP.
ld_target
= create_dyn_table( lt_target_struct ).
CHECK ld_target IS BOUND.
ASSIGN ld_target->* TO <any_tab>.
CHECK sy-subrc = 0.
LOOP AT it_source ASSIGNING <any>.
APPEND INITIAL LINE TO <any_tab> ASSIGNING <any1>.
MOVE-CORRESPONDING <any> TO <any1>.
ENDLOOP.
insert_tab_into_word_tab
( it_table = <any_tab>
ir_word 
= lr_word
iv_tab_indx
= iv_tab_indx ).
ENDIF.
ENDMETHOD.

method PUT_THE_STRUCTURE.
*  This method will put just one field of a structure
*  into the named range
FIELD-SYMBOLS: <field>  type any,
<source>
type any.
LOOP AT it_fields ASSIGNING <field>.
ASSIGN COMPONENT <field> OF STRUCTURE is_source to <source>.
IF <source> is ASSIGNED.
exit. "Here we've found some field from a list of fields at the source structure
ENDIF.
ENDLOOP.
CHECK <source> is ASSIGNED.
fill_value_by_range_name
( iv_range_name = iv_full_name
ir_document  
= ir_doi
iv_new_value 
= <source> ).
endmethod.

METHOD put_the_table.
*  This method should create a local version of the table if some fields specified
*  Otherwise it should put a whole table into the document
DATA: lr_str_descr TYPE REF TO cl_abap_structdescr,
lt_str_fields
TYPE ddfields,
lv_index     
TYPE i,
lt_target_struct
TYPE zhr_typedescr_itab,
ld_target       
TYPE REF TO data,
lt_fcat         
TYPE lvc_t_fcat.
FIELD-SYMBOLS: <table_line> TYPE any,
<field>     
TYPE any,
<any>       
TYPE any,
<any1>      
TYPE any,
<any_tab>   
TYPE STANDARD TABLE,
<str_field> 
TYPE dfies,
<target_str>
LIKE LINE OF lt_target_struct,
<fline>     
TYPE LINE OF lvc_t_fcat,
<component> 
TYPE abap_compdescr.

READ TABLE it_source ASSIGNING <table_line> INDEX 1.
CHECK <table_line> IS ASSIGNED. "No sense to continue if no data to put

IF it_fields IS INITIAL. "No fields specified
insert_table_into_named_range
( ir_document = ir_doi
it_table   
= it_source
iv_rangename
= iv_full_name ).
ELSE.
*  Create fields list
lr_str_descr ?= cl_abap_structdescr
=>describe_by_data( <table_line> ).
CHECK lr_str_descr IS BOUND.
LOOP AT it_fields ASSIGNING <field>.
CHECK <field> IS NOT INITIAL.
READ TABLE lr_str_descr->components WITH KEY name = <field> ASSIGNING <component>.
IF sy-subrc <> 0.
TRY.
MOVE <field> TO lv_index.
CATCH cx_sy_conversion_no_number .
CONTINUE.
ENDTRY.
READ TABLE lr_str_descr->components ASSIGNING <component> INDEX lv_index.
CHECK sy-subrc = 0.
ENDIF.
APPEND INITIAL LINE TO lt_fcat ASSIGNING <fline>.
<fline>
-fieldname = <component>-name.
<fline>
-datatype  = <component>-type_kind.
<fline>
-inttype   = <component>-type_kind.
<fline>
-intlen    = <component>-length.
<fline>
-decimals  = <component>-decimals.
ENDLOOP.
cl_alv_table_create
=>create_dynamic_table(
EXPORTING
it_fieldcatalog 
= lt_fcat
i_length_in_byte
= 'X'
IMPORTING
ep_table
= ld_target ).
CHECK ld_target IS BOUND.
ASSIGN ld_target->* TO <any_tab>.
CHECK sy-subrc = 0.
LOOP AT it_source ASSIGNING <any>.
APPEND INITIAL LINE TO <any_tab> ASSIGNING <any1>.
MOVE-CORRESPONDING <any> TO <any1>.
ENDLOOP.
insert_table_into_named_range
( ir_document = ir_doi
it_table   
= <any_tab>
iv_rangename
= iv_full_name ).
ENDIF.
ENDMETHOD.

method GET_FORM_FIELDS.
data: lt_fields TYPE soi_form_list.
FIELD-SYMBOLS: <field> type line of SOI_FORM_LIST,
<name> 
like LINE OF ct_names.

CHECK ir_form IS BOUND.
ir_form
->get_form_fields( IMPORTING fields = lt_fields ).
LOOP AT lt_fields ASSIGNING <field>.
APPEND INITIAL LINE TO ct_names ASSIGNING <name>.
MOVE-CORRESPONDING <field> to <name>. "Fill name and value
<name>
-kind = 'FLD'.                  "Domain value could be a reason of dumps if other values ranges determined

ENDLOOP.
endmethod.

METHOD get_word_bookmarks.
* Here's nothing to do actually due to no tools to get bookmarks from a word interface
* A Document ole reference could be used to get this info by Bookmarks collection

DATA: lv_count TYPE i,
lv_name 
TYPE text128,
lt_word_tables
TYPE zhr_wordtable_itab,
lv_cur_indx   
TYPE i.
FIELD-SYMBOLS: <name> LIKE LINE OF ct_names,
<wrdtab>
LIKE LINE OF lt_word_tables.
ir_doi
->get_document_handle( EXPORTING no_flush = 'X'
IMPORTING handle = go_doc ).
GET PROPERTY OF go_doc-obj 'Bookmarks' = go_names NO FLUSH.
GET PROPERTY OF go_names 'Count' = lv_count.
DO lv_count TIMES.
GET PROPERTY OF go_names 'Item' = go_range
NO FLUSH
EXPORTING
#1
= sy-index.
APPEND INITIAL LINE TO ct_names ASSIGNING <name>.
GET PROPERTY OF go_range 'Name' = <name>-name.
<name>
-kind = 'BKMRK'.   "Word bookmark
<name>
-ole_obj = go_range.
ENDDO.
FREE OBJECT: go_selection, go_br_cell, go_lt_cell, go_range, go_names.
CLEAR lv_count.
GET PROPERTY OF go_doc-obj 'Tables' = go_names NO FLUSH.
GET PROPERTY OF go_names 'Count' = lv_count.
DO lv_count TIMES.
*    ActiveDocument.Tables(i).Range.Bookmarks(1) = TableName
lv_cur_indx
= sy-index.
GET PROPERTY OF go_names 'Item' = go_selection
NO FLUSH
EXPORTING
#1
= lv_cur_indx.
GET PROPERTY OF go_selection 'Range' = go_range NO FLUSH.
GET PROPERTY OF go_range 'Bookmarks' = go_br_cell NO FLUSH.
GET PROPERTY OF go_br_cell 'Item' = go_lt_cell
NO FLUSH
EXPORTING
#1
= 1.
GET PROPERTY OF go_lt_cell 'Name' = lv_name.
CHECK sy-subrc = 0"Bookmark for table exists
APPEND INITIAL LINE TO ct_names ASSIGNING <name>.
<name>
-name = lv_name.
<name>
-kind = 'WRDTAB'.   "Word bookmark
<name>
-value = lv_cur_indx.
ENDDO.
*  FREE OBJECT: go_selection, go_br_cell, go_lt_cell, go_range, go_names.
FREE OBJECT: go_selection,
go_names
,
go_apl
,
go_doc
-obj,
go_range
,
go_br_cell
,
go_lt_cell
,
go_activesheet
.
ENDMETHOD.

method GET_XLS_FIELDS.
DATA: lt_ranges TYPE soi_range_list.
FIELD-SYMBOLS: <field> TYPE LINE OF soi_range_list,
<name> 
LIKE LINE OF ct_names.

CHECK ir_xls IS BOUND.
ir_xls
->get_ranges_names( IMPORTING ranges = lt_ranges ).
LOOP AT lt_ranges ASSIGNING <field>.
APPEND INITIAL LINE TO ct_names ASSIGNING <name>.
MOVE-CORRESPONDING <field> TO <name>. "Fill name
<name>
-kind = 'RNGE'.                 "Domain value could be a reason of dumps if other values ranges determined
*   Will not fill object value due to interface bounds
ENDLOOP.
endmethod.

 

Also you’ll need to create types:

ZHR_NAMEDESCR_ITAB (table type of ZHR_NAMEDESCR_WA)
ZHR_NAMEDESCR_WA (structure):
NAME                  CHAR128

KIND                     CHAR6

VALUE                  CHAR255

OLE_OBJ             OBJ_RECORD

ZHR_TYPEDESCR_ITAB (table type of ZHR_TYPEDESCR_WA)

ZHR_TYPEDESCR_WA (structure):

FIELD_NAME                     CHAR40

FIELD_TYPE                       CHAR100

ZHR_WORDTABLE_ITAB (table type of ZHR_WORDTABLE_WA)

ZHR_WORDTABLE_WA (structure):

INDX                     INT4

OLE_OBJ             OBJ_RECORD

Displaying an ALV Grid in Popup Screen with Custom Buttons

$
0
0

In some cases, we might came across a requirement for displaying an ALV Grid in popup screen where we need to select few records and then perform certain function based on selected data. For choosing which function we need to perform, we required custom buttons on the Popup screen. For achieving this requirement, I have created a factory class (ZCL_ALV_POPUP), for using it following things need to be remember:

 

FACTORY Method:

  • It returns the instance of the popup class.
  • For data to be displayed in ALV grid we need to pass an internal table in IT_DATA parameter.
  • For adding the custom buttons we can pass the PF-Status and its program name and whenever custom button is clicked, it raises an event button_click by exporting function code of button and internal table for selected data.
  • For multiple selection of data in ALV, we need to pass IV_MULTI_SELECT as abap_true else abap_false for single selection.

DISPLAY Method:

  • For displaying the popup we need to need to pass the coordinates. 

 

 

CLASS DEFINITION

 

class ZCL_ALV_POPUP definition
  public
  final
  create private .

public section.

  constants MC_FUNC_REFRESH type SALV_DE_FUNCTION value '&REFRS'. "#EC NOTEXT
  constants MC_FUNC_SELECTALL type SALV_DE_FUNCTION value '&SELECT'. "#EC NOTEXT
  constants MC_FUNC_DESELECTALL type SALV_DE_FUNCTION value '&DESELECT'. "#EC NOTEXT

  events BUTTON_CLICK
    exporting
      value(EV_SALV_FUNCTION) type SALV_DE_FUNCTION
      value(ET_SELECTED_DATA) type TABLE .

  type-pools ABAP .


  methods CONSTRUCTOR
    importing
      !IT_DATA type TABLE
      !IV_PROG_NAME type SYREPID optional
      !IV_PF_STATUS type SYPFKEY optional
      !IV_MULTI_SELECT type ABAP_BOOL optional .


  class-methods FACTORY
    importing
      !IT_DATA type TABLE
      !IV_PROG_NAME type SYREPID optional
      !IV_PF_STATUS type SYPFKEY optional
      !IV_MULTI_SELECT type ABAP_BOOL default ABAP_TRUE
    returning
      value(R_ALV_POPUP) type ref to ZCL_ALV_POPUP .


  methods DISPLAY
    importing
      !IV_START_COLUMN type I
      !IV_START_LINE type I
      !IV_END_COLUMN type I optional
      !IV_END_LINE type I optional .


  PROTECTED SECTION.

 

 

 


  PRIVATE SECTION.

 

 

    DATA mr_alv_data TYPE REF TO data .
    DATA mr_table_type TYPE REF TO cl_abap_tabledescr .
    DATA mr_alv TYPE REF TO cl_salv_table .
    DATA mv_multi_select TYPE abap_bool .
    DATA mv_prog_name TYPE syrepid .
    DATA mv_pf_status TYPE sypfkey .

 

    METHODS assign_alv_data
      IMPORTING
        !it_data TYPE table
      EXPORTING
        !er_data TYPE REF TO data
        !er_table_type TYPE REF TO cl_abap_tabledescr .

 


    METHODS get_selected_data
      EXPORTING
        value(et_data) TYPE table .

 


    METHODS select_all
      IMPORTING
        !iv_value TYPE abap_bool DEFAULT abap_true .

 


    METHODS on_link_click
      FOR EVENT link_click OF cl_salv_events_table
      IMPORTING
        !row
        !column .

 


    METHODS on_user_command
      FOR EVENT added_function OF cl_salv_events
      IMPORTING
        !e_salv_function .


ENDCLASS.

 

 

CLASS IMPLEMENTATION

 

   CLASS ZCL_ALV_POPUP IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->ASSIGN_ALV_DATA
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_DATA                        TYPE        TABLE
* | [<---] ER_DATA                        TYPE REF TO DATA
* | [<---] ER_TABLE_TYPE                  TYPE REF TO CL_ABAP_TABLEDESCR
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD assign_alv_data.

    DATA:
      lr_tdata TYPE REF TO data,
      lr_sdata TYPE REF TO data,
      lr_type TYPE REF TO cl_abap_typedescr,
      lr_table TYPE REF TO cl_abap_tabledescr,
      lr_struct TYPE REF TO cl_abap_structdescr,
      lt_field TYPE cl_abap_structdescr=>component_table,
      lt_final TYPE cl_abap_structdescr=>component_table,
      ls_final TYPE LINE OF cl_abap_structdescr=>component_table.

    FIELD-SYMBOLS: <fs> TYPE any,
                   <fs_t_data> TYPE STANDARD TABLE,
                   <fs_s_data> TYPE any.

    CLEAR: er_data, er_table_type.

    ASSIGN it_data TO <fs>.
    GET REFERENCE OF <fs> INTO lr_tdata.

    cl_abap_tabledescr=>describe_by_data_ref(
      EXPORTING
        p_data_ref           = lr_tdata
      RECEIVING
        p_descr_ref          = lr_type
      EXCEPTIONS
        reference_is_initial = 1
        OTHERS               = 2
           ).
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.

    er_table_type ?= lr_type.
    CHECK er_table_type IS BOUND.

    lr_struct ?= er_table_type->get_table_line_type( ).
    CHECK lr_struct IS BOUND.

    lt_field = lr_struct->get_components( ).

    CLEAR: ls_final, lr_struct, lr_table.
    ls_final-name = 'CHOOSE'.
    ls_final-type ?= cl_abap_datadescr=>describe_by_name( 'XFELD' ).
    APPEND ls_final TO lt_final.
    APPEND LINES OF lt_field TO lt_final.

    lr_struct = cl_abap_structdescr=>create( lt_final ).
    lr_table  = cl_abap_tabledescr=>create( lr_struct ).

    CREATE DATA me->mr_alv_data TYPE HANDLE lr_table.
    CREATE DATA lr_sdata TYPE HANDLE lr_struct.

    ASSIGN me->mr_alv_data->* TO <fs_t_data>.
    ASSIGN lr_sdata->* TO <fs_s_data>.

    LOOP AT it_data ASSIGNING <fs>.
      CLEAR <fs_s_data>.
      MOVE-CORRESPONDING <fs> TO <fs_s_data>.
      APPEND <fs_s_data> TO <fs_t_data>.
    ENDLOOP.

    GET REFERENCE OF <fs_t_data> INTO er_data.

  ENDMETHOD.                    "ASSIGN_ALV_DATA


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_ALV_POPUP->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_DATA                        TYPE        TABLE
* | [--->] IV_PROG_NAME                   TYPE        SYREPID(optional)
* | [--->] IV_PF_STATUS                   TYPE        SYPFKEY(optional)
* | [--->] IV_MULTI_SELECT                TYPE        ABAP_BOOL(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD constructor.

    CLEAR: me->mr_alv,
           me->mr_alv_data,
           me->mr_table_type,
           me->mv_pf_status,
           me->mv_prog_name,
           me->mv_multi_select.

    me->mv_pf_status    = iv_pf_status.
    me->mv_prog_name    = iv_prog_name.
    me->mv_multi_select = iv_multi_select.

    me->assign_alv_data(
      EXPORTING
        it_data       = it_data
      IMPORTING
        er_data       = me->mr_alv_data
        er_table_type = me->mr_table_type
             ).

  ENDMETHOD.                    "constructor


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_ALV_POPUP->DISPLAY
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_START_COLUMN                TYPE        I
* | [--->] IV_START_LINE                  TYPE        I
* | [--->] IV_END_COLUMN                  TYPE        I(optional)
* | [--->] IV_END_LINE                    TYPE        I(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD display.

    DATA:
      lr_functions  TYPE REF TO cl_salv_functions_list,
      lr_columns    TYPE REF TO cl_salv_columns,
      lr_column     TYPE REF TO cl_salv_column_table,
      lr_selections TYPE REF TO cl_salv_selections,
      lr_events     TYPE REF TO cl_salv_events_table.

    FIELD-SYMBOLS <fs_t_data> TYPE STANDARD TABLE.

    ASSIGN me->mr_alv_data->* TO <fs_t_data>.

    TRY.
        cl_salv_table=>factory(
          IMPORTING
            r_salv_table = me->mr_alv
          CHANGING
            t_table      = <fs_t_data> ).
      CATCH cx_salv_msg.                                "#EC NO_HANDLER
    ENDTRY.

    lr_functions = me->mr_alv->get_functions( ).
    lr_functions->set_all( if_salv_c_bool_sap=>true ).

    lr_columns = me->mr_alv->get_columns( ).
    lr_columns->set_optimize( if_salv_c_bool_sap=>true ).

    TRY.
        lr_column ?= lr_columns->get_column( 'CHOOSE' ).
        lr_column->set_cell_type( if_salv_c_cell_type=>checkbox_hotspot ).
        lr_column->set_short_text( 'Choose'(t01) ).
        lr_column->set_medium_text( 'Choose'(t01) ).
        lr_column->set_long_text( 'Choose'(t01) ).
      CATCH cx_salv_not_found.                          "#EC NO_HANDLER
    ENDTRY.

    lr_selections = me->mr_alv->get_selections( ).
    lr_selections->set_selection_mode( if_salv_c_selection_mode=>none ).

    IF me->mv_pf_status IS NOT INITIAL AND me->mv_prog_name IS NOT INITIAL.
      me->mr_alv->set_screen_status(
            pfstatus      = me->mv_pf_status
            report        = me->mv_prog_name
            set_functions = me->mr_alv->c_functions_all ).
    ENDIF.

    lr_events = me->mr_alv->get_event( ).

    SET HANDLER me->on_user_command FOR lr_events.
    SET HANDLER me->on_link_click   FOR lr_events.

    me->mr_alv->set_screen_popup(
      start_column = iv_start_column
      end_column   = iv_end_column
      start_line   = iv_start_line
      end_line     = iv_end_line ).

    me->mr_alv->display( ).

  ENDMETHOD.                    "display_popup


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_ALV_POPUP=>FACTORY
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_DATA                        TYPE        TABLE
* | [--->] IV_PROG_NAME                   TYPE        SYREPID(optional)
* | [--->] IV_PF_STATUS                   TYPE        SYPFKEY(optional)
* | [--->] IV_MULTI_SELECT                TYPE        ABAP_BOOL (default =ABAP_TRUE)
* | [<-()] R_ALV_POPUP                    TYPE REF TO ZCL_ALV_POPUP
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD factory.

    CLEAR r_alv_popup.

    CREATE OBJECT r_alv_popup
      EXPORTING
        it_data         = it_data
        iv_prog_name    = iv_prog_name
        iv_pf_status    = iv_pf_status
        iv_multi_select = iv_multi_select.

  ENDMETHOD.                    "factory


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->GET_SELECTED_DATA
* +-------------------------------------------------------------------------------------------------+
* | [<---] ET_DATA                        TYPE        TABLE
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD get_selected_data.

    DATA: lr_t_data TYPE REF TO data,
        lr_s_data TYPE REF TO data,
        lr_struct TYPE REF TO cl_abap_structdescr,
        lv_cnt    TYPE i.

    FIELD-SYMBOLS: <fs_t_tdata> TYPE STANDARD TABLE,
                   <fs_s_tdata> TYPE any,
                   <fs_t_fdata> TYPE STANDARD TABLE,
                   <fs_s_fdata> TYPE any,
                   <fs>         TYPE any,
                   <fs_tdata>   TYPE any,
                   <fs_fdata>   TYPE any.

    CLEAR et_data.

    lr_struct ?= me->mr_table_type->get_table_line_type( ).
    CHECK lr_struct IS BOUND.

    CREATE DATA lr_t_data TYPE HANDLE me->mr_table_type.
    CREATE DATA lr_s_data TYPE HANDLE lr_struct.
    ASSIGN lr_t_data->* TO <fs_t_fdata>.
    ASSIGN lr_s_data->* TO <fs_s_fdata>.
    ASSIGN me->mr_alv_data->* TO <fs_t_tdata>.

    LOOP AT <fs_t_tdata> ASSIGNING <fs_s_tdata>.
      IF <fs_s_tdata> IS ASSIGNED.
        ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_tdata> TO <fs> CASTING TYPE xfeld.
        IF <fs> IS ASSIGNED.
          IF <fs> = abap_true.
            CLEAR <fs_s_fdata>.
            DO.
              lv_cnt = sy-index + 1.

              ASSIGN COMPONENT lv_cnt OF STRUCTURE <fs_s_tdata> TO <fs_tdata>.
              IF sy-subrc <> 0.
                EXIT.
              ENDIF.
              ASSIGN COMPONENT sy-index OF STRUCTURE <fs_s_fdata> TO <fs_fdata>.
              IF <fs_tdata> IS ASSIGNED AND <fs_fdata> IS ASSIGNED.
                <fs_fdata> = <fs_tdata>.
              ENDIF.
            ENDDO.
            APPEND <fs_s_fdata> TO <fs_t_fdata>.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDLOOP.

    et_data = <fs_t_fdata>.

  ENDMETHOD.                    "GET_SELECTED_DATA


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->ON_LINK_CLICK
* +-------------------------------------------------------------------------------------------------+
* | [--->] ROW                            LIKE
* | [--->] COLUMN                         LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD on_link_click.

    FIELD-SYMBOLS: <fs_t_data> TYPE STANDARD TABLE,
                   <fs_s_data> TYPE any,
                   <fs> TYPE any.

    CHECK mr_alv IS BOUND.

    ASSIGN me->mr_alv_data->* TO <fs_t_data>.
    READ TABLE <fs_t_data> ASSIGNING <fs_s_data> INDEX row.
    IF <fs_s_data> IS ASSIGNED.
      ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_data> TO <fs> CASTING TYPE xfeld.
      IF <fs> IS ASSIGNED.
        IF <fs> = abap_false.
          <fs> = abap_true.
        ELSE.
          <fs> = abap_false.
        ENDIF.
      ENDIF.
    ENDIF.
    IF mv_multi_select = abap_false.
      LOOP AT <fs_t_data> ASSIGNING <fs_s_data>.
        IF <fs_s_data> IS ASSIGNED AND sy-tabix <> row.
          ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_data> TO <fs> CASTING TYPE xfeld.
          IF <fs> IS ASSIGNED.
            <fs> = abap_false.
          ENDIF.
        ENDIF.
      ENDLOOP.
    ENDIF.

    mr_alv->refresh( ).

  ENDMETHOD.                    "on_link_click


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->ON_USER_COMMAND
* +-------------------------------------------------------------------------------------------------+
* | [--->] E_SALV_FUNCTION                LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD on_user_command.

    DATA lr_data TYPE REF TO data.
    FIELD-SYMBOLS <fs_data> TYPE STANDARD TABLE.

    CASE e_salv_function.
      WHEN mc_func_refresh OR mc_func_deselectall.
        me->select_all( iv_value = abap_false ).
      WHEN mc_func_selectall.
        me->select_all( iv_value = abap_true ).
      WHEN OTHERS.
        CREATE DATA lr_data TYPE HANDLE me->mr_table_type.
        ASSIGN lr_data->* TO <fs_data>.

        me->get_selected_data(
          IMPORTING
            et_data = <fs_data>
               ).

        RAISE EVENT button_click
              EXPORTING
                ev_salv_function = e_salv_function
                et_selected_data = <fs_data>.
    ENDCASE.

  ENDMETHOD.                    "on_user_command


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->SELECT_ALL
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_VALUE                       TYPE        ABAP_BOOL (default =ABAP_TRUE)
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD select_all.

    FIELD-SYMBOLS: <fs_t_data> TYPE STANDARD TABLE,
                   <fs_s_data> TYPE any,
                   <fs> TYPE any.

    CHECK mr_alv IS BOUND.

    ASSIGN me->mr_alv_data->* TO <fs_t_data>.

    LOOP AT <fs_t_data> ASSIGNING <fs_s_data>.
      IF <fs_s_data> IS ASSIGNED.
        ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_data> TO <fs> CASTING TYPE xfeld.
        IF <fs> IS ASSIGNED.
          <fs> = iv_value.
        ENDIF.
      ENDIF.
    ENDLOOP.

    mr_alv->refresh( ).

  ENDMETHOD.                    "select_all


ENDCLASS.

 

 

New Technical Brief on ABAP for SAP HANA

$
0
0

Build real-time business applications leveraging the SAP HANA platform to the max with SAP NetWeaver Application Server for ABAP. It offers an excellent, standards-based development and runtime environment with highly responsive user interfaces for enabling business processes across on-premise and on-demand solutions. Read the technical brief here!

Recording Deep Structure to Database via Data Cluster

$
0
0

While writing with ABAP, many programer uses deep structure. Some case we need to record data in deep structure but normal SE11 dictionary type doesnt allow us.

 

So i came up with this :

 

Using Data Cluster for Deep structure Data Clusters in the Database

 

Now my example here is like this:

 

Purpose of this example saving email data ( I know SAP records all e-mail data, this is just a example of using data cluster )

 

First we need to create ZMAIL_INDX table

ZMAIL_INDX.PNG

First key is relid this is Area ID

Second key is our record unique ID

Third key is counter for our record

 

after this we can add as many line as we like for data identification

 

last two line CLUSTR and CLUSTD fill automaticaly and this is our deep structure data.

 

Now creating our Mail data Deep structure:

 

ZMAIL_S_DATA.PNG

 

Now we can write code:

 

DATA : ls_mail_data TYPE zmail_s_data,          ls_mail TYPE zmail_indx,          lv_keyid TYPE char20.

To save :

   ls_mail-ernam = sy-uname.   ls_mail-erdat = sy-datum.   ls_mail-pgmid = sy-repid.   ls_mail-tcode = sy-tcode.

EXPORT mail = ls_mail_data TO DATABASE zmail_indx(zm) ID lv_keyid FROM ls_mail.

 

ZM is RELID

lv_keyid our unique ID

 

For information we sent ernam, erdat etc.

 

To read :

IMPORT mail = ls_mail_data FROM DATABASE zmail_indx(zm) ID lv_keyid TO ls_mail.

You must give keyid

 

Just like this we can record deep structure to database.

 

PS : I use CL_BCS for e-mail, all mail data created for CL_BCS. I assume ls_mail_data is filled with data, so i dont give example of CL_BCS.

 

Now i wonder,

Advantage and Disadvantage of using Data Cluster?

Any idea?


Stumbled Upon Checkpoint Groups

$
0
0

I stumbled upon the concept of Checkpoint groups by accident.

 

One day I was debugging a wave release process in EWM box by activating /h debugging and jumping around using F5, F6, F7 keys. It was getting hard to track the flow of logic because of ALV control framework and nervousness around object oriented code. To save time, I placed breakpoint on statement CALL FUNCTION and continued, hoping that I'll reach a main function module soon.

 

 

I came across BREAK-POINT ID statements while still in classes. They seemed to decipher my action and pass control to another class or function module. My first thought about this statement was that SAP has created special breakpoint statements with specific user IDs, and these are used when they respond to OSS messages.

 

It was a mistake not to see keyword documentation of BREAK-POINT ID. This resulted in significant waste of time.

 

Another day I was asked to apply a note, which had manual pre-implement steps. According to those steps, I had to go to SAAB transaction and create or activate a checkpoint group. System allowed me to create Checkpoint group without asking for access key. It then struck me that the concept is not for SAP internal use only.

 

 

If checkpoint group can be activated without access key or transport request, it is as easy as activating the debugger.

I read the documentation, and activated breakpoint in /SCWM/WAVE checkpoint group.

On releasing new wave, debugger popped up at BREAK-POINT ID statement.

 

I found it useful but limited in scope as the person doing debugging needs to know beforehand what checkpoint groups are applicable. Again, it was a mistake to assume.

 

In New ABAP Debugger, I was checking the number of watchpoints set up under Break./Watchpoints > Watchpoints tab. Right next to this tab was Checkpoint Activations. This tab showed list of checkpoints applicable in current process, also the ones used in current stack level.

 

 

After seeing the option activating Checkpoints in New ABAP Debugger, I now try to use it during analysis.

I think having custom checkpoint in every enhancement implementation will make life easy for person doing debugging in support environment.

 

Summary points

  • Checkpoint groups can be activated using Transaction SAAB.
  • Checkpoint groups can be activated in runtime using New ABAP Debugger.
  • Activation can be user specific, server specific or global.
  • Apart from Breakpoints (BREAK-POINT), option of Assertion (ASSERT) and Log point (LOG-POINT) is also there.
  • Logs can be checked in SAAB transaction.
  • SAP Help link

How To Open Purchase Order Document From Interactive Report

$
0
0

Dear Friends

     i will show you how to use to open Document from ALV  Interactive Report

We have 2 way To open Purchase Requisition

Note :here Ebeln  is Purchase Requisition Number


1. Using Dialog Code Parameter ID

   set parameter id 'BES' field wa_ekko_temp-ebeln.
        call transaction 'ME23N' and skip first screen.

2. Using Function Module

 

    call function 'ME_DISPLAY_PURCHASE_DOCUMENT'
           exporting
             i_ebeln                    = ebeln
*             i_ebelp                    = it_final-ebelp
          exceptions
            not_found                  = 1
            no_authority               = 2
            invalid_call               = 3
            preview_not_possible       = 4
                   .

 

 

Please Use One of this Code


call function 'REUSE_ALV_GRID_DISPLAY'
                     exporting
                       i_callback_program        = sy-repid
                        i_callback_user_command  = 'GETDAILY'

                       it_fieldcat                       = fieldtab[]

                      tables
                        t_outtab                          = it_final.
                              .
form getdaily using ucomm like sy-ucomm  selfield type slis_selfield.

read table it_final index selfield-tabindex.
   case selfield-fieldname.

     when 'EBELN' .

set parameter id 'BES' field wa_ekko_temp-ebeln.
        call transaction 'ME23N' and skip first screen.

or

call function 'ME_DISPLAY_PURCHASE_DOCUMENT'
           exporting
             i_ebeln                    = ebeln
*             i_ebelp                    = it_final-ebelp
          exceptions
            not_found                  = 1
            no_authority               = 2
            invalid_call               = 3
            preview_not_possible       = 4
.
endcase.


endform.

 

Useful SAP Notes for Reference

$
0
0

Below are some of the useful SAP Notes provided by SAP.......These notes are gathered based on my experience (in SD and MM area) and should ideally be helpful for Technical consultants. 

 

1. Adding custom fields to VBAP, VBAK or VBKD.

 

Solution:

Please refer note: Note 143580 - Information on SD BAPIs and customer enhancement concept

This note provides information on which structures are to be modified. How these custom fields can be filled using BAPI.

 

For adding custom fields to MARA..refer Note 44410 - Integrating cust.-specific fields in matl master

 

2. User Exits in Delivery Processing.

 

Solution:

Note 415716 - User exits in delivery processing

If you ever need to understand....on how to work with delivery user exits, this is the most useful note.

This note not only provides information on userexits.....but also on internal tables like XLIKP, YLIKP etc. Which internal table contains which data?

 

Note 209846 - Use of SY-TCODE in delivery processing

This Note provides information on how checks related to SY-TCODE can be avoided in Delivery userexits. (Extract from Note...given below)

In your user exits,use field T180-TRTYP instead of field SY-TCODE. This field has the following characteristics depending on the processing mode:

  • H  Creation of the delivery
  • V  Change of the delivery
  • A  Display of the delivery

    If a differentiation should be required whether the creation of the delivery is carried out online (Transaction VL01N) or is carried out in collective processing (Transaction VL10x), use the V50AGL-SAMMELGANG flag in addition:  

  • T180-TRTYP = 'H' and V50AGL-SAMMELGANG = 'X':
    Creation of the delivery is carried out in collective processing.
  • T180-TRTYP = 'H' and V50AGL-SAMMELGANG = SPACE:
    Creation of the delivery is carried out online.

The mentioned advice works for the new and the old delivery dialog and for inbound and outbound delivery in the same way.

 

 

3. User Exits in Sales Order Processing

 

Note 381348 - Using user exit, customer exit, VOFM in SD

This note provides information on "Exit Technologies" used in SAP. (This note does not tell you...how to implement them!)

 

Note 178328 - Problems due to incorrect user exits in SD

This note is useful because it contains "Basic information concerning the management of internal tables in Sales and Distribution" and "General recommendations for the use of user exists (include technique)"

 

Note 156230 - Requirements: What is permitted, what is not?

If you need to understand Requirement Routines (VOFM Transaction) for Condition Type in SD Pricing. This note is very helpful!

 

4. Performance Problem and Oracle Hints

 

Note 185530 - Performance: Customer developments in SD

Note 191492 - Performance: Customer developments in MM/WM

 

Both the notes, provide good information on how database tables related to respective modules are to be accessed. Worth a look! (Not necessarily helpful for everyone)

 

Note 334224 - Important notes for creating indexes

Note 912620 - FAQ: Oracle indexes

 

Above notes, provide useful information on creation of index and what it is!

 

Note 772497 - FAQ: Oracle Hints

Note 130480 - Database hints in Open SQL for Oracle

 

Both the notes, provide good information on what are Oracle Hints and how they can be used.

 

5. BAPI's and other topics

 

BAPI's to obtain next number in the number range for Customer, Vendor and Contact Person

BAPI_CUSTOMER_GETINTNUMBER
BAPI_VENDOR_GETINTNUMBER
BAPI_PARTNEREMPLOYEE_GETINTNUM

Note from which the above was obtained is Note - 1749700

 

Classes available in SAP for creation of Vendor or Customer is:

VMD_EI_API - Vendor
CMD_EI_API - Customer

Methods are MAINTAIN_BAPI, MAINTAIN

 

Note 582221 - FAQ: BAPIs for purchase orders

Note 1257033 - Cookbook: Modification/enhancement for standard SAP system

Note 623459 - Creating/ changing a search help in the ABAP Dictionary

Note 27 - Recommendations for the ABAP file interface

Note 1319507 - Overview: Analysis of ABAP Web Service Configuration

Dynamically request values from user

$
0
0

Today I’d like to introduce a tool to request a random number of values from user. For example, you’d like to ask and then store a template of some structure to use this pattern further.

I used it to determine sample values for structure of an HR infotype to create a flexible data download program.

Initial screen of this report looks very ascetic:

1.jpg

                    The bottom button is used to request data from user. If you push it you’ll get:

2.jpg

Here you can see a list of P0009 structure fields with their names described at ABAP repository. So any changes of this structure will change this screen with requesting values.

Probably, you’d like to know how many instructions I was to code. Well, lets see it:

 

The first part is to describe my requesting tool:

DATA: lr_request_values TYPE REF TO zcl_bas_dyn_request_values.
  lr_request_values
= zcl_bas_dyn_request_values=>factory( ).

 

 

The second is to get my structure filled with values by user:

DATA: default_p0009 TYPE p0009,
     lr_descr     
TYPE REF TO cl_abap_structdescr,
     lr_elemdescr 
TYPE REF TO cl_abap_elemdescr.
   
lr_descr ?= cl_abap_structdescr=>describe_by_data( default_p0009 ).
    CHECK lr_descr IS BOUND.
 
LOOP AT lr_descr->components ASSIGNING <component>.

      ASSIGN COMPONENT <component>-name OF STRUCTURE default_p0009 TO <field>.
  
CHECK sy-subrc = 0.
   lr_elemdescr ?= cl_abap_elemdescr
=>describe_by_data( <field> ).
   ls_field
= lr_elemdescr->get_ddic_field( ).
  
IF ls_field-scrtext_m IS INITIAL.
    ls_field
-scrtext_m = ls_field-scrtext_s.
  
ENDIF.
   lv_defaultc
= <field>.
   lv_paratype
= 'P0009-' && <component>-name.
  
IF ls_field-scrtext_m IS INITIAL.
    ls_field
-scrtext_m = lv_paratype.
  
ENDIF.
   lr_request_values
->add_parameter(
    
EXPORTING
      iv_parakind 
= 'P'
      iv_paratype 
= lv_paratype
      iv_label    
= ls_field-scrtext_m
      iv_def_value
= lv_defaultc
    
CHANGING
      cv_parameter
= <field> ).
 
ENDLOOP.


And at last request user:

    lr_request_values->request_values( ).

When the last call ends my structure default_p0009 is filled with values user just filled. As you may count it’s just about 20 lines of code to ask user for values of any flat structure from ABAP repository.

And now my code to get this functionality:

 

TXT files attached for class ZCL_BAS_DYN_REQUEST_VALUES and for class ZCL_BAS_DYN_PARAM.

Search inside Open XML documents

$
0
0

Hello.

since Open XML documents are based on OPC and  xml vocabulary,

It can be very helpful to search patterns in documents.

 

for example , if we look for a certain text ,  or version of a document

we can  use outer methods for handle it.

 

we can search for any type including mime types.

Open XML documents let us dive inside the data and handle

it explicitly.

 

there are some kind of  documents that are based on  an image

but in Open XML we can get direct to data, and that is a huge benefit!

Displaying a DMS PDF Document in Web Dynpro

$
0
0

Purpose

 

The plain technical requirement is that a PDF document is stored in SAP needs to be displayed as a Pop-up to the portal user.

 

Details

 

Earlier, I used to use SAP GUI for HTML and call the 'DOCUMENT_SHOW_DIRECT' in a wrapper program with submit.

 

But here is a better way.

 

Create a New method DISPLAY_DOCUMENT in your assitance class, generally the TYPE of document is static but you can keep all as parameterised.

 

Inside the method call the following code

 


 

  DATA : W_URL  type string,
 
          v_url type MCDOK-URL.


CALL FUNCTION 'CVAPI_DOC_VIEW'
 
EXPORTING
    PF_DOKAR              
= I_DOKAR
    PF_DOKNR              
= I_DOKNR
    PF_DOKVR              
= I_DOKVR
    PF_DOKTL              
= I_DOKTL
   PF_HOSTNAME           
= 'DEFAULT'
   PF_APPL_START         
= ' '
   PF_GET_URL            
= 'X'

IMPORTING

   PFX_URL                = v_URL

EXCEPTIONS
   ERROR                 
= 1
   NOT_FOUND             
= 2
   NO_AUTH               
= 3
   NO_ORIGINAL           
= 4
  
OTHERS                 = 5.

 

IF SY-SUBRC <> 0.

* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO

*         WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.

ENDIF.

 

W_URL = v_url.

 


  data lo_window_manager type ref to if_wd_window_manager.
 
data lo_api_component  type ref to if_wd_component.
 
data lo_window         type ref to if_wd_window.
 

  lo_api_component  = wd_comp_controller->wd_get_api( ).
  lo_window_manager
= lo_api_component->get_window_manager( ).
 

  CALL METHOD lo_window_manager->CREATE_EXTERNAL_WINDOW
   
EXPORTING
      URL           
= W_URL

      MODAL          = ABAP_FALSE
      HAS_MENUBAR   
= ABAP_TRUE
      IS_RESIZABLE  
= ABAP_TRUE
      HAS_SCROLLBARS
= ABAP_TRUE
      HAS_STATUSBAR 
= ABAP_TRUE
      HAS_TOOLBAR   
= ABAP_TRUE
      HAS_LOCATION  
= ABAP_TRUE
    RECEIVING
     
WINDOW         = lo_window.

 

  lo_window->open( ).

 

Output

 

Well, I have called this code on click of ALV on the DMS document number... and here is the result

 

Capture.PNG

Why develop ABAP in Eclipse?

$
0
0

Hello everybody, I've opened this post to discuss about the reasons or convenience for developing ABAP in Eclipse or keep doing it in SAP GUI.

 

I haven't begun yet any ABAP project in Eclipse, but at this point I've found some inconvenients of developing ABAP in Eclipse.

 

The first one is the complexity of installing all the plug-ins you need to start developing ABAP in Eclipse. It is not an easy issue, due to you must know the level of customer SAP release, the Eclipse version that you are using and find the correct plug-ins version.

 

The second one is that developing ABAP in Eclipse is not intuitive, you cannot develop as easy as you do un SAP GUI, there are a lot of steps more that you must carry out to begin your work.

 

What do you think? Bring me some feed back about your experience developing in Eclipse.

 

Regards,

David.


Automatic QA and release request

$
0
0

The motivation behind thisblogcame aftera visit toSAPLabsLatin America in SaoLeopoldo-Brazil. We hadcontact with the SAP expertHeinzLudwigwhointroduced us to theAbapTestCockpit. When askedifSAPwas alreadyusing theATCwasfunnyhis reaction...

We did not have alltheprerequisitesto install theATC (EHP6 and SP3 ABAP), w
e intend toupdate thelandscapein anear future. But we hadthe idea to createa similar routinetostaticcode verification. We addto this therequests automatic releasewhen nothingwasfound, in case of false positiveoccurred, the request forexemptionoccursvia email.

 

This solution is running in our environment about three months and during this period we noticed an improvement in code quality and especially the maturity of team programmers.

 

ATC is a wonderful tool for quality assurance and automatic verification, merging applications like extended check, code inspector and exemption authorization by workflow.

 

If your landscape supports ATC, you will not have problems to start using it.

Just take a look on some good blogs:

 

http://scn.sap.com/docs/DOC-32628

http://scn.sap.com/docs/DOC-32172

http://scn.sap.com/docs/DOC-31773

http://scn.sap.com/community/abap/testing-and-troubleshooting/blog/2012/12/03/teched-2012-the-brand-new-abap-test-cockpit-a-new-level-of-abap-quality-assurance

 

But if your company still waiting to upgrade to compatible version, do not wait anymore. Automatic quality assurance not is the future - but the present. You can start it with some abap code and little work. The hard work is change the process - and the people's mind!

Be careful:codequalitywithouttestingis abad code!

 

 

 

1st step.

Create a BADI for CTS_REQUEST_CHECK.

SE19 - CTS_REQUEST_CHECK.jpg

 

2nd step.

Create a implementation class. Activate the BADI created.

Implementation class.jpg

 

3rd step.

Configure code inspector variant: transaction code SCI. It is possible to create new checks too. And the bestnews: their struggle nowwill be usedlaterwhen thelandscapeiscompatible withATC!

http://wiki.sdn.sap.com/wiki/display/Snippets/Code+Inspector+Check

http://scn.sap.com/community/abap/blog/2006/11/02/code-inspector--how-to-create-a-new-check

 

SCI variant.jpg

 

4th step.

Code the method CHECK_BEFORE_RELEASE in the class that was created in the step 2.

 

How it works: It isinformedthattherequestto be evaluated; its objectsmust beextracted(programs, classes, functions and others) and the source codeof each objectas well,using thestandard functionSVRS_GET_REPS_FROM_OBJECT.
Tofind the differencebetween the current versionand thepreviousSVRS_COMPUTE_DELTA_REPSfunctioncan alsobe used.
With thesource codeextracted, just perform thevalidationsand present thecheckpoints founded.

 

The focusis notpresentthe codeitself, but to showhow simple it is, the following how to calltheextended checkandcodeinspector.

Manypossibilities andideaswere emerging, asdo the checkingonlythemodified version, ortheentire programwhen it issomething morecritical.

 

You can call code inspector like it was called in this thread:

 

Or you can do only extended check, if you want to do a "soft check".

{code}

  wa_flags-x_dat = 'X'.
  wa_flags-x_per = 'X'.
  wa_flags-x_txt = 'X'.
  wa_flags-x_bre = 'X'.

... "other extended check validations if you want, just use wa_flags strucutre.

   LOOP AT me->t_request_obj ASSIGNING <fs_obj>.

     o_checker = cl_slin_driver=>get_checker_group( wa_flags ).

     v_prog = <fs_obj>-obj_name.

     o_ref = cl_slin_driver=>io_result( progname    = v_prog
                          ignore_pseudo_comments = v_comment_flag
                          call_cntx              = v_call_cntx
                          checker                = o_checker
                          cache_use              = v_cache_use ).

     o_ref->old_get_result_tables( IMPORTING result = t_result result_stat = t_result_stat ).

...


   ENDLOOP.

{code}

 

This same logic is also performed in a transaction report and in the SE09/SE10 release button. We created authorization objects to secure that only approvers can release requests with points to check with inserting of a justificative.

 

SE09/SE10 screen asking an exemption on release

Critical errors.jpg

 

The transaction report: "points to do better"

Z_ATC.jpg

Errors_result.jpg

 

That is all folks!

Sales Flow (Sales Order->Delivery->Transfer Order->TO Confirmation->Shipment) in ECC

$
0
0

Sales Order Creation

 

Transaction VA01

Enter Order Type and Click Enter.

 

1.jpg

 

Enter below information and press enter

 

Ship-to-Party – 22266601

Sold-to-Party – 22266601

PO Number – 12345      

Material – 5260010

Quantity – 1 EA

2.jpg

Click Save

Sales Order Number – 44 is created

 

3.jpg

 

Delivery Creation

 

Transaction VL01N

Enter Shipping Point and Order Number – 44 and press Enter

 

4.jpg

4a.jpg

In transport tab enter, Route as 000001 and Click Save.

Delivery number – 8000052 is created

5.jpg

 

Transfer Orders Creation & Confirmation

 

Transaction LT03

6.jpg

Enter Warehouse Number, Delivery as 8000052, Press Enter and Click Save

 

7.jpg

Transfer Order – 27 is created

 

Transaction LT12

Enter TO Number and Warehouse

8.jpg

Press Enter

10.jpg

Click Save

Transfer Order Confirm

11.jpg

 

Shipment Creation

 

Transaction – VT01N

Enter TransportPlanningPt and Shipment Type

13.jpg

Press Enter

14.jpg

Click Save

Shipment Number – 1009 is created

 

11.jpg

 

Transaction VT02N

Enter Shipment Number 1009 and press Enter

 

16.jpg

Click Deliveries

17.jpg

Enter Outbound Delivery Number 8000052 and click Execute.

 

18.jpg

Click Save

 

So this is how Sales Order->Delivery->Transfer Order->TO Confirmation->Shipment

Creating Dynamic ALV

$
0
0

Requirement

Recently we had a requirement to create a dynamic ALV. The number of columns in the output would vary depending upon the number of unique records in another table say ZRECORD. If ZRECORD had 7 unique records, our ALV should have 7 columns with column name represented by the key field of ZRECORD. 

Solution
1. Define three field symbols.
<fs_dyntable> TYPE standard table
<fs_dyn_wa> TYPE any
<fs_dyn_field> TYPE any.

2. Create a table similar to fieldcatalogue of type lvc_t_fcat (t_fieldcat) by looping through ZRECORD and appending column names depending upon the key field of ZRECORD to t_fieldcat.

3. T_fieldcat is passed too cl_alv_table_create=>create_dynamic_table and the new imported table is assigned to <fs_dyntable>

4. <fs_dyn_wa> is created as line of <fs_dyntable> as shown below.
CREATE DATA wa_new_line LIKE LINE OF <fs_dyntable>.
ASSIGN wa_new_line->* TO <fs_dyn_wa> (wa_new_line is reference type of DATA)

5. Each row of this dynamic table now can be filled using
ASSIGN COMPONENT (n) (column number)
OF STRUCTURE <fs_dyn_wa> TO <fs_dyn_field>.

<fs_dyn_field> = (data need to input).

6. After filling each row append <fs_dyn_wa> to <fs_dyntable>

7. Pass <fs_dyntable> to REUSE_ALV_GRID_DISPLAY as t_outtab, along with the new fieldcatalogue and other desired parameters.

Open XML documents on a Background Task

$
0
0

This is a screen cast showing  Word Open  XML documents generation

from  SAP  on a Background  Job  (SM37)

The screen cast also showing selection

of the files content controls  data back into  SAP.

 

 

http://www.youtube.com/watch?v=zNhcnDwK-88

 

 

Hope you'll like  it.   

 

            Ronen  Almog

 

OpenXML.jpg

Useful ABAP Packages for Demo programs

$
0
0

Hi everyone,

 

As a developer, whenever we have to work with a new object, to grab the new concept, we may:

- Read about it on http://help.sap.com/nw_platform#section6

- Browse through different blog posts/documents on SCN

- Simply Google it

 

Another way I tend to do is to find the demo programs for that object in SAP. This is very useful as we have chance to see how the object works in action, and at the same time follow standard development practices from SAP.

 

So in this blog post, I will share the packages that I found very useful for object demoing purposes. Hope it is useful to you and if you know of any packages, feel free to add it in the comment so that we all have more knowledge. You may want to browse through the package from SE80 to find the demo of the concept you want to know about.

 

PackageTitleCommentsExample Reports/Webdynpro Components
BC400

Training: BC400 - ABAP Workbench: Concepts and Tools.

Contain programs that show some fundamental concepts of ABAP


BC401Course: BC401 - ABAP Objects. Contain programs that demonstrate some OO concepts in ABAP.
BC405Training Course BC405: List Creation and QueryContain programs that demonstrate concepts in Report Programming (e.g. ALV, Report Event, Logical Database)
BC412Course BC412: ABAP Dialog Program with EnjoySAP ControlsContain programs that demonstrate concepts in Dialog Programming
BC417SAP Training: BC417Contain programs that demonstrate BAPI concept
BC427BC427 Training ObjectsContain programs that demonstrate Enhancement Framework concepts (Classic BADI, New BADI, etc.)
BC470Training Course: BC470 - SAP Smart FormsContain programs that demonstrate SmartformsSAPBC470_DEMO
SABAPDEMOSDemos for ABAP DocumentationMany programs that demonstrate ABAP language concepts from ABAP Documentation

My favorite:

DEMO_REGEX

DEMO_REGEX_TOY

DEMO_JAVA_SCRIPT_MINI_EDITOR

SDW4Packages for Demo Center from tCode DWDMPrograms that demonstrates objects in Control Framework (I havent had much opportunities to use it in Production)
SLISGeneric list types

Contains pretty much useful and detail example with using ALV (REUSE_ALV_* and CL_GUI_ALV_GRID)

My favorite: BCALV_GRID_*
SALV_OM_OBJECTSALV Object Model Basis ClassesContains pretty much useful and detail example with using SALV (CL_SALV_TABLE)

My favorite

SALV_DEMO_TABLE_EVENTS

SALV_DEMO_TABLE_*

SWDP_DEMOWebdynpro Demo ApplicationContains many useful Web Dynpro applications that illustrate essential UI elements in Web Dynpro
SWDP_DEMO_TUTORIALSWebdynpro Demo ApplicationDemo Web Dynpro Application concepts with Flight Booking system, Quiz System
SWDP_TESTWeb Dynpro: Tests

Many many useful Web Dynpro applications, illustrate UI elements usage and important concepts in Web Dynpro

A must look if you want to grab Web Dynpro concepts

WDR_TEST_EVENTS

SEU_TREE_CONTROLOO Framework for Tree ControlI haven't had chance to work with Tree Control object.
SOFFICEINTEGRATIONPlatform- and application-indep. Office integrationOLE. I haven't had chance to work with Office Integration.
APB_FPM_DEMOFloorplan Manager (Examples and Demo applications)Demo applications for FPM to show concepts of Guided Activity Floorplan (GAF), Object Instance Floorplan (OIF)Web Dynpro Application: FPM_DEMO_FLIGHT_OVERVIEW

 

 

So that's it. Above is my current list of useful packages. Browse through the package, find the program that illustrate the concept you want to grab. Hope it will helps you. Please comment if you know any other useful packages and I will also update this blog post when I find new useful packages. Cheers!

Viewing all 943 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>