logo

Les tables des matières expliquées à ma fille

Vos plus beaux documents produits via l’ODS (PDF, RTF, HTML, Excel) méritent, s’ils sont complexes, d’avoir une aide à la navigation. Ce document fait un tour d’horizon des possibilités, avec leurs pièges et leurs options, tout d’abord pour chacune des « destinations » de l’ODS, puis avec la procédure DOCUMENT et sa faculté de réorganiser les sorties, ainsi que leur arborescence, et donc de créer une table des matières totalement sur mesure.

Les exemples proposés dans ce document ont été construits avec SAS 9.2 sur Windows et sur Unix (dans ce dernier cas, via SAS Enterprise Guide) – en utilisant le même code sur ces deux environnements, on obtient les mêmes résultats.

1. Les options de tables des matières selon les destinations

1.1. ODS HTML : la navigation par les clics

Dès l’origine, c’est l’ODS HTML qui intègre la possibilité d’une table des matières. On l’obtient sous forme d’une page Web séparée, qu’on peut juxtaposer à la page Web principale au sein d’un contenant unique (la « frame »).

ODS HTML PATH="répertoire" (URL=NONE)
        GPATH="répertoire des images" (URL=NONE|"chemin relatif")
        FRAME="page principale.htm"
         FILE="page de résultats.htm"
     CONTENTS="page de navigation.htm"
          autres options ;

Les options indiquées dans cette syntaxe correspondent aux besoins suivants :

  • PATH et GPATH indiquent des répertoires.
    • PATH sera le répertoire commun aux fichiers HTML (dont les noms sont cités dans FILE, CONTENTS et FRAME). L’option URL=NONE permet de ne pas utiliser le chemin complet (indiquant tous les noms de répertoires de l’arborescence de fichiers, ce qu’on appelle aussi le « chemin physique ») pour les liens de navigation entre les fichiers HTML. Cela permet de porter plus facilement le résultat de l’ODS, à condition de déplacer ensemble tous les fichiers.
    • GPATH indique le répertoire de stockage des images produites par les procédures graphiques. Ce n’est pas forcément le même répertoire que celui de PATH. Si PATH et GPATH indiquent le même emplacement, utiliser l’option URL=NONE. Si GPATH est un sous-répertoire (par exemple, appelé img) de PATH, alors URL vaudra « img/ ». Si GPATH et PATH sont deux répertoires situés au même niveau, alors le chemin relatif sera « ../img/ », avec le .. qui indique de « remonter » d’un niveau dans l’arborescence.
  • FRAME indique la page HTML principale, celle que l’utilisateur visualise. Elle sert de contenant aux autres : sur la gauche, la page dont le nom est indiqué par CONTENTS et où se trouvent les liens de navigation. Sur la partie centrale et droite, la page citée dans FILE qui contient les sorties du code SAS.
ODS HTML PATH="c:\temp" (URL=NONE)
        GPATH="c:\temp\img" (URL="img/")
        FRAME="page principale.htm"
         FILE="page de résultats.htm"
     CONTENTS="page de navigation.htm"
        STYLE=SKETCH ;
PROC PRINT DATA=sashelp.class (OBS=3)
           NOOBS ;
RUN ;
PROC SGPLOT DATA=sashelp.class ;
  SCATTER X=height Y=weight / DATALABEL=name ;
RUN ;
ODS HTML CLOSE ;

Contenu du répertoire C:\TEMP après exécution du code ci-dessus. Le sous-répertoire IMG contient un fichier image (extension PNG) produit par la procédure SGPLOT.

tdm1

En ouvrant la page HTML « PAGE PRINCIPALE.HTM » on voit ceci :

tdm2

A gauche, la page de navigation (option CONTENTS), à droite la page de résultats (option FILE).

1.2. ODS RTF : la table des matières invisible

La syntaxe de l’ODS RTF est la plus simple : il suffit d’ajouter à l’instruction ouvrante deux options CONTENTS et TOC_DATA (attention à ne pas oublier l’une des deux !).

ODS RTF FILE="…" TOC_DATA CONTENTS … ;

Cependant, à l’ouverture du document, on ne voit rien !

