BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Hi,

Ok, I have been banging my head against a wall for too long on what should be a very simple task.  What I want is an output file, of type PDF, with one bookmark - this being for page 1, not other bookmarks.

I have tried half a dozen different methods and none of them seem to work.

So if I try:

ods proclabel="My bookmark";
title "A title";
footnote "A footnote";
ods pdf file="want.pdf";
ods pdf bookmarkgen;
proc sgplot data=sashelp.class;
  scatter x=age y=height;
run;
ods pdf nobookmarkgen;
proc sgplot data=sashelp.class;
  scatter x=age y=weight;
run;
ods pdf close;

This creates the PDF correctly, with titles/footnotes, with my bookmark, but also with the secondary bookmark "The sgplot procedure".  Attempting to description="" to the first proc sgplot removes that text, but still leaves a bookmark there.

 

I have also tried proc document.  However when I run graphs through that, they work fine for RTF destination, titles/footnotes, but in PDF titles/footnotes are not showing (i.e. have RTF and PDF open when replay is called).  I can move the graphs up to the top level, but I still also get bookmarks for each graph, but now no titles or footnotes.

ods document name=tmp(write);
title "A title";
footnote "A footnote";
proc sgplot data=sashelp.class;
  x=age y=height;
run;
proc sgplot data=sashelp.class;
  x=age y=weight;
run;
ods document close;
ods rtf file="myfile.rtf";
ods pdf file="myfile.pdf";
proc document name=tmp;
  replay;
run; quit;
ods rtf close;
ods pdf close;

In the above, the RTF has titles, the PDF has no titles (bad).  The RTF has no bookmarks (good), the PDF has four bookmarks, two for each proc (bad).

For the bookmarks I tried adding:

proc document name=tmp;
  setlabel \SGPlot#2\SGPlot#1 '';
  move \SGPlot#2\SGPlot#1 to SGPlot#1;
  delete \SGPlot#2;
  replay;
run; quit;

However I still get no titles in the PDF, and I have one bookark with two sub bookmarks then.

(Do note, this is an example, there maybe several proc statements, from report and sgplot and GTL, I still only want one bookmark per output file).

 

Why can this process not be simply, as I surely can't be the only person who wants one bookmark per output:

ods pdf file="want.pdf" bookmark="my bookmark";
...
ods pdf close;

Its really frustrating that this seeming simple task looks like it requires third party tools to make effective.

1 ACCEPTED SOLUTION

Accepted Solutions
BrunoMueller
SAS Super FREQ

Give the code below a go. We do need to create some output to get the first bookmark

 

ods pdf file="c:\temp\want.pdf" startpage=no;
ODS PROCLABEL 'ods proc label';

data _null_;
  declare odsout ODS();
  ODS.note(data: " ",  style_attr: 'font_size=1pt');
run;

ods pdf nobookmarkgen;

proc sgplot data=sashelp.class;
  scatter x=age y=height;
run;

ods pdf startpage=yes;

proc sgplot data=sashelp.class;
  scatter x=age y=weight;
run;

ods pdf close;

View solution in original post

4 REPLIES 4
MCoopmans
SAS Employee

Hello, 

 

You can get exactly the result you are looking for using the ODS DOCUMENT destination and PROC DOCUMENT to replay your graphs to the ODS PDF destination.

That approach allows you to get a finer control over several things, such as the PDF bookmarks.

I changed your code a little bit to first generate the graphs into the ODS DOCUMENT:

 

 

ODS html close;
ODS pdf close;

ods document name=graphdocument(write); 
title "A title";
footnote "A footnote";

proc sgplot data=sashelp.class ;
  scatter x=age y=height ;
run;

title "A title - chart 2";
footnote "A footnote - chart 2";
ods proclabel="";
proc sgplot data=sashelp.class ;
  scatter x=age y=weight;
run;
ods document close;

and next replay it :

 

 

ods pdf file = "want.pdf" ;
proc document;
 doc name=graphdocument ;
  copy \SGPlot#1\SGPlot#1 to \temp;
  setlabel \temp "This is graph 1";
  replay \temp;

  copy \SGPlot#2\SGPlot#1 to \temp;
  setlabel \temp "This is graph 2";
  replay \temp;

 quit;
 ODS PDF close;

 

This is what the result looks like:

2020-05-28_174508.png

 

Should you want to learn more about how to find the names of the graphs, you can use this piece of code to get the contents of the document: 

ods output properties=myds;
ods html;
 proc document name=graphdocument;
 list / levels=all;
 run;
 quit;
ods html close;
ods output close; 

You can use that dataset (type ne "Dir") to iterate through all the contents and replay it as you like to completely automate this.

 

Hope this is what you were looking for!

Greetings,

Mathias.

 

 

 

 

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Hi,

 

Thank you for your reponse, however you have misunderstood the question.  The point is that I would like to have one bookmark per file, regardless of what procs are output to it.  You have shown this in the screenshot you post, there is one file called want.pdf, but it has two bookmarks.  I want want.pdf with one bookmark at page 1 only.  There isn't a way in ods document to remove the second bookmark (not the second level bookmark, that is possible).  So another way of explaining, from your pdf output, I only want to see "This is graph 1", even though both graphs output.

 

To put it another way, if you create an rtf file with lots of different proc outputs, report, graphs etc.  Then Create a PDF in Adobe from that file with not further options, you get a file with the same name, but pdf extension, and 1 bookmark as the filename.  It does not matter what the contents of the rtf are, 1 bookmark per 1 file.  Hence why, I would set it up so its on the ods line as int:

ods rtf "somefile.rtf" bookmark="This is the only bookmark I want in the file";
...
ods rtf close;

I don't believe this is a new question, I am sure when I was using 8.2 back in the day, this is why we did not use ods pdf, but it still hasn't changed.

BrunoMueller
SAS Super FREQ

Give the code below a go. We do need to create some output to get the first bookmark

 

ods pdf file="c:\temp\want.pdf" startpage=no;
ODS PROCLABEL 'ods proc label';

data _null_;
  declare odsout ODS();
  ODS.note(data: " ",  style_attr: 'font_size=1pt');
run;

ods pdf nobookmarkgen;

proc sgplot data=sashelp.class;
  scatter x=age y=height;
run;

ods pdf startpage=yes;

proc sgplot data=sashelp.class;
  scatter x=age y=weight;
run;

ods pdf close;
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Hi,

 

Well, I will give you the points, as this code did what was needed.  However the moment I add anything to it then it breaks.  For instance, try adding: ods escapechar="^"; before that, I then get no graph output.  Adding RTF ods around that, i.e. to get the same output to two ods leads to a warning, and empty pdf output. 

 

I will stick with the create an RTF file, then use Adobe to create PDFs from there, it seems to be the only method which reliably works.  I would suggest though that SAS add something like this in as often people want to generate a file with just the one bookmark form compilation into other documents, I mean its Adobe default behaviour so its very strange that it is not available from SAS.

 

Thanks

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 7022 views
  • 2 likes
  • 3 in conversation