Quantcast
Channel: SAP Portfolio and Project Management (SAP RPM, cProjects) and cFolders
Viewing all articles
Browse latest Browse all 36

PPM Gantt in PDF Report - Part 3

$
0
0

Part 1: Introduction

Part 2: XML-based Gantt customizing

Part 3: ABAP-based Chart engine

Part 4: Conclusion

 

After previously collecting the project data, we now need to convert it into an XML-based document. To realize this, standard iXML libraries come into play. For more information regarding iXML libraries, please refer to the following link.

 

The chart engine is represented in the system by a global ABAP class:

class diagram.png

Also, in the types section:

 

  types:
    BEGIN OF s_category,
      description TYPE string,
    END OF s_category.
  types:
    t_category TYPE TABLE OF s_category.

  types:
    BEGIN OF s_series_gantt,
      points      TYPE yppm_tty_point,
      label       TYPE string,
      customizing TYPE string,
    END OF s_series_gantt.
  types:
    t_series_gantt TYPE TABLE OF s_series_gantt.

Additionally, a data dictionary structure (E.g. YPPM_STR_POINT) and it’s corresponding table type must be created:

ComponentType
START_VALUESTRING
END_VALUESTRING
TOOLTIPSTRING

 

Using the project data from Part 2, we now call the FILL_CHART_CONTEXT method, passing the internal table as a parameter. We’ve used the following code to fill in class attributes MT_CATEGORY_GANTT and MT_SERIES_GANTT:

types:
   
begin of s_ms,
        index
type i,

       start   type datum,
        end   
type datum,
   
end of s_ms,
      t_ms
type standard table of s_ms.

 
data:
    ls_category  
type s_category,     " found in the TYPES section
    ls_series    
type s_series_gantt, " found in the TYPES section

    lt_point_plan
type yppm_tty_point,
    lt_point_date
type yppm_tty_point,
    lt_point_ms  
type yppm_tty_point,
    ls_point     
type yppm_str_point,

    ls_ms        
type s_ms,
    lt_ms        
type t_ms,

    lv_date1     
type string,
    lv_date2     
type string.

 
field-symbols:
    <fs_data>  
like line of it_data[].

 
define convert_date.
   
concatenate &1+6(2) &1+4(2) &1(4) into lv_date1 separated by '.'.
   
concatenate &2+6(2) &2+4(2) &2(4) into lv_date2 separated by '.'.
  

    if lv_date1 ne lv_date2.
     
concatenate &3 lv_date1 '-' lv_date2 into &4 separated by space.
   
else.
     
concatenate &3 lv_date1 into &4 separated by space.
   
endif.

 
end-of-definition.

 
" create all categories first
 
refresh mt_category_gantt[].
 
loop at it_data[] assigning <fs_data>.
    ls_category
-description = <fs_data>-object_desc.

   
append ls_category to mt_category_gantt[].
 
endloop.

 
" create points for each series
 
loop at it_data[] assigning <fs_data>.
    ls_point
-start_value = <fs_data>-date_start.
    ls_point
-end_value   = <fs_data>-date_end.
    convert_date ls_point
-start_value ls_point-end_value 'Plan:' ls_point-tooltip.
   
append ls_point to lt_point_plan[]. clear ls_point.

    ls_point
-start_value = sy-datum.
    ls_point
-end_value   = sy-datum.
    convert_date ls_point
-start_value ls_point-end_value 'Current Date:' ls_point-tooltip.
   
append ls_point to lt_point_date[]. clear ls_point.

   
do 5 times. " maximum number of milestones, can be a dynamic value
      ls_ms
-index = sy-index.

     
read table <fs_data>-ms[] index ls_ms-index into ls_ms-start.

     
if sy-subrc is initial.
        ls_ms
-end = ls_ms-start.
     
else.
       
clear:
          ls_ms
-start,
          ls_ms
-end.
     
endif.

     
append ls_ms to lt_ms[]. clear ls_ms.
   
enddo.
 
endloop.

 
" create all series
 
refresh mt_series_gantt[].
 
do 2 times.
   
case sy-index.
     
when 1.
       
" plan series
        ls_series
-customizing = 'Plan'.
        ls_series
-label            = 'Plan'.
        ls_series
-points          = lt_point_plan[].

     
when 2.
       
" line for current date
        ls_series
-customizing = 'ACTDATE'.
        ls_series
-points           = lt_point_date[].

   
endcase.

   
append ls_series to mt_series_gantt[].
 
enddo.

 
" create milestones
 
do 5 times.
   
loop at lt_ms[] into ls_ms where index eq sy-index.
      ls_point
-start_value = ls_ms-start.
      ls_point
-end_value   = ls_ms-end.

     
append ls_point to lt_point_ms[]. clear ls_point.
   
endloop.


    ls_series
-customizing = 'MS'.
    ls_series
-label            = 'MS'.
    ls_series
-points          = lt_point_ms[]. refresh lt_point_ms[].

   
append ls_series to mt_series_gantt[]. clear ls_series.
 
enddo.