La raison est qu’un document RTF est construit par SAS de manière linéaire, à partir du contenu généré par les procédures. La pagination se fait « au fil de l’eau » et c’est le logiciel qui affichera le document au final (Word, OpenOffice Writer) qui s’occupera de numéroter les pages et de gérer les transitions entre pages. SAS se contente donc d’insérer en tête de document un champ « table des matières » (option CONTENTS), et au fil des procédures, des champs marquant une entrée de table des matières (option TOC_DATA).

tdm3

On peut d’ailleurs débrancher temporairement TOC_DATA par NOTOC_DATA si une partie du document produit ne doit pas apparaître au sommaire !

ODS RTF FILE="%SYSFUNC(GETOPTION(work))/sommaire.doc" 
        CONTENTS TOC_DATA ;
ODS PROCLABEL "Table CLASS et proc PRINT" ;
PROC PRINT DATA=sashelp.class CONTENTS=" " ;
RUN ;
ODS RTF 
    NOTOC_DATA ; /* la sortie devient invisible dans le sommaire */
TITLE1 "Partie invisible" ;
PROC MEANS DATA=sashelp.cars MEAN MEDIAN ;
  VAR cylinders ;
  CLASS make ;
RUN ;
TITLE ;
ODS RTF TOC_DATA ; /* les sorties sont à nouveau dans le sommaire */
ODS PROCLABEL "SGPLOT : nuage poids * taille" ;
PROC SGPLOT DATA=sashelp.class DESCRIPTION=" " ;
  SCATTER X=height Y=weight ;
RUN ;
ODS RTF CLOSE ;

1.3. ODS PDF : le double choix marque-pages et table des matières

Dans les sorties PDF, on peut opter au choix pour une navigation par clics avec les signets présentés à gauche de l’écran, et le classique sommaire sans clics (du pur texte) pour la version qui sera imprimée.

ODS PDF FILE="…" CONTENTS 
                 PDFTOC=niveau 
                 NOBOOKMARKGEN|NOTOC
                 BOOKMARKLIST=NONE|HIDE|SHOW … ;

Le sommaire se demande avec l’option CONTENTS. Les signets sont présents par défaut ; on peut contrôler leur affichage et leur profondeur avec les options suivantes :

  • NOBOOKMARGEN : pas de signets générés sur ce document PDF. Contrairement à l’ODS RTF, cette option n’est pas réversible en cours de document.
  • BOOKMARKLIST= HIDE : les signets sont créés mais à l’ouverture du document, le volet des signets est masqué
  • PDFTOC=x : on ne montre que les x premiers niveaux de l’arborescence des signets. Tous sont générés, mais l’arborescence n’est pas totalement déployée. (Option disponible à partir de SAS 9.2)

L’option BOOKMARKLIST=NONE supprimera totalement les signets. Elle est équivalente à NOBOOKMARKGEN ou à l’option NOTOC.

ODS PDF FILE="%SYSFUNC(GETOPTION(work))/sommaire.pdf" 
        CONTENTS BOOKMARKLIST=HIDE PDFTOC=1 ;
ODS PROCLABEL "Table CLASS et proc PRINT" ;
PROC PRINT DATA=sashelp.class CONTENTS=" " ;
RUN ;
ODS PROCLABEL "Statistiques" ;
PROC MEANS DATA=sashelp.cars MEAN MEDIAN ;
  VAR cylinders ;
  CLASS make ;
RUN ;
ODS PDF CLOSE ;

Voici le résultat à l’ouverture du document. BOOKMARKLIST=HIDE a masqué le volet des onglets sur la gauche de l’écran.

tdm3b

Après ouverture du volet des onglets, on voit que PDFTOC=1 ne déplie spontanément que le 1er niveau des onglets. Les marques situées plus bas dans l’arborescence sont néanmoins bien positionnées et disponibles si besoin.

tdm4

Outre les tables des matières automatiques, on peut également recourir à des navigations personnalisées avec des liens internes au document. Le travail est alors à réaliser à la main, en jouant sur deux éléments :

  • l’option ANCHOR de l’instruction ODS PDF qui permet de créer des « ancres », c’est-à-dire des points de repère, portant un nom spécifique. Ces ancres se situent au début des sorties d’une procédure et sont invisibles pour le lecteur du document PDF ;
  • des liens hypertextes qui pointent vers ces ancres.
ODS PDF ANCHOR="nomAncre" … ;

On utilise pour construire la table des matières soit une procédure de listing avec une table SAS contenant les items vers lesquels pointer, soit une série d’instructions ODS PDF TEXT dont chacune génèrera une entrée dans la table des matières.

