The SAS Output Delivery System and reporting techniques

Struggling with Styles

Reply
Occasional Contributor
Posts: 9

Struggling with Styles

I have been reading the documentation for ODS, and struggling with using styles with Proc Report for a few days now.

So, HELP.

I created a simple report:

<code>

proc report data=summarized;

  column basename filetype files size=total timeframe,size;

  define basename / group ;

  define filetype / group ;

  define files / analysis sum format=comma7. ;

  define total / analysis sum format=bytes. ;   * -- bytes is a predefined format by me ;

  define timeframe / across ;

  define size / analysis sum format=bytes. ;

break after basename / ol summarize skip ;

  rbreak after / dol summarize;

run;

quit;

</code>

But, when I put it into the ODS document system for later output into a PDF file,

It looses the overline, double overline, and skip.

So, to get the "skip" back I have had to include:

<code>

  compute after basename ;

    line ' ' ;

  endcomp;

</code>

But, I have been going nuts trying to change the border lines = borderbottomstyle and bordertopstyle

And the fonts, etc.

I wanted to use Proc Template to group all the customizations together, and that has been a disaster as well.

I can't seem even to take baby steps.

This shoud not be this hard.

SAS Super FREQ
Posts: 8,744

Re: Struggling with Styles

Hi:

  Many of the options that you used (OL, DOL, SKIP, etc) are LISTING only options (also LISTING only options are PANEL, SPACING, BOX, FLOW, WIDTH, LS and PS). These LISTING options would be ignored by ODS whether you used ODS DOCUMENT or not. To prove this to yourself, you can try a simple program like this (without using ODS DOCUMENT):

  

ods listing;

title; footnote;

options center nodate nonumber orientation=portrait;

    

** Note how LISTING options will be ignored by PDF;

** note also that the PDF output does NOT look like LISTING output;

ods pdf file='c:\temp\no_list_techniques.pdf';

 

proc report data=sashelp.class nowd;

  column  sex age height weight;

  define sex / group f=$3.;

  define age / group ;

  define height / analysis sum format=comma7. ;

  define weight / analysis sum format=comma7. ;

  break after sex / ol summarize skip ;

  rbreak after / dol summarize;

run;

 

ods _all_ close;

Now, if you compare the LISTING window output to the PDF file, you will see that LISTING techniques are ignored by PDF. The whole idea of overlining and underlining pieces of a report, like summary lines, has become sort of obsolete, since PDF, RTF and HTML all create report tables with very distinct interior table lines and you can use other techniques for highlighting summary rows other than a row of equal signs for double overlining or double underlining. (you can make the summary line bold, you can make it the same color as the header cells, you can change the color of the font or make the font italic or make the font bigger...)

  The technique that you used to introduce the equivalent of a SKIP into the output is the correct technique. Since SKIP was designed for LISTING there was no way that SKIP would have worked anywhere but LISTING. This Tech Support note (and many previous forum postings) explain this behavior:

http://support.sas.com/kb/2/549.html (note that the date on this note is 2002 -- this behavior has been documented for quite a while)

and the workaround using style attributes for PDF and RTF is available as a Tech Support note: http://support.sas.com/kb/42/743.html

and the workaround for other options is here as a Tech Support FAQ: http://support.sas.com/rnd/base/ods/templateFAQ/report1.html

  When I use the code below with TEXTDECORATION to do the OVERLINE, I had to also use the JOURNAL style to remove the interior table lines, so the OVERLINE would be visible. When I replayed the saved DOCUMENT, the overlines show up in the replayed PDF file.

cynthia

** now, create a PDF document using PROC REPORT;

** with style= overrides for the break lines;

** and capture the output in an ODS DOCUMENT store;

ods listing close;

ods document name=work.doc(write);

ods pdf file='c:\temp\use_ods_techniques.pdf'

        style=journal;

    

