h1

Améliorer l’habillage de vos tableaux (débuter avec PROC TEMPLATE via PROC REPORT)

juin 2, 2008

La syntaxe ODS (Output Delivery System) de SAS fait appel à des templates pour définir la mise en forme des tableaux, graphiques à publier. Dans le cas présent, il s’agira de définir un template qui s’appliquera à tous les tableaux générés par un PROC REPORT. Les styles caractérisant les templates sont définis avec la procédure PROC TEMPLATE. Tout d’abord, il s’agit de savoir comment appliquer les styles sans template pour un seul PROC REPORT et ainsi se familiariser avec la syntaxe.

1. Le tableau par défaut

Le programme suivant créé un document RTF (CLASS_V1.RTF) contenant un tableau avec 5 colonnes. Les données proviennent du data set CLASS de la bibliothèque SAS.

ods rtf file = ‘C:/sasreference/class_v1.rtf’;
proc report data=sashelp.class nowd;
columns sex name age height weight;
define sex    / display ‘Sexe’;
define name   / display ‘Nom’;
define age    / display ‘Age’;
define height / display ‘Taille’;
define weight / display ‘Poids’;
run;
ods rtf close;

Le tableau est quadrillé. Les lettres sont alignées à gauche et les chiffres à droite. Le nom des colonnes ont un fond grisé et sont mises en gras. Le tout a une police Times New Roman de taille 10pt.

2. Des styles pour trois destinations différentes

Dans PROC REPORT, on peut ajouter des options au niveau de l’instruction PROC REPORT pour appliquer le résultat à l’intégralité de la table ou dans une instruction DEFINE en particulier pour agir sur une colonne. Il est possible de grouper les deux méthodes. Par exemple, on peut choisir d’avoir des colonnes de trois centimètres partout sauf dans une colonne.

  • STYLE(COLUMN) : pour changer les informations au niveau des colonnes, c’est-à-dire les données sans le titre, on ajoutera STYLE(COLUMN)=[…] dans l’instruction DEFINE.
  • STYLE(HEADER) : pour modifier les caractéristiques des noms de colonnes, les headers, il faudra utiliser STYLE(HEADERr)=[…]
  • STYLE(REPORT) : pour définir les bordures, leur position, couleur et épaisseur, et les espaces entre les cellules, STYLE(REPORT)=[…] est utilisé dans l’instruction PROC REPORT.

3. De multiples options

Les options sont listées dans les crochets, Un espace sert de séparateur entre les options. Voici un aperçu de ces options:

3.1 Agir sur le texte

  • FONT_FACE= ou comment définir une police différente de Times : pour changer la police en Arial, on fait appel à FONT_FACE=’Arial’.
  • FONT_SIZE= ou comment opter pour une taille de caractères différente de 10pt : pour changer la taille du texte en 12, cela donne FONT_SIZE=12pt.
  • FONT_WEIGHT ou comment jongler entre gras et normal : pour mettre en gras, on utilisera FONT_WEIGHT=BOLD. Si au contraire est déjà en gras, et qu’on souhaite le remettre en normal, il faut choisir FONT_WEIGHT=MEDIUM.
  • FOREGROUND= ou comment changer la couleur du texte : l’option FOREGROUND= sert à définir la couleur du texte. Ainsi FOREGROUND=DARKBLUE mettra le texte en bleu foncé.

3.2 Agir sur la position du texte

  • JUST= ou comment changer l’alignement en largeur du texte dans une cellule : par défaut les lettres sont alignés à gauche et les nombres sont alignés à droite. Pour définir le même alignement partout et ensuite changer ponctuellement si besoin, il y a JUST=. Ainsi, JUST=C (center) centre, JUST=R (right) aligne à droite et JUST=L (left) aligne à gauche.
  • VJUST= ou comment changer l’alignement vertical du texte dans une cellule : si le texte d’une case s’étend sur plusieurs lignes, celui des autres cellules est aligné vers le haut. Pour changer l’alignement, on utilise VJUST=BOTTOM.

3.3 Changer la couleur de fond

  • STYLE(COLUMN)=[BACKGROUND=…] ou comment changer le fond des cellules contenant les observations.
  • STYLE(HEADER)=[BACKGROUND=…] ou comment changer la couleur de fond des titres des colonnes.
  • STYLE(REPORT)=[BACKGROUND=… ] ou comment changer l’arrière plan : défini dans STYLE(REPORT), la couleur s’applique à l’arrière du tableau. Si l’espace qui sépare les cellules n’est pas de zéro (CELLSPACING), cette couleur de fond apparaît. Par défaut la couleur noir apparaît entre les cellules. On peut soit changer la couleur pour blanc (BACKGROUND=WHITE) ou réduire l’espace entre les cellules à zéro (CELLSPACING=0).
  • CELLWIDTH= ou comment définir la largeur des colonnes : la largeur de toutes les cellules d’une colonne est défini par CELLWIDTH. Cela donne CELLWIDTH=3cm.

