Thursday, February 05, 2009

Excel OLE y ABAP


El otro día el funcional me pidió que hiciera un reporte en Excel. "Eso es demasiado fácil" pensé...Bueno...No era tan verdad...El quería titulos, colores de fondo, letra en negrita y un formato especial.

Todos sabemos que cuando descargamos un Excel utilizando ABAP, no importa lo que hagamos, vamos a tener siempre la misma aburrida estructura. Sin colores y sin estructuras extrañas.

Por supuesto, pensé en utilizar Excel OLE...Pero nunca lo había utilizado, así que me puse a buscar en el SCN para tratar de encontrar algo que me ayudara a aprender. Llegué a Manipulate Excel with OLE & ABAP escrito por mi buen amigo Rich Heilman.

Este blog es realmente muy bueno, pero le faltan algunas cosas importantes que necesitaba para mi reporte...El archivo necesitaba existir en el sistema y no estaba utilizando colores ni formato de letras...Claro, en ese entonces, el estaba recién aprendiendo como utilizar las herramientas, así que más que una crítica, pienso que es excelente que compartiera sus conomientos mientras estaba aprendiendo.

En fín...Seguí buscando en los foros y encontré toda la información que necesitaba para terminar mi reporte. Luego de eso, decidí crear un pequeño y simple ejemplo, mostrando lo que se puede hacer con Excel OLE y ABAP.


*&----------------------------------------------------*
*& Report ZDUMMY_SANDBOX *
*&----------------------------------------------------*
REPORT zdummy_sandbox.

*&----------------------------------------------------*
* INCLUDES *
*&----------------------------------------------------*
INCLUDE ole2incl.

*&----------------------------------------------------*
*& TYPES *
*&----------------------------------------------------*
TYPES: BEGIN OF ty_spfli,
carrid TYPE spfli-carrid,
connid TYPE spfli-connid,
countryfr TYPE spfli-countryfr,
cityfrom TYPE spfli-cityfrom,
airpfrom TYPE spfli-airpfrom,
countryto TYPE spfli-countryto,
cityto TYPE spfli-cityto,
airpto TYPE spfli-airpto,
END OF ty_spfli.

TYPES: BEGIN OF ty_titles,
title(20) TYPE c,
field(20) TYPE c,
END OF ty_titles.

*&----------------------------------------------------*
*& INTERNAL TABLES *
*&----------------------------------------------------*
DATA: t_spfli TYPE STANDARD TABLE OF ty_spfli,
t_titles TYPE STANDARD TABLE OF ty_titles.

*&----------------------------------------------------*
*& FIELD-SYMBOLS *
*&----------------------------------------------------*
FIELD-SYMBOLS: <fs_spfli> LIKE LINE OF t_spfli,
<fs_titles> LIKE LINE OF t_titles,
<fs> TYPE ANY.

*&----------------------------------------------------*
*& VARIABLES *
*&----------------------------------------------------*
DATA: w_tabix TYPE sy-tabix,
w_titles TYPE sy-tabix,
w_line TYPE sy-tabix,
w_field TYPE string,
filename TYPE string,
path TYPE string,
fullpath TYPE string.

DATA: data_titles TYPE REF TO data.

DATA: e_sheet TYPE ole2_object,
e_activesheet TYPE ole2_object,
e_newsheet TYPE ole2_object,
e_appl TYPE ole2_object,
e_work TYPE ole2_object,
e_cell TYPE ole2_object,
e_color TYPE ole2_object,
e_bold TYPE ole2_object.

*&----------------------------------------------------*
*& SELECTION-SCREEN *
*&----------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1.
PARAMETERS: p_file TYPE rlgrap-filename.
SELECTION-SCREEN END OF BLOCK b1.

*&----------------------------------------------------*
*& START-OF-SELECTION *
*&----------------------------------------------------*
START-OF-SELECTION.
PERFORM get_titles.
PERFORM get_data.
PERFORM create_excel.

*&----------------------------------------------------*
*& AT SELECTION-SCREEN *
*&----------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.

CALL METHOD cl_gui_frontend_services=>file_save_dialog
EXPORTING
window_title = 'Select archivo'
default_extension = 'xls'
file_filter = '*.xls'
CHANGING
filename = filename
path = path
fullpath = fullpath.

IF sy-subrc EQ 0.
p_file = fullpath.
ENDIF.

*&----------------------------------------------------*
*& Form get_titles *
*&----------------------------------------------------*
FORM get_titles.

CREATE DATA data_titles TYPE ty_titles.
ASSIGN data_titles->* TO <fs_titles>.

<fs_titles>-title = 'CARRIED ID'.
<fs_titles>-field = 'CARRID'.
APPEND <fs_titles> TO t_titles.
<fs_titles>-title = 'CONNECTION ID'.
<fs_titles>-field = 'CONNID'.
APPEND <fs_titles> TO t_titles.
<fs_titles>-title = 'COUNTRY FROM'.
<fs_titles>-field = 'COUNTRYFR'.
APPEND <fs_titles> TO t_titles.
<fs_titles>-title = 'AIRPORT FROM'.
<fs_titles>-field = 'AIRPFROM'.
APPEND <fs_titles> TO t_titles.
<fs_titles>-title = 'COUNTRY TO'.
<fs_titles>-field = 'COUNTRYTO'.
APPEND <fs_titles> TO t_titles.
<fs_titles>-title = 'CITY TO'.
<fs_titles>-field = 'CITYTO'.
APPEND <fs_titles> TO t_titles.
<fs_titles>-title = 'AIRPORT TO'.
<fs_titles>-field = 'AIRPTO'.
APPEND <fs_titles> TO t_titles.