proc report data=sashelp.class nowd;

  column  sex age height weight;

  define sex / group f=$3.;

  define age / group ;

  define height / analysis sum format=comma7. ;

  define weight / analysis sum format=comma7. ; 

  break after sex / summarize style={textdecoration=overline};

  compute after sex;

    line ' ';

  endcomp;

  rbreak after /summarize style={textdecoration=overline};

run;

   

ods _all_ close;

ods document close;

     

** now replay the document;

ods listing;

ods pdf file='c:\temp\replay_doc.pdf' style=journal;

proc document name=work.doc;

  replay;

run;

quit;

ods pdf close;

PROC Star
Posts: 1,236

Re: Struggling with Styles

Hi,

A few quick thoughts.

1. I would suggest instead of writing to ods document, write straight to a pdf file.  That will take any  document/replay issues out of the mix.

2. Try writing a simple ods pdf example, and see if you can get the formatting you want.  Write it around a sashelp dataset, so that you can post your example code with questions.  something like:

ods pdf file="d:\junk\mypdf.pdf";
proc report data=sashelp.shoes nowd;
  define region /group;
  break after region/ dol summarize;
run;
ods pdf close;

3. I think the OL  DOL options only apply to the list (i.e. standard text) output. To get them into your pdf, you are correct that you need to use  ODS styles (either a template or in-line formatting.)

4. A great reference for ODS is "Output Delivery System: The  basics and behond" by Haworth, Zender & Burlew.  There are also lots of user group papers (lexjansen.com).

HTH

--Q.

Occasional Contributor
Posts: 9

Re: Struggling with Styles

I have to write to an ODS document first because I have to play around with the pathing to create the TOC correctly.

I was from the documentation that OL, etc. are "listing" only options.

I believe this limitation flies in the face of SAS simplifying programming as a 4GL when using ODS outputs.  The "skip" should still work, SAS should simply interpret it as a "compute ... endcompute;" option for us.

I never saw "textdecoration" in any of the SAS documentation I have read through for the past three days in relationship to proc report, ODS and styles.

It never even showed up in the proc template list=all

Where did "Journal" come from? and why would I have to use that "style" as my base?

This is too hard/convoluted and arcane.

Also, I am using EG and batch SAS in a Unix environment.

My EG does not show SASHELP.tmplmst or whater the template master is, or at least it does not show up in the library list.

I suppose that is because it is an item store and not a SAS dataset, so .... another aggrevation.

OK, enough steam whistle blowing.

So how do I find what I need to know in the documentation?

Or are there only white papers and SUGI papers that cover the information?

I don't remember who, think is was tech support, that pointed me to a paper to customize the TOC.

What a pain that has been as well.

Can be done, but the hoops you have to jump through are rediculous.

SAS makes analyzing the data I have to chunk through easy.

SAS reporting makes up for that with ever increasing _________________

Over the past 16 years, I have met people every now and then who claim to "know all things SAS", or some such thing.

Cindy, you are the closest I have ever found to actually fulfilling that remark.

Keep up your good work, and helpful patience.


SAS Super FREQ
Posts: 8,744

Re: Struggling with Styles

Hi:

  I'm not sure where to start. So let me start where I think the beginning is.

 

  LISTING or a "plain" text file was the first and ONLY output that SAS could produce for a long, long time. LISTING output was generally printed on a physical device (printer) that had a fixed pitch (or monospace) font and, so, achieving the "modern" look of proportional fonts was just not possible in LISTING output. So distinguishing one line on a report from the other by lines of dashes or equal signs was the only way to call attention to a break line. The LISTING output (what started as a "plain" text file) became known as "monospace" output when fancy printers with proportional fonts became available. When ODS was introduced, the LISTING output became known as the LISTING destination and/or traditional "monospace" output or the traditional "monospace" destination.

 

  At any rate, options that developed over the years, which were designed to work in an EBCDIC (the really old days) or ASCII text file on ALL platforms, are just not appropriate options for the varying result types such as HTML, RTF, PDF, CSV, LaTeX and other ways of presenting output when you use ODS (starting with SAS version 7).

 

  So, while I do understand your frustration, in the documentation, for example on the SKIP option of the BREAK statement DOES say (on the line for Restriction) that:

http://support.sas.com/documentation/cdl/en/proc/63079/HTML/default/viewer.htm#p16uti3vzgml7gn1nt3ov...

"SKIP

  Restriction: This option has no effect on ODS destinations other than traditional SAS monospace output."

 

  Any PROC REPORT option that ONLY works in LISTING will have the same type of restriction documented. And, as I pointed out, the "workarounds" have been known and published for a long time. When you use SKIP, for an ODS destination, should PROC REPORT insert an automatic COMPUTE block into your code? I don't think so. And here's my opinion why not: There are a LOT of "older" PROC REPORT options that only work in LISTING. The fix for skip is straightforward, but is about the only workaround that is simple and would work in any destination. All the other workarounds for LISTING only options are either more complicated or don't work in all destinations. I think of it in terms of my mom's advice: If you don't have enough candy for everybody, don't bring candy to the party. Meaning that if PROC REPORT fixes for LISTING options are like the candy, and if there isn't a straightforward fix for every option, it's better, in the long run, to show the fixes and let folks use them as needed.

About where you would see TEXTDECORATION:  

TEXTDECORATION is a style attribute and appears in the documentation under the topic "Detailed Information for All Style Attributes" (9.3) or "Style Attributes and their Values" (9.2),

http://support.sas.com/documentation/cdl/en/odsug/62755/HTML/default/viewer.htm#n19a4b40swc766n18qcz... (9.3 doc)

TEXTDECORATION is not used, by default, in a style template, so you would only have found it in the documentation (as noted above), displaying the style template code would not have told you anything about TEXTDECORATION.

    

In the topic, you will see the list of all the STYLE ATTRIBUTES that are available for usage for tables that you create with SAS. Usually, you use these STYLE ATTRIBUTES in one of two ways:

1) inside a STYLE= override for PRINT, REPORT or TABULATE (such as I show with PROC REPORT in the previous example or the one below)

or