3.4 Agir sur les bordures

  • BORDERCOLOR= ou comment changer la couleur des bordures
  • BORDERWIDTH= ou comment changer  la largeur des bordures du cadre (frame).
  • FRAME= ou comment décider quels côtés du cadre doivent apparaître : on distingue huit valeurs pour FRAME :
    • BOX garde tout le cadre extérieur
    • VOID enlève les bords du cadre
    • HSIDES (horizontal side) garde les deux côtés horizontaux
    • VSIDES (vertical side) garde les deux côtés verticaux
    • ABOVE garde la ligne du dessus,
    • BELOW garde la ligne du dessous
    • LHS (left hand side) garde le côté gauche
    • RHS (right hand side) garde le côté droite
  • RULES= ou comment décider quelles lignes à l’intérieur du tableau doivent être visible : on a cinq valeurs à disposition pour RULES :
    • NONE (none ou aucun) enlève toutes les lignes intérieures
    • ROWS (row ou ligne) ne garde que les lignes horizontales
    • COLS (column ou colonne) ne garde que les lignes verticales
    • GROUP ne garde que la ligne séparant les titres de colonnes, des observations.

Voici donc un schéma récapitulalif des combinaisons de FRAME et RULES lorsque, dans STYLE(REPORT), BACKGROUND=WHITE ou CELLSPACING=0. Pour facilité la lecture, l’effet de FRAME est en noir et celui de RULES est en rouge.

*NB: Cette image contient une erreur : remplacez grps par group.

4. L’effet final avec les options de PROC REPORT

Voici un résumé de l’Exemple ci-dessous :

  • Seules les bordures du haut et du bas sont gardées (FRAME=HSIDES), et épaissie (BORDERWIDTH=.2cm) après avoir mis en blanc l’arrière plan du tableau pour qu’il n’apparaisse pas entre les cellules (BACKGROUND=WHITE). On choisi de séparer les titres des valeurs par une ligne  (RULES=GROUPS) et de mettre tous les trais en gris (BORDERCOLOR=GRAY).
  • Au niveau des titres, la couleur de fond est enlevée (BACKGROUND=WHITE).  Une police Arial de 12pt non gras est choisie.
  • Enfin au niveau des données, la police est également Arial de taille 12pt. Les colonnes sont de 3 cm de largeur et le texte est aligné à droite.

ods rtf file  = ‘C:/sasreference/final_v1.rtf’
        style = sasref;

proc report data=sashelp.class nowd
style(report)=[rules       = groups
frame       = hsides
background  = white
                /*cellspacing = 0*/
bordercolor = gray
borderwidth = .2cm]
style(header)=[background  = white
font_size   = 12pt
font_face   = ‘Arial’
font_weight = medium]
style(column)=[font_size   = 12pt
font_face   = ‘Arial
cellwidth   = 3 cm
just        = r];
columns name sex age height weight;
define name   / display ‘Nom’;
define sex    / display ‘Sexe’;
define age    / display ‘Age’;
define height / display ‘Taille’;
define weight / display ‘Poids’;
run;

ods rtf close;

5. Obtenir le même résultat avec un proc template

A présent que vous avez vu les différentes régions sur lesquelles vous pouvez agir et une grande partie des options que vous pouvez changer, voici la syntaxe de PROC TEMPLATE.

Ici, le nouveau template s’appelle SASREF (DEFINE STYLE). Il est basé sur le style par défaut (PARENT=).

proc template;
define style styles.sasref;
parent = styles.default;
/*.à compléter..*/
   end;
run;

Vous remarquerez que les informations listées dans REPLACE TABLE sont les mêmes que dans notre précédent ODS(REPORT). Celles listées dans REPLACE HEADER correspondent à celle de ODS(HEADER) et enfin celle de REPLACE DATE sont identiques à ODS(COLUMN).

proc template;
define style styles.sasref;
parent = styles.default;
replace table /  rules       = groups
frame       = hsides
background  = white
                  /*cellspacing = 0*/