Solution 1 : avec une proc Report

Dans cette première version, on crée manuellement une table contenant les noms des ancres créées plus loin, et dans une seconde variable, le texte servant d’entrée de table des matières.

DATA work.sommaire ;
  INFILE DATALINES DLM="@" MISSOVER ;
  INPUT ancre :$10. intitule :$100. ;
DATALINES ;
données@Données de détail (enfants)
stats@Statistiques descriptives (moyenne et médiane par sexe)
;
RUN ;

Une fois la table créée, on insère en tête du fichier PDF une proc Report qui prendra la forme d’une table des matières. A chaque ligne de la table lue, on associe un lien calculé en ajoutant un # devant le nom de l’ancre vers laquelle pointe le lien. Quelques instructions de mise en forme pour assurer de grandes cellules de texte complètent le code. Pourquoi ces cellules de grande dimension ? Dans un document PDF, un lien hypertexte se signale par un liseré bleu autour du texte associé. Si le texte est dans un tableau, le liseré épouse la bordure de la cellule. Pour éviter que le liseré soit trop près du texte, on laisse un peu d’espace vide.

OPTION CENTER ;
ODS PDF FILE="c:\temp\anchor.pdf" NOTOC ;
PROC REPORT DATA=work.sommaire NOWD ;
  COLUMNS intitule ancre ;
  DEFINE intitule / "Table des matières"
     STYLE(COLUMN)=[CELLHEIGHT=20PT CELLWIDTH=15CM] ;
  DEFINE ancre / NOPRINT ;
  COMPUTE ancre ;
    CALL DEFINE("intitule","URL","#"!!ancre) ;
  ENDCOMP ;
RUN ;
OPTION NOCENTER ;

On notera dans ce code l’option NOTOC au niveau de l’ODS PDF afin de laisser seule la table des matières générée manuellement.

Enfin, les procédures alimentant le document PDF sont précédées d’une instruction ODS PDF avec l’option ANCHOR pour nommer l’ancre associée à ce résultat.

ODS PDF ANCHOR="données" ;
PROC PRINT DATA=sashelp.class ;
RUN ;
ODS PDF ANCHOR="stats" ;
PROC MEANS DATA=sashelp.class MEAN MEDIAN ;
  VAR height weight ;
  CLASS sex ;
RUN ;
ODS PDF CLOSE ;

Le résultat prend l’aspect suivant. Chaque texte encadré de bleu peut être cliqué pour « sauter » directement à la sortie correspondante.

tdm5

Solution 2 : avec ODS PDF TEXT

La logique est la même que dans l’exemple précédent (la génération des sorties elles-mêmes est d’ailleurs totalement identique) mais plutôt que de passer par une table SAS puis une procédure Report, la solution est ici d’écrire directement dans le document les lignes de texte ad hoc. Pour cela, on utilise l’instruction ODS TEXT.

ODS PDF TEXT="texte à insérer dans le document PDF" ;

Ce texte est rendu avec un style par défaut mais peut être amélioré par des éléments de mise en forme dits « intégrés » (on parle d’in-line formatting). Comme la mise en forme précède directement le texte associé au sein de la paire de guillemets, il importe de distinguer les deux (texte et options). Pour cela, on désigne un caractère d’échappement (ODS ESCAPECHAR) choisi arbitrairement[1]. Si on choisit la tilde par exemple, la syntaxe devient alors :

ODS ESCAPECHAR="~" ;
ODS PDF TEXT="~S={mise en forme}texte avec cette mise en forme" ;

La syntaxe ~S (pour Style) indique entre accolades l’ensemble des options de mise en forme qui s’appliquent au texte suivant l’accolade fermante. A partir de SAS 9.3, une syntaxe légèrement différente est proposée.

ODS ESCAPECHAR="~" ;
ODS PDF TEXT="~S={mise en forme texte avec cette mise en forme}" ;

Cette fois, les options de mise en forme précèdent le texte au sein de la paire d’accolades. Passée l’accolade fermante, on retrouve la mise en forme par défaut. Cette syntaxe, qui paraît moins simple, est surtout plus souple puisqu’elle permet d’incruster des styles en cascade.