ENDFORM. "get_titles

*&----------------------------------------------------*
*& Form get_data *
*&----------------------------------------------------*
FORM get_data.

SELECT carrid connid countryfr cityfrom
airpfrom countryto cityto airpto
INTO TABLE t_spfli
FROM spfli
WHERE carrid EQ 'LH'.

ENDFORM. " get_data

*&----------------------------------------------------*
*& Form create_excel *
*&----------------------------------------------------*
FORM create_excel.

w_line = 1.

CREATE OBJECT e_appl 'EXCEL.APPLICATION'.
SET PROPERTY OF e_appl 'VISIBLE' = 1.

CALL METHOD OF e_appl 'WORKBOOKS' = e_work.
CALL METHOD OF e_work 'Add' = e_work.

GET PROPERTY OF e_appl 'ActiveSheet' = e_activesheet.
SET PROPERTY OF e_activesheet 'Name' = 'Flights'.

LOOP AT t_spfli ASSIGNING <fs_spfli>.
w_tabix = sy-tabix.
w_line = w_line + 1.

LOOP AT t_titles ASSIGNING <fs_titles>.
w_titles = sy-tabix.
CALL METHOD OF e_appl 'Cells' = e_cell
EXPORTING
#1 = 1
#2 = w_titles.
SET PROPERTY OF e_cell 'Value' = <fs_titles>-title.
GET PROPERTY OF e_cell 'Interior' = e_color.
SET PROPERTY OF e_color 'ColorIndex' = 35.

GET PROPERTY OF e_cell 'Font' = e_bold.
SET PROPERTY OF e_bold 'Bold' = 1.

CALL METHOD OF e_appl 'Cells' = e_cell
EXPORTING
#1 = w_line
#2 = w_titles.

CONCATENATE '<fs_spfli>-' <fs_titles>-field
INTO w_field.
ASSIGN (w_field) TO <fs>.

SET PROPERTY OF e_cell 'Value' = <fs>.
GET PROPERTY OF e_cell 'Interior' = e_color.
SET PROPERTY OF e_cell 'ColumnWidth' = 20.
SET PROPERTY OF e_color 'ColorIndex' = 0.
GET PROPERTY OF e_cell 'Font' = e_bold.
SET PROPERTY OF e_bold 'Bold' = 0.
ENDLOOP.
ENDLOOP.

CALL METHOD OF e_work 'SAVEAS'
EXPORTING
#1 = p_file.

CALL METHOD OF e_work 'close'.
CALL METHOD OF e_appl 'QUIT'.
FREE OBJECT e_appl.

ENDFORM. " create_excel

Ahora...Una imagen...


Saludos,

Blag.

7 comments:

Anonymous said...

Si el funcional te llega a pedir que hagas un informe en excell y que se puede ejecutar en fondo. Hay si te veo sudar sangre.
Un saludo Jac.

Alvaro "Blag" Tejada Galindo said...

Puede ser...Pero quien dice que la mía es la única forma disponible?

https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/13121

https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/13092

https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/3808

Saludos,

Blag.

Anonymous said...

Si el funcional te llega a pedir que hagas un informe en excell y que se puede ejecutar en fondo. Hay si te veo sudar sangre. <--- Ami me encargaron eso, aparte tengo que enviarlo por correo. Alguna idea de si eso es posible y como puedo atacarlo. :'(

Anonymous said...

Hola Blag, buen blog, como siempre en lo que haces.
Yo cuando utilizo Ole2 y abap, lo que hago normalmente es grabar una macro en el excel de lo que quiero hacer y luego veo el código generado en visual basic y lo 'traduzco' a abap a base de prueba y error...

Ahora tengo que hacer una cosa que no se muy bien por donde cogerla, y es hacer un listBox en una celda de una lista de valores de otra pestaña...
he hecho el macro y tal, pero no tengo ni idea de como poner esto en abap.
Os pego el código, ¿Alguna idea?

With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=valor"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With

Thanks !

Anonymous said...

Excelente Ejemplo. Muchas gracias por compartirlo.

Atte. Noel Bravo

Anonymous said...

Hola blag hice un programa con ole pero al moneto k llena los datos al excel se demora un monton como se puede solucionar eso... lo he probado tanto en modo visible como no visible y en ambos demora...

Alvaro "Blag" Tejada Galindo said...

Definitivamente, utilizar Excel OLE siempre va a ser lento...este post lo escribi hace casi 3 anhos...y las cosas cambian -:)

Ahora podemos hacer lo que queramos con Excel utilizando ABAP2XLSX:

http://wiki.sdn.sap.com/wiki/display/ABAP/abap2xlsx

No es mi proyecto, pero si participe agregando un par de funcionalidades nuevas -;)

Saludos,

Blag.