bordercolor = gray
borderwidth = .2cm;
replace header / foreground  = black
background  = white
font_size   = 12pt
font_face   = ‘Arial’
                    font_weight = medium;
replace data   / background  = white
font_size   = 12pt
font_face   = ‘Arial’
cellwidth   = 3 cm
just        = r;
end;
run;

Vous noterez en plus l’utilisation de FOREGOUND dans REPLACE HEADER et BACKGROUND dans REPLACE DATA. En effet, si vous appelez le template sans les instructions REPLACE, SAS ajoute un font gris aux données et met les titres en bleu.

A présent, il s’agit de faire référence à ce template dans l’instruction ODS RTF.

ods rtf file  = ‘C:/sasreference/class_v1.rtf’
style = sasref;

Avant de terminer, il vous faudra supprimer le template.

proc template;
delete styles.sasref;
run;

21 commentaires

  1. Bonjour,

    Pourquoi, avant de terminer, faut-il supprimer le template ?

    Merci.


  2. Supprimer le template n’est pas une obligation.

    Mais avoir un SAS propre en fin de programme c’est une bonne habitude. Cela évite les mauvaises surprises lorsqu’on exécute d’autres programmes par la suite. Et cela réduit les zones de recherche pour débugger un programme.

    De plus, lorsq’on continue de programmer, on part d’a priori sur les options et autres. Et on programme en fonction. C’est d’autant plus important que d’autres personnes sont amenées à inclure le programme dans leur propre programme ou doivent continuer le développement.

    C’est le même principe que déactiver une bibliothèque, supprimer les formats, les macros variables globales, réinitiationes les options standards (options…) ou les options graphiques (goptions).

    Cela répond t-il à votre question ?


  3. Cela répond tout à fait à ma question, merci. Je n’avais pas pensé au fait de garder la session « propre ». J’étais plus dans l’optique de conserver le template afin de l’utiliser à nouveau pour d’autres rapports (ODS PATH) mais cela fera probablement le sujet d’un autre article…

    Si la suppression des formats ou des variables macro est une chose que je fais systématiquement, comment désactive-t-on une bibliothèque ? Et lorsqu’on crée un petit catalogue macro sasmacr dans la bibliothèque temporaire work, peut-on le supprimer par une ligne de commande sans fermer la session SAS ?

    Merci.


  4. Pour supprimer un nom de bibliothèque, on utilise le mot-clé CLEAR:

    libname sasref ‘C:/sasref’;
    libname sasref clear;

    (ou libname _all_ clear; pour toutes les désassigner).

    Voir l’article suivant sur les bibliothèques :
    http://www.sasreference.com/2008/03/06/libname/

    Un catalogue macro est, d’après ma compréhension de la documentation en ligne SAS, assigné pour l’intégralité d’une session SAS. Dès lors, dans la même session, vous ne pouvez ni le supprimer, ni supprimer la bibliothèque qui a servi éventuellement pour sa création. A vous de tenir compte de ce constat lors de la programmation.

    Pour supprimer un catalogue macro permanent dans une autre session, vous pouvez faire appel à la procédure PROC DATASETS :

    libname sasref ‘C:/sasref’;

    proc datasets lib=sasref memtype=catalog;
    delete sasmacr;
    run;

    Par contre, si vous voulez supprimer le contenu du catalogue plutôt que le catalogue lui-même, il faudra faire appel à la procédure PROC CATALOG.

    proc catalog cat=sasref.sasmacr;
    delete test_perm / et=macro;
    run;

    Je vous propose un exemple où deux catalogues qui contiennent chacun une macro. L’un est temporaire, l’autre est permanent.

    libname sasref ‘C:/sasref’;
    options mstored sasmstore=sasref;

    %macro test_perm/store;
    proc print data=sashelp.class;
    run;
    %mend test_perm;

    %macro test_tmp;
    proc print data=sashelp.class;
    run;
    %mend test_tmp;

    title ‘Before’;
    proc sql;
    select *
    from dictionary.catalogs
    where upcase(libname) in (‘WORK’,’SASREF’);
    quit;

    proc catalog cat=sasref.sasmacr;
    delete test_perm/et=macro;
    run;

    proc catalog cat=work.sasmacr;
    delete test_tmp/et=macro;
    run;

    title ‘After’;
    proc sql;
    select *
    from dictionary.catalogs
    where upcase(libname) in (‘WORK’,’SASREF’);
    quit;


  5. C’est parfait. Merci beaucoup.


  6. Bonjour,

    Une petite question…
    J’essaie désespérement de toruver une façon de fusionner les cases de ma première colonne, puisque celle ci est en option « group » dans ma report.
    J’ai une macro word pour faire ça, mais j’essaie d’automatiser le plus possible mes sorties sas.
    Je ne sais pas si c’est possible, mais si oui, et si vous savez comment, alors je veux bien savoir !!


  7. Bonjour,

    Il n’y a pas à ma connaissance de moyen direct d’appliquer les lignes par groupe. En effet, seul RULES=GROUP pourrait potentiellement répondre à votre question. Mais en faisant le test, on se rend compte que cela ne fonctionne pas.

    Je vous propose donc d’insérer une ligne blanche à la place du trait entre vos groupements via COMPUTE.

    Voici donc votre exemple mis à jour :

    data essai;
    input patient visite valeur;
    cards;
    1 1 0.1
    1 2 0.2
    1 3 0.4
    2 1 0.6
    2 2 0.4
    2 3 0.2
    3 1 0.3
    3 2 0.2
    3 3 0.8
    4 1 0.1
    4 2 0.2
    4 3 0.5
    5 1 0.1
    5 2 0.6
    5 3 0.4
    ;
    run;

    ods rtf file= »C:/sasref/essai.rtf »;
    proc report data=essai nowindows
    style(report)=[rules = group
    frame = hsides
    cellspacing = 0];

    column patient visite valeur;
    define patient / group ;
    define visite / display ;
    define valeur / display ;

    compute before;
    line ‘ ‘;
    endcomp;

    compute after patient;
    line ‘ ‘;
    endcomp;
    run;
    ods rtf close;

    Cela vous convient-il ?


  8. Merci de cette réponse rapide.

    Cette solution avait effectivement été évoquée dans ma boîte, mais cela ne règle pas le problème. Cela revient au même de récupérer une sortie classique et de faire le travail sur word, que de modifier ce nouveau tableau.

    Je me doutais bien que SAS ne fusionnait pas… tant pis !

    Merci en tout cas.


  9. Bonjour,

    y a t-il un moyen de modifier le background des cellules d’une colonne selon la valeur prise par la variable ? Par exemple: un background vert pour une valeur faible et rouge pour des valeurs fortes?

    D’avance merci.


  10. Bonjour,

    On peut remplacer la couleur de la colonne par un format. Voici un petit exemple où la cellule est mise en jaune clair quand l’âge est inférieur à 13 ans.

    proc format;
    value age
    low-<13=’light yellow’;
    run;

    ods rtf file=’C:/sasref/couleur_fond.rtf’;
    proc report data=sashelp.class;
    columns name age;
    define name / display;
    define age / display style(column)=[background=age.];
    run;
    ods rtf close;

    Cela répond t-il à votre question ?


  11. Bonjour
    est-il possible de ne faire apparaitre dans une sortie rtf que les lignes horizontales par groupe ?
    ex: dans sashelp.class, je trie ma table par sex, et je voudrai en sortie un tableau avec une ligne horizontale apres les headers, une ligne horizontale apres la premiere modalite de la variable sex et une seconde à la fin de mon tableau, et ceci si possible via une proc template.
    Merci de votre réponse.


  12. Bonjour,

    j’ai exactement le même problème que MAthieu, comment faire pour séparer les groupes par une ligne!
    Merci d’avance


  13. Bonjour,

    Lorsque j’ai besoin d’ajouter des lignes ,j’utilise COMPUTE dans PROC REPORT car BREAK AFTER n’a pas d’effet avec l’ODS RTF.

    Je n’ai pas connaissance de la syntaxe pour agir au niveau du template, s’il y en a une. Mais l’idée est bonne.

    Si d’autres lecteurs ont eu l’opportunité d’approfondir le sujet, ils sont les bienvenus pour apporter leur expérience.

    Voici donc dans un premier temps un exemple avec COMPUTE.

    proc sort data=sashelp.class out=class;
    by sex;
    run;

    ods listing close;
    ods rtf file=’C:/sasref/test.rtf’;

    proc report data=class nowd;
    columns sex age;
    define sex/group;
    define age/display;

    compute before;
    line ‘ ‘;
    endcomp;
    compute after sex;
    line ‘ ‘;
    endcomp;
    run;

    ods rtf close;
    ods listing;

    Une autre solution pour l’espace après le header est de définir une hauteur un peu plus grande et d’aligner vers le haut les noms de colonne.
    – Mais d’une part cela ne traite pas le problème des lignes entre les BY variables.
    – D’autre part, il faut mieux enlever la couleur de fond et les lignes pour une présentation agréable.

    proc sort data=sashelp.class out=class;
    by sex;
    run;

    ods listing close;
    ods rtf file=’C:/sasref/test.rtf’;

    proc report data=class nowd
    style(report)=[frame=void rules=none background=white]
    style(header)=[cellheight=1cm vjust=top background=white ];
    columns sex age;
    define sex/group;
    define age/display;
    run;

    ods rtf close;
    ods listing;


  14. avec la 9.2, que j’ai la chance d’avoir (elle va être déployée en décembre 2008)
    c’est facile, cette nouvelle version est beaucoup mieux pour les reporting.
    sinon j’ai eu l’idée suivante en 9.1 mais c’est difficile à macrotiser…
    ods rtf file= »G:/assens/essai/data_colle2.rtf » ;

    ods rtf sectiondata= »\sbknone » ;
    title  » SECTIONDATA TEST ON  » ;

    data hommes;
    set sashelp.class (where= (sex= »M »));
    run;

    proc report data=hommes nowd
    style(report)=[frame=box rules=all background=white borderwidth= 3 pt]
    style(header)=[cellheight=1cm vjust=top background=white bordercolor=black]
    style(column)=[ borderwidth= 1 pt] ;
    columns (« ceci est un essai » sex age height);
    define sex/group style=[cellwidth=2 cm ];
    define age/display style=[cellwidth=5 cm ];
    define height/display style=[cellwidth=5 cm ];
    run;

    data femmes;
    set sashelp.class (where= (sex= »F »));
    run;

    proc report data=femmes nowd noheader
    style(report)=[frame=box rules=all background=white borderwidth= 3 pt]
    style(column)=[ borderwidth= 1 pt] ;
    columns sex age height;
    define sex/group style=[cellwidth=2 cm ];
    define age/display style=[cellwidth=5 cm ] ;
    define height/display style=[cellwidth=5 cm ];
    run;

    ods rtf close;


  15. […] Améliorez l’habillage de vos tableaux (débuter avec PROC TEMPLATE) […]


  16. Bonjour,

    est il possible de mixer plusieurs style de bordures ?

    ex:
    header => avec rules = all, frame = box,
    contenu => avec rules = cols, frame = box,
    ligne conditionnée* => avec rules = all, frame = box

    *IF maValeur=’X’ THEN CALL DEFINE(_ROW_, « STYLE », …)

    Merci par avance. (et un grand merci pour ce site trés utile)


  17. RULES et FRAME influence le cadre au niveau de la table uniquement.

    Maintenant si je vais un test avec COMPUTE et des options censées fonctionner au niveau de la cellule, je vois que la couleur de fond (BACKGROUND=) fonctionne mais pas les options BORDERCOLOR et BORDERWIDTH.

    proc sort data=sashelp.class out=class;
    by sex;
    run;

    ods listing close;
    ods rtf file=’/by-sast/sasuser/eziqv/test.rtf’;

    proc report data=class nowd;
    columns sex age;
    define sex/group ;
    define age/display;
    compute age;
    if age=13 then call define (_col_,’style’,’style=[background=yellow bordercolor=red borderwidth=100pt]’);
    endcomp;
    run;

    ods rtf close;
    ods listing;

    Source : SAS Online Doc


  18. […] Améliorer l’habillage de vos tableaux (débuter avec PROC TEMPLATE via PROC REPORT) […]


  19. […] Améliorer l’habillage de vos tableaux (débuter avec PROC TEMPLATE au moyen de PROC REPORT) […]


  20. Bonjour j’ai un problème.
    Je souhaite esxporter une sortie tabulate vers excel en spécifiant les cellules dans lequels je veux exporter la table.J’ai déjà fais la mise en forme sous excel.
    J’ai utilisé la procédure template et l’ods (

    FILENAME excel DDE « Excel|Segperim!L4C2:L12C5 » NOTAB ;
    ODS MARKUP TYPE=xlDDE FILE = excel ;
    proc tabulate data=&lib..Base_Geode_&aamm
    ….;
    run;
    ods markup close; )
    Les valeurs sont bien exportés mais j’ai un problèmes avec mes libellés.
    Lorsque j’ai des cellules fusionnés, les noms de clonnes ne sont pas au bon endroit.
    Merci de m’aider.


  21. Bonjour,

    Je souhaite colorer certaines lignes d’une table SAS en utilisant la procédure print et l’ods.

    Est ce possible?

    Si non, comment faire?

    Merci par avance.



Laisser un commentaire