ODS ESCAPECHAR="~" ;
%LET style=FONT_SIZE=14PT CELLHEIGHT=20PT CELLWIDTH=15CM ;
ODS PDF FILE="c:\temp\anchor2.pdf" NOTOC ;
ODS PDF TEXT="~S={FONT_WEIGHT=BOLD FONT_SIZE=20PT}Table des matières" ;
ODS PDF TEXT="~S={URL='#données' &style}Données de détail" ;
ODS PDF TEXT="~S={URL='#stats' &style}Statistiques descriptives" ;
ODS PDF STARTPAGE=NOW ;

Le reste du document est généré à l’identique de la méthode précédente ; les ancres nommées sont produites avec ODS PDF ANCHOR. Le résultat est le suivant.

tdm6

1.4. ODS TAGSETS.EXCELXP : la feuille de route

[La syntaxe et les options ci-dessous ont été testées sur la version v1.127 du tagset. Pour les versions plus anciennes, certaines options peuvent ne pas exister sans édition d’un message d’erreur. Pensez à toujours vérifier dans votre Log/Journal la version du tagset utilisé.]

ODS TAGSETS.EXCELXP FILE="…" OPTIONS(CONTENTS="YES"|"NO" 
                                        INDEX="YES"|"NO" 
                                      …) … ;

L’option CONTENTS permet de créer une feuille en tête de classeur avec des liens vers tous les éléments du classeur. Le contenu est à l’identique des signets PDF ou des tables des matières dans les autres destinations.

L’option INDEX permet de créer une feuille en tête de classeur avec des liens vers toutes les feuilles du classeur. Il n’y a dans ce cas qu’une ligne par feuille, même si celle-ci contient plusieurs tableaux.

tdm7

Les résultats ci-dessus ont été produits par le programme exemple suivant.

ODS TAGSETS.EXCELXP FILE="%SYSFUNC(GETOPTION(work))/sommaire.xls"
                   STYLE=JOURNAL
                      OPTIONS(CONTENTS="YES" INDEX="YES"
                         SHEET_INTERVAL="PROC") ;
ODS PROCLABEL "Table CLASS et proc PRINT" ;
PROC PRINT DATA=sashelp.class ;
RUN ;
ODS PROCLABEL "Statistiques" ;
PROC UNIVARIATE DATA=sashelp.cars ;
  VAR cylinders ;
RUN ;
ODS TAGSETS.EXCELXP CLOSE ;

2. Personnaliser une table des matières : options CONTENTS, ODS PROCLABEL

Dans les exemples précédents, la structure et les intitulés dans les navigations étaient tous dictés par les choix par défaut de SAS. La section suivante permettra de réorganiser la structure ; mais dès à présent on peut influer sur l’intitulé des liens dans la table des matières.

Le 1er niveau est celui de la procédure produisant la sortie. On l’altère avec l’instruction ODS PROCLABEL.

ODS PROCLABEL "nouvel intitulé de table des matières" ;

Cette instruction est automatiquement annulée après la fin de la procédure (RUN ou QUIT selon les cas). Il n’est donc pas utile, au contraire d’un TITLE, de prévoir une instruction rectificative. La valeur par défaut est « The XXX procedure » (ou sa traduction en français).

Sous ce premier niveau de libellé, on en trouve ensuite plusieurs, dans une arborescence plus ou moins complexe selon la procédure. Seules certaines d’entre elles (PRINT, TABULATE et REPORT – les trois procédures orientées reporting ; les procédures graphiques) proposent des options pour avoir la main sur l’intitulé des niveaux suivants : ce sont les options CONTENTS et DESCRIPTION.

Pour les autres procédures, on verra plus loin qu’une manipulation plus complexe permet néanmoins d’avoir la main sur l’intitulé souhaité.

Procédures de reporting : PRINT, TABULATE, REPORT

PROC PRINT DATA=… CONTENTS="intitulé dernier niveau" … ;

La procédure PRINT est la plus simple : une seule option CONTENTS qui correspond à l’unique niveau de l’arborescence situé sous le niveau piloté par PROCLABEL. On peut supprimer ce niveau d’arborescence avec CONTENTS= » » (sans espace entre les guillemets).

ODS PDF FILE="%SYSFUNC(GETOPTION(work))/sommaire.pdf" ;
ODS PROCLABEL "Niveau 1 (PROCLABEL)" ;
PROC PRINT DATA=sashelp.prdsale (OBS=10)
          CONTENTS="Niveau 2 (PROC)" ;
RUN ;
ODS PDF CLOSE ;

tdm8

