|
Código fuente -
Utilidades con ficheros
|
|
Domingo, 16 de Mayo de 2004 00:44 |
|
Comparación de ficheros
REPORT z_file_compare LINE-SIZE 1023.
*** tables
DATA : BEGIN OF tbl_fichier1 OCCURS 0,
zone(1000),
END OF tbl_fichier1.
DATA : tbl_fichier2 LIKE tbl_fichier1 OCCURS 0 WITH HEADER LINE.
DATA : BEGIN OF tbl_fichier2_tri OCCURS 0,
zone(1000),
index LIKE sy-tabix,
traite,
END OF tbl_fichier2_tri.
DATA : BEGIN OF tbl_diff OCCURS 0,
code,
zone(1000),
num_ligne1 TYPE i,
num_ligne2 TYPE i,
END OF tbl_diff.
DATA : BEGIN OF tbl_idx OCCURS 0,
index_old TYPE i,
index_new LIKE sy-tabix,
END OF tbl_idx.
*** variable
DATA : d_nblignes1 TYPE i,
d_nblignes2 TYPE i,
d_flag_ident,
d_flag_diff.
******************** ECRAN DE SELECTION ***************************
****** 1 er fichier
SELECTION-SCREEN BEGIN OF BLOCK bl1 WITH FRAME TITLE text-001.
*** ligne fichier PC
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(10) text-021 FOR FIELD p_pc1.
SELECTION-SCREEN POSITION 15.
PARAMETER : p_pc1 RADIOBUTTON GROUP g1 USER-COMMAND clak DEFAULT 'X'.
SELECTION-SCREEN POSITION 20.
PARAMETER : p_file1 LIKE rlgrap-filename.
SELECTION-SCREEN END OF LINE.
*** ligne fichier AS400
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(13) text-022 FOR FIELD p_as4001.
SELECTION-SCREEN POSITION 15.
PARAMETER : p_as4001 RADIOBUTTON GROUP g1.
SELECTION-SCREEN POSITION 20.
PARAMETER : p_fas1 LIKE filename-fileextern DEFAULT '/tmp/'.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK bl1.
****** 2 ème fichier
SELECTION-SCREEN BEGIN OF BLOCK bl2 WITH FRAME TITLE text-002.
*** ligne fichier PC
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(10) text-021 FOR FIELD p_pc2.
SELECTION-SCREEN POSITION 15.
PARAMETER : p_pc2 RADIOBUTTON GROUP g2 USER-COMMAND clak DEFAULT 'X'.
SELECTION-SCREEN POSITION 20.
PARAMETER : p_file2 LIKE rlgrap-filename.
SELECTION-SCREEN END OF LINE.
*** ligne fichier AS400
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(13) text-022 FOR FIELD p_as4002.
SELECTION-SCREEN POSITION 15.
PARAMETER : p_as4002 RADIOBUTTON GROUP g2.
SELECTION-SCREEN POSITION 20.
PARAMETER : p_fas2 LIKE filename-fileextern DEFAULT '/tmp/'.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK bl2.
AT SELECTION-SCREEN OUTPUT.
**** grise le nom du fichier non désiré
LOOP AT SCREEN .
IF p_as4001 = 'X' AND screen-name = 'P_FILE1'.
screen-input = 0.
MODIFY SCREEN.
ELSEIF p_pc1 = 'X' AND screen-name = 'P_FAS1'.
screen-input = 0.
MODIFY SCREEN.
ENDIF.
IF p_as4002 = 'X' AND screen-name = 'P_FILE2'.
screen-input = 0.
MODIFY SCREEN.
ELSEIF p_pc2 = 'X' AND screen-name = 'P_FAS2'.
screen-input = 0.
MODIFY SCREEN.
ENDIF.
ENDLOOP.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file1.
*** aide si utilisateur fait F4
PERFORM f4_file USING p_file1.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file2.
*** aide si utilisateur fait F4
PERFORM f4_file USING p_file2.
*****************
START-OF-SELECTION.
*** chargement fichier 1
IF p_pc1 = 'X'.
PERFORM chargement_fichier_pc TABLES tbl_fichier1 USING p_file1.
ELSE.
PERFORM chargement_fichier_serveur TABLES tbl_fichier1 USING p_fas1.
ENDIF.
*** chargement fichier 2
IF p_pc2 = 'X'.
PERFORM chargement_fichier_pc TABLES tbl_fichier2 USING p_file2.
ELSE.
PERFORM chargement_fichier_serveur TABLES tbl_fichier2 USING p_fas2.
ENDIF.
*** vérification fichiers non vides
IF tbl_fichier1[] IS INITIAL.
MESSAGE i398(00) WITH 'Le fichier 1 est vide'.
STOP.
ENDIF.
IF tbl_fichier2[] IS INITIAL.
MESSAGE i398(00) WITH 'Le fichier 2 est vide'.
STOP.
ENDIF.
*** remplissage table triée
PERFORM fill_table2_tri.
*** traitement
PERFORM traitement.
*** report
PERFORM report.
END-OF-SELECTION.
*&---------------------------------------------------------------------*
*& Form f4_file
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_P_FILE text
*----------------------------------------------------------------------*
FORM f4_file USING p_file.
CALL FUNCTION 'WS_FILENAME_GET'
EXPORTING
def_filename = ' '
def_path = 'c:'
mask = '*.*,Tous *.*.'
mode = ' '
title = text-002
IMPORTING
filename = p_file
EXCEPTIONS
inv_winsys = 1
no_batch = 2
selection_cancel = 3
selection_error = 4
OTHERS = 5.
ENDFORM. " f4_file
*&---------------------------------------------------------------------*
*& Form chargement_fichier_pc
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_TBL_FICHIER1 text
* -->P_P_FILE1 text
*----------------------------------------------------------------------*
FORM chargement_fichier_pc TABLES p_table USING p_file.
CALL FUNCTION 'WS_UPLOAD'
EXPORTING
* CODEPAGE = ' '
filename = p_file
filetype = 'ASC'
* HEADLEN = ' '
* LINE_EXIT = ' '
* TRUNCLEN = ' '
* USER_FORM = ' '
* USER_PROG = ' '
* DAT_D_FORMAT = ' '
* IMPORTING
* FILELENGTH =
TABLES
data_tab = p_table
EXCEPTIONS
conversion_error = 1
file_open_error = 2
file_read_error = 3
invalid_type = 4
no_batch = 5
unknown_error = 6
invalid_table_width = 7
gui_refuse_filetransfer = 8
customer_error = 9
OTHERS = 10
.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE 'I' NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
MESSAGE e398(00) WITH text-003 p_file.
ENDIF.
ENDFORM. " chargement_fichier_pc
*&---------------------------------------------------------------------*
*& Form chargement_fichier_serveur
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_TBL_FICHIER1 text
* -->P_P_FAS1 text
*----------------------------------------------------------------------*
FORM chargement_fichier_serveur TABLES p_table USING p_file.
OPEN DATASET p_file FOR INPUT IN TEXT MODE.
IF sy-subrc <> 0.
MESSAGE e398(00) WITH text-004 p_file.
ENDIF.
DO.
READ DATASET p_file INTO p_table.
IF sy-subrc <> 0.
EXIT.
ENDIF.
APPEND p_table.
ENDDO.
CLOSE DATASET p_file.
ENDFORM. " chargement_fichier_serveur
*&---------------------------------------------------------------------*
*& Form fill_table2_tri
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM fill_table2_tri.
LOOP AT tbl_fichier2.
tbl_fichier2_tri-zone = tbl_fichier2-zone.
tbl_fichier2_tri-index = sy-tabix.
APPEND tbl_fichier2_tri.
ENDLOOP.
SORT tbl_fichier2_tri.
*** nouveaux index en fonction de l'ancien
LOOP AT tbl_fichier2_tri.
tbl_idx-index_old = tbl_fichier2_tri-index.
tbl_idx-index_new = sy-tabix.
APPEND tbl_idx.
ENDLOOP.
SORT tbl_idx BY index_old.
ENDFORM. " fill_table2_tri
*&---------------------------------------------------------------------*
*& Form traitement
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM traitement.
DATA : l_tabix1 LIKE sy-tabix,
l_tabix2 LIKE sy-tabix,
l_tabix2_last LIKE sy-tabix,
l_tabixtmp LIKE sy-tabix.
*** nombre de lignes des tables
DESCRIBE TABLE tbl_fichier1 LINES d_nblignes1.
DESCRIBE TABLE tbl_fichier2 LINES d_nblignes2.
LOOP AT tbl_fichier1.
l_tabix1 = sy-tabix.
*** lecture de la premiere ligne semblable dans le 2eme fichier
READ TABLE tbl_fichier2_tri WITH KEY zone = tbl_fichier1-zone
traite = space
BINARY SEARCH.
IF sy-subrc = 0.
*** sauvegarde de l'index de la ligne
l_tabix2 = sy-tabix.
d_flag_diff = 'X'.
l_tabixtmp = tbl_fichier2_tri-index.
PERFORM append_diff2 USING tbl_fichier2_tri-index l_tabix2_last.
*** on ajoute une ligne semblable
tbl_diff-zone = tbl_fichier1-zone.
tbl_diff-code = '0'.
tbl_diff-num_ligne1 = l_tabix1.
tbl_diff-num_ligne2 = l_tabixtmp.
APPEND tbl_diff.
*** lecture et marquage de la ligne semblable du fichier 2
READ TABLE tbl_fichier2_tri INDEX l_tabix2.
tbl_fichier2_tri-traite = 'X'.
MODIFY tbl_fichier2_tri INDEX l_tabix2.
ELSE.
*** ligne présente uniquement dans le fichier 1
d_flag_ident = 'X'.
tbl_diff-zone = tbl_fichier1-zone.
tbl_diff-code = '1'.
tbl_diff-num_ligne1 = l_tabix1.
tbl_diff-num_ligne2 = 0.
APPEND tbl_diff.
ENDIF.
ENDLOOP.
*** traitement des lignes restantes du fichier 2
l_tabixtmp = d_nblignes2.
ADD 1 TO l_tabixtmp.
PERFORM append_diff2 USING l_tabixtmp l_tabix2_last.
ENDFORM. " traitement
*&---------------------------------------------------------------------*
*& Form append_diff2
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_L_TABIX2 text
*----------------------------------------------------------------------*
FORM append_diff2 USING p_tabix2 p_tabix2_last.
*** cette routine traite toutes les lignes du fichier 2 dont les
*** index sont inférieurs à la ligne semblable qu'on vient de
*** trouver ou alors inférieurs à la dernière ligne du fichier 1
*** ET supérieurs à p_tabix2_last. Cette valeur transmise en paramètre
*** contient
*** l'index courant du dernier numéro de ligne traitée du fichier 2.
*** Ces lignes sont donc des lignes du fichier 2 absentes du fichier 1.
DATA : l_index LIKE sy-tabix.
l_index = p_tabix2.
DO.
*** index de la premiere ligne non traitée du fichier2
ADD 1 TO p_tabix2_last.
*** si on arrive à la ligne "en cours", on sort
IF p_tabix2_last = l_index.
EXIT.
ENDIF.
*** lecture de l'index dans la table
*** triée, du numero de ligne du fichier 2
READ TABLE tbl_idx WITH KEY index_old = p_tabix2_last
BINARY SEARCH.
IF sy-subrc = 0.
*** lecture et marquage de la ligne differente du fichier 2
READ TABLE tbl_fichier2_tri INDEX tbl_idx-index_new.
tbl_fichier2_tri-traite = 'X'.
MODIFY tbl_fichier2_tri INDEX tbl_idx-index_new.
d_flag_ident = 'X'.
*** ajout de la ligne différente du fichier 2
tbl_diff-zone = tbl_fichier2_tri-zone.
tbl_diff-code = 2.
tbl_diff-num_ligne1 = 0.
tbl_diff-num_ligne2 = tbl_fichier2_tri-index.
APPEND tbl_diff.
*** si on est à la fin du fichier 2, on sort
ELSE.
EXIT.
ENDIF.
ENDDO.
ENDFORM. " append_diff2
*&---------------------------------------------------------------------*
*& Form report
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM report.
DATA : l_lastflag,
l_index_debut LIKE sy-tabix,
l_index_fin LIKE sy-tabix,
l_long_serie TYPE i,
l_indextmp LIKE sy-tabix,
l_code LIKE tbl_diff-code,
l_texte(50),
l_tmp(10).
*** rappel des noms de fichier
IF p_pc1 = 'X'.
WRITE : / p_file1.
ELSE.
WRITE : / p_fas1.
ENDIF.
l_tmp = d_nblignes1.
CONCATENATE 'Nombre de lignes : ' l_tmp INTO l_texte.
WRITE / l_texte.
SKIP.
IF p_pc2 = 'X'.
WRITE : / p_file2.
ELSE.
WRITE : / p_fas2.
ENDIF.
l_tmp = d_nblignes2.
CONCATENATE 'Nombre de lignes : ' l_tmp INTO l_texte.
WRITE / l_texte.
ULINE.
IF d_flag_ident IS INITIAL.
WRITE / 'Les 2 fichiers sont identiques'.
ELSEIF d_flag_diff IS INITIAL.
WRITE / 'Les 2 fichiers sont totalement différents'.
ELSE.
LOOP AT tbl_diff.
l_code = tbl_diff-code.
*** nouvelle suite
AT NEW code.
l_index_debut = sy-tabix.
ENDAT.
*** la rupture permet de compter à l'avance la longueur de la suite
*** de lignes semblables afin de l'abréger si elle est plus grande que 7
AT END OF code.
l_index_fin = sy-tabix.
l_long_serie = l_index_fin - l_index_debut + 1.
SKIP.
FORMAT COLOR COL_BACKGROUND INTENSIFIED ON.
CASE l_code.
WHEN '0'.
WRITE / 'Lignes semblables :'.
WHEN '1'.
WRITE / 'Lignes présentes uniquement dans le fichier 1 :'.
WHEN '2'.
WRITE / 'Lignes présentes uniquement dans le fichier 2 :'.
ENDCASE.
*** si la serie de lignes semblables est plus longue que 7, on la
*** raccourci.
IF l_long_serie >= 7 AND l_code = '0'.
l_indextmp = l_index_debut.
DO 3 TIMES.
PERFORM write_ligne USING l_indextmp.
ADD 1 TO l_indextmp.
ENDDO.
*** ligne abrégée
FORMAT COLOR COL_BACKGROUND INTENSIFIED OFF.
WRITE : /(6) '...'.
WRITE 8(6) '...'.
WRITE : 19 '...'.
l_indextmp = l_index_fin - 3.
DO 3 TIMES.
ADD 1 TO l_indextmp.
PERFORM write_ligne USING l_indextmp.
ENDDO.
ELSE.
l_indextmp = l_index_debut.
DO l_long_serie TIMES.
PERFORM write_ligne USING l_indextmp.
ADD 1 TO l_indextmp.
ENDDO.
ENDIF.
ENDAT.
ENDLOOP.
ENDIF.
ENDFORM. " report
*&---------------------------------------------------------------------*
*& Form write_ligne
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_L_INDEXTMP text
*----------------------------------------------------------------------*
FORM write_ligne USING p_indextmp.
DATA : l_num6(6) TYPE n.
READ TABLE tbl_diff INDEX p_indextmp.
FORMAT COLOR COL_BACKGROUND INTENSIFIED OFF.
*** numero de ligne fichier 1
IF tbl_diff-num_ligne1 IS INITIAL.
WRITE : /(6) space.
ELSE.
l_num6 = tbl_diff-num_ligne1.
WRITE : /(6) l_num6.
ENDIF.
*** numero de ligne fichier 2
IF tbl_diff-num_ligne2 IS INITIAL.
WRITE : 8(6) space.
ELSE.
l_num6 = tbl_diff-num_ligne2.
WRITE 8(6) l_num6.
ENDIF.
*** ligne du fichier
CASE tbl_diff-code.
WHEN '0'.
WRITE : 19 tbl_diff-zone COLOR COL_BACKGROUND INTENSIFIED OFF.
WHEN '1'.
WRITE : 19 tbl_diff-zone COLOR 1 INTENSIFIED OFF.
WHEN '2'.
WRITE : 19 tbl_diff-zone COLOR 2 INTENSIFIED OFF.
ENDCASE.
ENDFORM. " write_ligne
|