2) inside a STYLE template (such as described in my paper on using STYLE templates: http://support.sas.com/resources/papers/proceedings10/033-2010.pdf ) Inside a style template, a list of style attributes "belongs" to a style element (a style element is a piece of a report -- like SystemTitle or Header or Data cells or SystemFooter). This scheme -- where a style template is a collection of style element definitions and a style element definition is a collection of style attribute definitions-- is very elegant (in my opinion). It allows the SystemTitle to have one font and fontweight and fontsize that is different from the Header cell font, fontweight and fontsize and is also different from the Data cell font, fontweight and fontsize and is different from the By line font, fontweight and fontsize, etc, etc.

         

  In my earlier post, I explained about the JOURNAL style when I said:

"When I use the code below with TEXTDECORATION to do the OVERLINE, I had to also use the JOURNAL style to remove the interior table lines, so the OVERLINE would be visible."

                              

Anyway, I did not say or mean to imply that you had to use JOURNAL style as your base style. I said that I used it to show you the appearance of the TEXTDECORATION lines. If I had coded the example using the default PDF style, then the interior table lines that normally are used for PDF report tables would have looked weird with the OVERLINE (again, in my opinion). But, in all honesty, I wouldn't use TEXTDECORATION=OVERLINE to make the summary lines distinctive; my usual method to highlight the summary lines (from BREAK and RBREAK) is to make them the same style as the HEADER cells (shown below).

   

PROC TEMPLATE can access many different types of templates. To see what is inside various item stores or template stores, you need to use more precise syntax to see the entire list of STYLE definitions that are available to you. In this paper: http://support.sas.com/resources/papers/proceedings09/227-2009.pdf on page 2 look at the code for Example 2. To see the JOURNAL style existed, you would have had to use LIST STYLES; in your PROC TEMPLATE code. However, unless you are up for reading PROC TEMPLATE code, you can use the STYLE=JOURNAL option in your ODS invocation in order to see the actual output that is created. Doing a simple LIST with PROC TEMPLATE will not reveal the full code for a style template definition. You would have had to use a SOURCE statement in PROC TEMPLATE to see all the possible style attributes that were used in a template.

Alternately, since you are using EG, you could also review the overall "look and feel" of a SAS pre-defined style template by opening the EG Style Wizard, where you could browse a "local" copy (CSS version) of the most common styles. Normally JOURNAL style is one of the styles that folks use when they want mostly border and line-free black and white output that looks like the kind of tables published in journals.

 

  Back to EG -- there are some ODS basics that EG protects you from needing to know about. For example, EG automatically inserts ODS statements around any SAS code that is generated by your project. And, yes, by default, when you look at a library in EG, only data sets are shown to you. This is part of EG's basic design and underlying assumptions that folks using EG largely did not want to worry about the "details" of submitting a job or seeing any of the SAS catalogs or item stores that were needed or any of the ancillary code that was needed to submit a job in batch. When you look at the SAS log for your project or task, you should see quite a bit "added" code -- that is what EG does automatically for you. But batch syntax for PROC TEMPLATE or PROC CATALOG should still work for you to reveal the SAS files that are not data sets in your libraries.

   

In this paper, called The Greatest Hits: ODS Essentials Every User Should Know,
http://support.sas.com/resources/papers/proceedings11/300-2011.pdf I cover some of the basics of ODS "essentials" and "hit #8" starting on page 21 is the one all about styles (ALL about styles).

If you want to watch a movie of the paper presentation, there is an SGF "Take-out" video on Brainshark, you can find the video here: http://my.brainshark.com/ODS-Greatest-Hits-158359784 and the first 6 minutes are ODS "intro" basics and then the "greatest hits" start at about slide 8 (since the audio is attached to each slide).

  

ODS is not point and click. Using ODS and specifying ODS options or a custom style or changing a style or specifying a style override -- all of those changes are largely code-based changes, except for the few things you can select in the EG options.

 

Perhaps the days of programmers writing programs using a particular syntax are over and now we have analysts pointing and clicking their way to analytic reports without ever seeing code. But for results that go "beyond" the defaults, I have always needed to know how to write or modify SAS programs. The way you apply a style to an HTML table is different from the way you apply style to an RTF table or a PDF table or a LaTeX table -- so there has to be one way in SAS to have an impact on such varying types of output -- style templates or style definitions is that way that happens. I'm glad I don't have to know the ins and outs of RTF or PDF or HTML in order to produce output with ODS -- I just have to learn how ODS works and then my output is created appropriately for whichever destination I want. (And some things work in one destination, but may not work the same way in another. This is not because SAS is being nasty or persnickety, but because of the fundamental nature of the different destinations. LISTING is not RTF. RTF is not HTML. HTML is not LISTING. PDF is not HTML. HTML is not PDF. PDF is not LISTING. etc, etc.)

From my standpoint, having coded in Fortran, COBOL, a little PL1, Basic and a few other languages, I think SAS is much more simplfied as a language (in my opinion). It's not object-oriented, like Java or C++ (although if you like object-oriented, SAS has that too). I guess it depends on where you started. From where I started, SAS seems simple and Java and C++ seem arcane and like magic to me.

 

I don't know what customizations you need to do to the PDF TOC -- a LOT can be done with ODS PROCLABEL and with the CONTENTS= option without needing ODS DOCUMENT at all. But, if you need to either replay or rearrange items in the TOC, then ODS DOCUMENT is appropriate. I've put an example of using ODS PROCLABEL and CONTENTS= below.

Anyway, one of my PROC REPORT steps has 2 nodes, the top-level node in the TOC and then just 1 subordinate node. Those lower level nodes were controlled with CONTENTS= options. The second PROC REPORT step just shows the top-level node being used. There are no lower level nodes for the second PROC REPORT. I don't know what you want to achieve. If your requirement only involves renaming or removing nodes, you might not need ODS DOCUMENT. If your requirement is to add nodes or rearrange the output objects, then you probably will need ODS DOCUMENT.

cynthia

options nodate nonumber center orientation=portrait;

    

ods listing close;

title; footnote;

    

data shoes;

  set sashelp.shoes;

  where region in ('Asia', 'Pacific');

  ** need "fake" brkvar to change TOC node to something;

  ** other than "Table 1" in PDF TOC;

  brkvar = 1;

run;

     

ods document name=work.shoes(write);

ods pdf file='c:\temp\proclabel_contents_techniques.pdf';

ODS PROCLABEL='Product Summary by Region';

  

** this proc report shows how to name the proc report;

** node something other than "Table 1";

proc report data=shoes nowd contents='';  /* quote-quote no space in between */

  column  brkvar region product ('Totals' sales inventory returns);

  define brkvar / group noprint;

  define region / group;

  define product / group ;

  define sales / 'Sales' sum format=comma12. ;

  define inventory / 'Inventory' sum format=comma12. ;

  define returns / 'Returns' sum format=comma12. ;

  break after region / summarize style=Header{font_size=14pt};

  break before brkvar/ contents="Totals" page;  /* using brkvar to put string into TOC */

  compute after region / style={background=white foreground=white};

    line ' ';

  endcomp;

  rbreak after /summarize style=Header{color=purple font_size=14pt};

  compute after;

    region='Grand Total';

  endcomp;

run;

 

ODS PROCLABEL='Product Averages by Region';

  

** this PROC REPORT suppresses all the TOC nodes created;

** by PROC REPORT and only keeps the PROCLABEL string in the TOC;

proc report data=shoes nowd contents='';

  column brkvar region product ('Averages' sales inventory returns);

  define brkvar / group noprint;

  define region / group;

  define product / group ;

  define sales / 'Sales' mean format=comma12. ;

  define inventory / 'Inventory' mean format=comma12. ;

  define returns / 'Returns' mean format=comma12. ;

  break after region / summarize style=Header{font_size=14pt};

  break before brkvar/ contents="" page; /* using quote-quote to suppress lower level node */

  compute after region / style={background=white foreground=white};

    line ' ';

  endcomp;

  rbreak after /summarize style=Header{color=purple font_size=14pt};

  compute after;

    region='Grand Total';

  endcomp;

run;

  

ods _all_ close;

ods document close;

** now replay the document;

** but if the above PDF is OK, may not need this step;

ods listing;

ods pdf file='c:\temp\replay_shoes.pdf';

proc document name=work.shoes;

  replay;

run;

quit;

ods pdf close;

ods listing;

Occasional Contributor
Posts: 9

Re: Struggling with Styles

Wow Cynthia,

I did not expect a full essay.

Thank you.

It will take me a while to go through all that.

I had worked with someone from Tech Support a number of months ago with dealing with PDF TOC's.

He pointed me to a white paper he had authored on the subject, and it proved very helpful.

Yes, I needed to rearrange the TOC to have a specific tree structure.

Personally, I took my first programming class in 1977 -- PL/C.

I have been programming since, also in a large number of languages, from machine code and up.

I am Certified in SAS and told your C?O a number of years back that "SAS is the greatest data processing system on the planet".

I still feel that way, in general.

But, there are frustrating parts to it, as there are to everything else, and I think there have been periods in SAS's history where some management type person did not do it justice in documentation and development control.  But, that's my opinion.

Hope you had a good Memorial Day weekend.

You are a real asset to SAS.


Ask a Question
Discussion stats
  • 5 replies
  • 408 views
  • 6 likes
  • 3 in conversation