PROC TABULATE DATA=… CONTENTS="intitulé niveau intermédiaire" … ;
  …
  TABLE … / CONTENTS="intitulé dernier niveau" … ;
RUN ;

On remarquera que TABULATE, qui crée une arborescence en plusieurs strates, propose deux options CONTENTS qui sont complémentaires et permettent de personnaliser les deux niveaux situés sous le niveau « PROCLABEL ». Les deux niveaux peuvent êtres supprimés par CONTENTS= » » (sans espace entre les guillemets).

ODS PDF FILE="%SYSFUNC(GETOPTION(work))/sommaire.pdf" ;
ODS PROCLABEL "Niveau 1 (PROCLABEL)" ;
PROC TABULATE DATA=sashelp.prdsale 
          CONTENTS="Niveau 2 (PROC)" ;
     CLASS country year ;
     VAR actual ;
     TABLE country="", year="" * actual=""*SUM="" 
        / CONTENTS="Niveau 3 (TABLE)" ;
RUN ;
ODS PDF CLOSE ;

tdm9

PROC REPORT DATA=… NOWD CONTENTS="intitulé niveau intermédiaire" … ;
  COLUMNS … ;
  DEFINE variable / CONTENTS="intitulé dernier niveau" PAGE … ;

Dans la procédure REPORT, il faut indiquer 2 niveaux d’options CONTENTS. Le premier est analogue aux procédures PRINT et TABULATE, le second se greffe dans l’instruction DEFINE de la première variable citée dans COLUMNS. Pour faire effet, elle doit impérativement s’accompagner de l’option PAGE.

Si on peut supprimer le niveau intermédiaire avec CONTENTS= » » (sans espace entre les guillemets) au niveau de l’instruction PROC, en revanche, ce n’est pas possible avec le dernier niveau défini au niveau de l’instruction DEFINE.

ODS PDF FILE="%SYSFUNC(GETOPTION(work))/sommaire.pdf" ;
ODS PROCLABEL "Niveau 1 (PROCLABEL)" ;
PROC REPORT NOWD DATA=sashelp.prdsale 
          CONTENTS="Niveau 2 (PROC)" ;
     COLUMNS country year actual;
     DEFINE country / GROUP CONTENTS="Niveau 3 (DEFINE)" PAGE ;
     DEFINE year / GROUP ;
     DEFINE actual / ANALYSIS SUM "Ventes" ;
RUN ;
ODS PDF CLOSE ;

tdm9b

Procédures graphiques : GPLOT, GCHART, SGPLOT, etc.

Il existe un système similaire pour les procédures graphiques (GCHART, GPLOT, GMAP) avec cette fois une option DESCRIPTION qui est l’équivalent de CONTENTS. Il n’y a que deux niveaux d’arborescence (PROCLABEL et donc DESCRIPTION) ; mais l’option vient se nicher dans l’instruction graphique (VBAR, HBAR, PIE, STAR pour GCHART, PLOT ou BUBBLE pour GPLOT et BLOCK, CHORO, etc. pour GMAP).

Dans tous les cas, il n’est pas possible d’éliminer de niveau d’arborescence avec DESCRIPTION= » » (avec ou sans espace entre les guillemets).

PROC GCHART|GMAP|GPLOT DATA=… ;
  instruction graphique / DESCRIPTION="intitulé dernier niveau" … ;
RUN ; QUIT ;

Pour les procédures graphiques plus récentes (SGPLOT, SGPANEL, …) l’option DESCRIPTION remonte au niveau de l’instruction PROC, comme dans la procédure PRINT.

PROC SGPLOT|SGSCATTER|SGRENDER|SGPANEL DATA=… 
                    DESCRIPTION="intitulé dernier niveau" … ;

Un exemple qui combine les procédures ancienne génération (GCHART) et nouvelle génération (SGPLOT) pour produire le même graphique.

ODS PDF FILE="%SYSFUNC(GETOPTION(work))/sommaire.pdf" ;
ODS PROCLABEL "GCHART : Niveau 1 (PROCLABEL)" ;
PROC GCHART DATA=sashelp.cars ;
  VBAR origin / DESCRIPTION="Niveau 2 (VBAR)" ;
RUN ;
ODS PROCLABEL "SGPLOT : Niveau 1 (PROCLABEL)" ;
PROC SGPLOT DATA=sashelp.cars DESCRIPTION="Niveau 2 (PROC)" ;
  VBAR origin ;