The next step is to load and parse the XML-based customizing file and use it to fill the class attribute MT_CUSTOMIZING.

 

  set_graphic_parameter( '/sap/public/ppm/ypdf/gantt_customizing.xml').

We do this by calling the method SET_GRAPHIC_PARAMETER using the MIME path as an import parameter. This method encapsulates the following code:

 

  data:
    lo_mime_repository type ref to if_mr_api,
    lv_content         type xstring,

    lo_ixml            type ref to if_ixml,
    lo_stream_factory  type ref to if_ixml_stream_factory,
    lo_istream         type ref to if_ixml_istream,
    lo_document        type ref to if_ixml_document,
    lo_parser          type ref to if_ixml_parser.

  " get the .xml file from MIME
  lo_mime_repository = cl_mime_repository_api=>if_mr_api~get_api( ).
  lo_mime_repository->get( exporting i_url             = iv_path                                  
                                     i_check_authority = abap_false
                           importing e_content         = lv_content ).

  if lv_content is initial.
    " raise exception
  endif.

  " generate XML instance
  lo_ixml = cl_ixml=>create( ).

  lo_stream_factory = lo_ixml->create_stream_factory( ).

  lo_istream = lo_stream_factory->create_istream_xstring( lv_content ).

  lo_document = lo_ixml->create_document( ).

  lo_parser = lo_ixml->create_parser(
    document       = lo_document
    istream        = lo_istream
    stream_factory = lo_stream_factory ).

  lo_parser->set_namespace_mode( mode = if_ixml_parser=>co_namespace_aware ).
  lo_parser->set_validating( mode = if_ixml_parser=>co_validate_if_dtd ).
  lo_parser->parse( ).

  " save customizing
  refresh mt_customizing[].
  append lo_document to mt_customizing[].


At this point, we already have the XML-based customizing and the ready to use project data (still in ABAP format).

Now it’s time to convert the MT_CATEGORY_GANTT and MT_SERIES_GANTT internal tables into a XML-based document. We do this using method CREATE_CHART_DATA_XML, having the following source code:

 

data:
    lo_ixml      
type ref to if_ixml,
    lo_document  
type ref to if_ixml_document,
    lo_encoding  
type ref to if_ixml_encoding,
    lo_chartdata 
type ref to if_ixml_element,
    lo_categories
type ref to if_ixml_element,

    lo_category  
type ref to if_ixml_element,
    ls_category  
type s_category,

    lo_series    
type ref to if_ixml_element,
    ls_series    
type s_series_gantt,

    lo_point     
type ref to if_ixml_element,
    ls_point     
type yppm_str_point,

    lo_element   
type ref to if_ixml_element,
    lv_string    
type string value is initial.

 
" create document and set header data
  lo_ixml
= cl_ixml=>create( ).
  lo_document
= lo_ixml->create_document( ).

  lo_encoding
= lo_ixml->create_encoding( byte_order     = if_ixml_encoding=>co_little_endian
                                                                     character_set
= 'utf-8' ).
  lo_document
->set_encoding( lo_encoding ).

 
" create main elements for chart data and categories
  lo_chartdata 
= lo_document->create_simple_element( name = 'ChartData'  parent = lo_document ).
  lo_categories
= lo_document->create_simple_element( name = 'Categories' parent = lo_chartdata ).

 
loop at mt_category_gantt[] into ls_category.
    lv_string
= ls_category-description.
    lo_category
= lo_document->create_simple_element( name   = 'Category'
                                                                                          parent
= lo_categories
                                                                                         
value  = lv_string ). clear lv_string.
 
endloop.

 
" build XML structure for each series
 
loop at mt_series_gantt[] into ls_series.

   
" create series elements
    lo_series
= lo_document->create_simple_element( name = 'Series' parent = lo_chartdata ).

    lv_string
= ls_series-label.
    lo_series
->set_attribute( name = 'label'       value = lv_string ). clear lv_string.

    lv_string
= ls_series-customizing.
    lo_series
->set_attribute( name = 'customizing' value = lv_string ). clear lv_string.

   
" build XML structure for each point of each series
   
loop at ls_series-points[] into ls_point.

     
" create point elements
      lo_point
= lo_document->create_simple_element( name = 'Point' parent = lo_series ).

     
" create TIME VALUE start
      lv_string
= ls_point-start_value.
      lo_element
= lo_document->create_simple_element( name   = 'Value'
                                                                                           parent
= lo_point
                                                                                          
value  = lv_string ). clear lv_string.

      lo_element
->set_attribute( name = 'type' value = 'time' ).

     
" create TIME VALUE finish
      lv_string
= ls_point-end_value.
      lo_element
= lo_document->create_simple_element( name   = 'Value'
                                                                                           parent
= lo_point
                                                                                          
value  = lv_string ). clear lv_string.

      lo_element
->set_attribute( name = 'type' value = 'time' ).
   
endloop.
 
endloop.

  mr_chart_data
= lo_document.

 

The final step is the actual rendering of the graphic which will be covered in Part 4.


Viewing all articles
Browse latest Browse all 36

Trending Articles



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