Return to ODS MARKUP

Base SAS

The htmlpanel Tagset Controls Paneling

Putting tables and graphs side-by-side or in more complex layouts has always been difficult or impossible. This tagset solves that problem by providing automatic, semi-automatic, and manually controlled paneling. The htmlpanel tagset is supported in SAS 9.1 and later.

A Simple Example

This tagset inherits most of its behavior from the HTML4 tagset. The HTML4 tagset is what you are using when you invoke the ODS HTML destination. By default, only BY-grouped graphs are paneled. Also by default the panels have two columns and no borders. The titles and footnotes appear once, outside the paneled graphs.

   %inc "htmlpanl.tpl";

   ods tagsets.htmlpanel file="gbypanel.html";
   goptions dev=javaimg xpixels=480 ypixels=320;

   title1 "A by-group test";
   footnote1 "A Footnote";

   proc gchart data=sashelp.class;
      by weight;
      hbar age / sumvar=height;

   ods _all_ close;

Getting Help

This tagset is one of the first to have built-in help. This feature only works with SAS 9.1.3 and later. The help text, which is sent to the SAS log, shows sample usage and explains the options and event controls for the htmlpanel tagset. The DOC= option has three values:


You can get help on the opening ODS statement or any time after the destination has been opened. Here are some examples:

   ods tagsets.htmlpanel file="gbypanel.html" options(doc='help');

   ods tagsets.htmlpanel options(doc='quick');

   ods tagsets.htmlpanel options(doc='settings');

Controlling the Columns and Borders

The number of columns defaults to two. But you can change that with a macro variable or through an OPTIONS parameter. OPTIONS is a very flexible feature for tagsets. An option is a name-value pair. That name and value are passed through to the tagset. It is the tagset that defines any option that it recognizes and uses.

Note: You must download the SAS 9.2 htmlpanel tagset (.zip) to use these OPTIONS values in SAS 9.1.3. The values are not shipped in the SAS 9.1.3 tagset. The downloaded SAS 9.2 tagset actually works in SAS 9.1 and later, but the OPTIONS syntax is supported beginning with SAS 9.1.3.

   /* Change the number of columns to 3 */

   %let panelcolumns = 3;

   /* Put a 4-pixel border around all the panels */

   %let panelborder = 4;

Using the OPTIONS syntax can be more straightforward, because it appears on the ODS statement. The following opening statements are equivalent to the macro variable settings above.

   ods tagsets.htmlpanel file="gbypanel.html"
       options(panelcolumns = '3' panelborder = '4');

   /* The options can be changed at any time, not just at the beginning */

   ods tagsets.htmlpanel options(panelcolumns = '3' panelborder = '4');

Semi-automatic paneling is the next-simplest thing to do. In this case you can tell ODS when to start paneling and when to stop. Here's a simple example that puts three outputs from PROC PRINT side-by-side:

   /* Change the number of columns to 3 */

   %let panelcolumns = 3;

   ods tagsets.htmlpanel file="printpanel.html";

   /* Start the paneling */

   ods tagsets.htmlpanel event = panel(start);

   proc print data=sashelp.class;run;
   proc print data=sashelp.class;run;
   proc print data=sashelp.class;run;

   ods tagsets.htmlpanel event = panel(finish);

Controlling Titles and BY Lines

The default is for titles and footnotes to be outside the panel. The titles that are in effect when the panel starts are used. The first footnotes defined are what come out when the panel stops. There is another option to put the titles inside the panels.

Note: Automatic paneling only works with legacy image formats when the NOGTITLE option is specified on the ODS statement.

   /* Put titles and footnotes inside the panels */

   %let embedded_titles = yes;

   /* OR */

   ods tagsets.htmlpanel options(embedded_titles = 'yes');

Another desirable behavior is the removal of the VARIABLE= in BY lines. That can be controlled using the BYLABELS option.

   /* Remove BY labels */

   %let bylabels = no;

   /* OR */

   ods tagsets.htmlpanel options(bylabels = 'no');

Here is a simple example using all of the features so far:

   goptions dev=gif xpixels=480 ypixels=320;

   /* NOGTITLE is necessary for automatic paneling to work when      */
   /* the device is one of the legacy image formats. GIF, JPEG, etc. */

   ods tagsets.htmlpanel nogtitle file="printpanel2.html"

   /* Start the paneling */

   ods tagsets.htmlpanel event = panel(start);

   title 'First PROC PRINT';

   proc print data=sashelp.class;run;

   title 'Second PROC PRINT';
   proc print data=sashelp.class;run;

   title 'Third PROC PRINT';
   proc print data=sashelp.class;run;

   /* Stop the current panel */

   ods tagsets.htmlpanel event = panel(finish);

   /* Change the panel settings */

   ods tagsets.htmlpanel options(panelcolumns='2'

   /* This BY group gets a panel of its own */

   title ;

   proc sort data=sashelp.class out=foo;
      by age;

   proc gchart data=foo;
     by age;
     hbar weight / sumvar=height;

   /* Start a new, semi-automatic panel */

   ods tagsets.htmlpanel event = panel(start);

   title 'Fourth PROC PRINT';
   proc print data=sashelp.class;run;

   title 'Fifth PROC PRINT';
   footnote 'End of Fifth proc Print';
   proc print data=sashelp.class;run;

   ods tagsets.htmlpanel event = panel(finish);

   ods _all_ close;

Manual Panel Controls

The most complex usage of the htmlpanel tagset is manually controlled panels. All automatic behavior is suspended when these controls are used. The complexity of manually controlled panels is that panels can be nested. Panels come in two flavors: row-wise panels and column-wise panels. With just these two types, very complex layouts can be created. These panels can be started and stopped in the same way the semi-automatic panels can. They are events that are called from the ODS statement. The following example is very simple. More comprehensive examples are included with the tagset (.zip).

   ods tagsets.htmlpanel file="manualpanel.html";

   ods tagsets.htmlpanel event=row_panel(start);
   ods tagsets.htmlpanel event=column_panel(start);

   proc print data=sashelp.class;run;
   proc print data=sashelp.class;run;

   ods tagsets.htmlpanel event=column_panel(finish);

   proc gchart data=sashelp.class;
     hbar age / sumvar=height;

   ods tagsets.htmlpanel event=row_panel(finish);

   ods tagsets.htmlpanel close;

Adding Scrolling Tables

Because the htmlscroll and htmlpanel tagsets have no overlap of events, it is a simple matter of inheritance to combine the two. The inheritance can go either way. It seems to make the most sense to have htmlpanel inherit from htmlscroll. Just change this line:


To look like this:



The tagset and examples are available in a .zip file.

Your Turn

Send e-mail to with your comments.

Last Updated: June 2004