RUN ;
ODS PDF CLOSE ;

tdm10

Autres procédures : modification du modèle tabulaire

Pour les autres procédures que celles citées ci-dessus, les choses sont plus compliquées. Il n’y a pas d’option dans leur syntaxe pour personnaliser l’intitulé associé à la procédure ; seul le 1er niveau peut être modifié avec ODS PROCLABEL. Pour le niveau suivant, il faut intervenir sur le modèle tabulaire de la sortie en question.

La figure ci-dessous[2] indique à quel moment intervient le modèle tabulaire. Un modèle tabulaire est associé à chaque objet ODS, c’est-à-dire à chaque tableau produit par une procédure. Pour connaître son nom, on utilise principalement la syntaxe ODS TRACE qui affiche dans la fenêtre Log/Journal les caractéristiques de chaque objet produit.

ODS TRACE ON ;
PROC … ;
…
RUN ;
ODS TRACE OFF ;

tdm11

Quand une procédure est exécutée avec ODS TRACE activé, la fenêtre Log/Journal contient des blocs rédigés ainsi : ci-dessous une procédure Means a été soumise à SAS.

tdm12

Le nom du modèle tabulaire se trouve à la ligne « Template » (dans les versions françaises de SAS, « Modèle »). Pour la procédure Means, il s’appelle donc BASE.SUMMARY.

Ce modèle pilote la mise en forme du tableau rendu par la procédure : nom et ordre des colonnes, format des valeurs, etc. Une de ses propriétés se nomme CONTENTS_LABEL ; c’est elle qui indique comment afficher l’entrée de table des matières ou le signet PDF correspondant à cet objet.

Cependant, on n’imagine pas devoir retoucher ce modèle (en faisant intervenir une procédure Template) à chaque procédure Means qu’on souhaite exécuter ! On peut paramétrer une nouvelle définition du modèle tabulaire qui aurait comme valeur de l’attribut CONTENTS_LABEL une macro-variable dynamique. Le modèle tabulaire serait sauvegardé ainsi, sans valeur particulière pour la macro-variable, dans la bibliothèque personnelle de l’utilisateur (SASUSER). Il resterait alors à définir avant chaque procédure Means la macro-variable ad hoc pour y inscrire le message souhaité.

PROC TEMPLATE;
  EDIT base.summary ;
    MVAR monLabel ;
    contents_label = monLabel ;
  END ;
RUN ;

Le code ci-dessus redéfinit le modèle tabulaire associé à la procédure Means en lui associant la macro-variable MONLABEL. Vient ensuite le moment d’exécuter la procédure Means, ce qui se fait ainsi.

ODS PDF FILE="c:\temp\tabulaire.pdf" ;
ODS PROCLABEL="Statistiques descriptives" ;
%LET monLabel = Moyenne et médiane du poids ;
PROC MEANS DATA=sashelp.class MEAN MEDIAN ;
  VAR weight ;
  CLASS sex ;
RUN ;
%SYMDEL monLabel ;
ODS PDF CLOSE ;

L’instruction %SYMDEL permet de supprimer la macro-variable et ainsi de revenir au libellé par défaut. La logique est la même qu’avec l’effacement des titres et des pieds de page après une procédure. On constate que le résultat est conforme à nos souhaits.

tdm13

On peut généraliser cette approche à tous les modèles tabulaires, c’est-à-dire in fine à toutes les procédures sauf Print, Tabulate, Report, les procédures graphiques et la procédure Freq quand elle produit des tableaux croisés. Cependant, la redéfinition des modèles tabulaires est une tâche ingrate : elle est longue et lourde, et ne peut se systématiser qu’en écrivant des macro-programmes alambiqués. Pour personnaliser une procédure Univariate par exemple, il faudrait modifier plus d’une vingtaine de modèles tabulaires (par défaut, Univariate produit déjà 5 objets ODS et ce nombre peut enfler avec diverses options).

Quant à la diffusion des modèles modifiés, elle peut se réaliser en stockant les nouvelles définitions e dehors de la bibliothèque SASUSER, dans un espace partagé par plusieurs utilisateurs ; il suffit ensuite d’une modification de l’instruction ODS PATH pour indiquer à SAS où chercher les nouveaux modèles tabulaires.

3. Personnaliser une table des matières : ODS DOCUMENT

3.1. Principe de fonctionnement

Quand on sollicite une procédure, le fonctionnement de SAS est d’envoyer ses sorties dans toutes les destinations ODS ouvertes. Mais une fois la procédure terminée, impossible de modifier son emplacement des fichiers générés, ni ses titres ou pieds de page. Impossible… sauf avec ODS DOCUMENT.

tdm14

Le principe est d’envoyer la sortie de la procédure dans un fichier intermédiaire appelé document. Cet archivage sera accessible par SAS pour des retouches ultérieures. Il ne fait l’objet d’aucune mise en forme pour le moment, et le contenu de l’archivage pourra être « rejoué », en partie ou totalement, plus tard pour un envoi sous la forme ODS définitive.

L’étape intermédiaire de manipulation du document permet de changer aussi bien les intitulés que l’ordre des tableaux produits au fil de l’eau par SAS. On peut même jouer sur les hiérarchies en créant ou en supprimant des niveaux de répertoires dans le document.

3.2. Stockage avec ODS DOCUMENT

La première phase est donc d’alimenter l’archive. Pour cela, on encapsule la ou les procédures dont on veut manipuler les sorties à l’intérieur d’un sandwich ODS spécifique.

ODS DOCUMENT NAME=bib.nomArchive (WRITE|UPDATE) ;
PROC xxx … ;
…
RUN ;
etc.
ODS DOCUMENT CLOSE ;

Le nom du document suit les normes habituelles pour une table SAS : le nom d’une bibliothèque le précède, et il occupe 32 caractères au maximum, des lettes non accentuées, des chiffres et des underscores. L’option WRITE après le nom du document crée un document nouveau. L’option UPDATE ajoute au document s’il existe déjà.

Bien que stocké dans une bibliothèque, le document n’est pas visible avec les autres objets SAS (tables, vues, catalogues). Comme un index, il existe mais SAS ne l’affiche pas dans ses fenêtres. Son type est un item store, comme pour les définitions de styles, des modèles graphiques GTL ou de mises en formes tabulaires : l’item store est un type de fichier largement utilisé dans la sphère ODS.

 

Côté procédures, toutes sont supportées à partir de la version 9.2, y compris les graphiques de toutes générations (procédures G et SG). En revanche, en SAS 8 et 9.1, la procédure PRINT avec une instruction BY, et surtout la procédure REPORT ne sont pas compatibles avec l’archivage en document. La proc PRINT génère une archive où les éléments sont dupliqués, la proc REPORT n’est pas acceptée à l’intérieur de l’archive.

Dans le client lourd SAS, on peut consulter le contenu de l’archive avec la commande ODSDOC à exécuter dans la fenêtre de commandes (à gauche de la barre d’outils). Dans SEG, on utilisera du code pour visualiser ce que contient un document.

PROC DOCUMENT NAME=bib.nomArchive ;
  LIST / LEVELS=ALL ;
RUN ; QUIT ;

En reprenant les exemples précédents et en les stockant dans un document commun, on obtient ceci.

ODS DOCUMENT NAME=work.archive (WRITE) ;
ODS PROCLABEL "Niveau 1 (PROCLABEL)" ;
PROC REPORT NOWD DATA=sashelp.prdsale 
          CONTENTS="Niveau 2 (PROC)" ;
     COLUMNS country year actual;
     DEFINE country / GROUP CONTENTS="Niveau 3 (DEFINE)" PAGE ;
     DEFINE year / GROUP ;
     DEFINE actual / ANALYSIS SUM "Ventes" ;
RUN ;
ODS PROCLABEL "GCHART : Niveau 1 (PROCLABEL)" ;
PROC GCHART DATA=sashelp.cars ;
  VBAR origin / DESCRIPTION="Niveau 2 (VBAR)" ;
RUN ;
ODS PROCLABEL "SGPLOT : Niveau 1 (PROCLABEL)" ;
PROC SGPLOT DATA=sashelp.cars DESCRIPTION="Niveau 2 (PROC)" ;
  VBAR origin ;
RUN ;
ODS DOCUMENT CLOSE ;

L’archive créée est ici stockée dans la WORK. Son contenu s’affiche ainsi (on notera l’extrême limpidité des noms automatiques dans l’arborescence).

tdm15

Les noms visibles dans le tableau ci-dessus seront ceux à employer lors de la manipulation de l’archive.

3.3. Réagencement des sorties : instructions MAKE, MOVE et SETLABEL

Dans la procédure DOCUMENT, trois instructions ont une action directe sur les tables des matières et autres signets : MAKE, MOVE et SETLABEL.

  • MAKE permet de créer un nouveau répertoire dans l’arborescence du document. Cet ajout peut se faire à côté des répertoires existants ou à l’intérieur de ceux-ci. On peut ainsi modifier l’organisation des rubriques dans la table des matières et la profondeur des arborescences.
MAKE chemin complet du répertoire créé ;
  • MOVE déplace un répertoire ou un élément terminal (tableau, graphique ; disons de manière générique un objet ODS) vers un autre répertoire de la même archive. Cette instruction est essentielle à la réorganisation.
MOVE chemin complet du répertoire ou de l’objet existant TO ^ ;
  • SETLABEL a pour objet de changer l’intitulé de table des matières et de signet d’un niveau de répertoire ou d’un objet ODS. Il permet d’éviter les arrachages de cheveux de la partie 2 autour de l’existence (ou non) d’une option CONTENTS ou DESCRIPTION, et les batailles avec ODS PROCLABEL. Tout peut ici être réajusté a posteriori.
SETLABEL chemin complet du répertoire ou de l’objet 
               "nouveau libellé" ;

tdm16

Lors du démarrage de la proc DOCUMENT, le répertoire courant est la racine de l’archive (cf. schéma ci-dessus). On peut indiquer un autre répertoire courant avec l’instruction DIR. Dans tous les cas, le répertoire courant est désigné par le caractère ^ (accent circonflexe) dans la proc DOCUMENT. La racine est désignée par un \ (antislash) comme dans les chemins Unix.

DIR chemin complet du répertoire devant le répertoire courant ;

Un exemple qui reprend l’archive précédente pour organiser deux répertoires : tableaux et graphiques. La procédure REPORT aura ses résultats dans le 1er, les procédures GCHART et SGPLOT dans le 2e.

PROC DOCUMENT NAME=work.archive ;
  MAKE tableaux ;
  MAKE graphiques ;
  DIR \tableaux ;
  MOVE \Report#1\Report#1\Report#1 TO ^ ;
  DIR \graphiques ;
  MOVE \Gchart#1\GCHART#1 TO ^ ;
  MOVE \Sgplot#1\SGPlot#1 TO ^ ;
RUN ; QUIT ;

3.4. Réédition des sorties avec PROC DOCUMENT

Pour renvoyer vers l’ODS une partie ou l’intégralité d’un document, on utilise l’instruction REPLAY de la proc DOCUMENT.

PROC DOCUMENT NAME=bib.nomArchive ;
  REPLAY ^  ;
  REPLAY chemin d’un répertoire ;
RUN ; QUIT ;

L’exemple renvoie le résultat des manipulations de l’archive des sections précédentes.

ODS PDF FILE="%SYSFUNC(GETOPTION(work))/test.pdf" CONTENTS ;
ODS RTF FILE="%SYSFUNC(GETOPTION(work))/test.doc" 
        CONTENTS=YES TOC_DATA ;
PROC DOCUMENT NAME=work.archive ;
  REPLAY \tableaux ;
  REPLAY \graphiques ;
RUN ; QUIT ;
ODS PDF CLOSE ;
ODS RTF CLOSE ;

Voici le résultat dans le document Word.

tdm17

Et dans Acrobat Reader pour le PDF.

tdm18

Remarque : Dans les sorties rééditées par la procédure Document, les titres et pieds de page sont ceux définis lors du stockage dans l’archive. Si on souhaite mettre à jour ces titres ou pieds de page avec les instructions TITLE et FOOTNOTE courantes, on ajoutera à l’instruction REPLAY les options ACTIVETITLE et ACTIVEFOOTN après un slash.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

[1] Dans les exemples les plus récurrents, on trouve l’accent circonflexe utilisé seul, ou la tilde. Il s’agit d’utiliser un caractère suffisamment rare pour ne pas avoir d’ambiguïté avec le texte lui-même. Le caractère ¤ obtenu avec la combinaison de touches ALTGR + $ est également un bon candidat mais n’est pas toujours supporté sous SAS Enterprise Guide : méfiance !

 

[2] Reprise du livre Reporting avec SAS, Olivier Decourt, éditions Dunod

2 found this helpful