BookmarkSubscribeRSS Feed
deleted_user
Not applicable
I am trying to nest multiple bookmarks within a large PDF document.

Currently I am using:

ODS PROCLABEL="1"
...
proc gplot data=dataIN gout= graphOUT;
...plot Y*X ... description="1.1";

which allows me two levels of bookmarks. However I would prefer 4 or 5 levels. Is there any way to nest the bookmarks this way in SAS?

Thanks,
Johnny
9 REPLIES 9
Bill
Quartz | Level 8
I haven't tried this, but if the description="1.1", were an incrementing macro variable (e.g. description="&level" )inside of a macro pgm section would it not create the additional levels for you?
Cynthia_sas
SAS Super FREQ
Hi:
If you review these previous forum postings
http://support.sas.com/forums/thread.jspa?messageID=9982⛾
http://support.sas.com/forums/thread.jspa?messageID=3423ൟ

you'll see some examples of ODS DOCUMENT which will allow you extensive control over folders/TOC links that get generated for you. Even though one of the examples illustrates the use of ODS DOCUMENT being replayed to ODS RTF, the same program can also work with ODS PDF or ODS HTML. The important thing is to learn about how to use an ODS DOCUMENT store first.

The web site about ODS Document is here:
http://support.sas.com/rnd/base/ods/odsdocument/

cynthia

cynthia
deleted_user
Not applicable
Bill, Thank you for your advice. I'm familiar with symbolic references...in fact that is how I am indexing my bookmarks/TOC currently.

Cynthia, So I've struggled to interpret the ODS Document examples most of the day and I'm not sure if it solves my problem, or I guess in my mind it is not seem to be the most direct way. Below is the simplified version of what I'm working on. The commented section shows where I believe the changes would be made. Let me know if you have any recommendations or if ODS Document is my only way out.

data data1;
do i = 1 to 10;
X=i;
Y=i*i;
output;
end;
run;

goptions reset=all;
ods listing close;
ods pdf file="C:/Temp/TestGraphs.pdf";
options orientation=landscape;
goptions rotate=landscape;
ODS PROCLABEL="Level 1";

*Here is where I'd like to insert two additional levels of bookmarks/TOC
I understand the loops and symbolic references, which are all in place
I was just hoping I could use something like Title and Title2...;
*ODS PROCLABEL1="1";
*ODS PROCLABEL2="1.1";
*ODS PROCLABEL3="1.1.1";

proc gplot data=data1;
Title "Title for graph";
Title2 "Subtitle for graph";
axis1 label=(a=90 j=c h=1 "Y axis label");
axis2 color=black label=("X axis label");
plot Y*X /overlay vaxis=axis1 haxis=axis2 description="Ideally Level 4";
run;
quit;
ods pdf close;

Thanks
Johnny
Cynthia_sas
SAS Super FREQ
Johnny:
Sadly, there is only ODS PROCLABEL. It is NOT like the TITLE statement or the FOOTNOTE statement. My interpretation of what you want to to is that you want to ADD levels that may not be automatically created by SAS.

If you look in your SAS Results window, after you run the code below, for example, you would see this folder/icon structure:

+--Print: Top Node PRINT (folder icon)
----------Wombat (PDF icon)
+--Gchart: Top Node GCHART (folder icon)
----------D_Age (PDF icon)

and then you would see this in the PDF Table of Contents:
[pre]
Top Node PRINT................................1
Wombat....................................1
Top Node GCHART...............................2
D_Age.....................................2
[/pre]

what you can touch in the TOC is sort of up to the procedure that you're using. If you want to change PROC PRINT, PROC TABULATE or PROC REPORT, then ODS PROCLABEL changes the TOP NODE and the CONTENTS= option changes the lower level nodes.

[pre]
** the code;

ods listing close;
options nodate nonumber;

ods pdf file='c:\temp\toc.pdf' contents=yes;
ods proclabel 'Top Node PRINT';
proc print data=sashelp.class
contents='Wombat';
title 'PROC PRINT of SASHELP.CLASS';
run;

goptions device=gif;
ods proclabel 'Top Node GCHART';
proc gchart data=sashelp.class;
title 'PROC GCHART of Age in SASHELP.CLASS';
vbar age / discrete
name='N_Age'
des='D_Age';
run;
quit;
ods pdf close;
[/pre]

Every procedure sort of "knows" how to build the nodes and the TOC. As I said, you can touch/change them sometimes, but without using ODS DOCUMENT, you can't insert nodes/levels into the TOC.

If you added another vbar statement to your proc gchart:
[pre]
proc gchart data=sashelp.class;
title 'PROC GCHART of Age in SASHELP.CLASS';
vbar age / discrete
name='N_Age'
des='D_Age';
vbar height / name='N_Ht'
des='D_Ht';
run;
quit;
ods pdf close;
[/pre]

Then your PDF TOC would look like this:
[pre]
Top Node PRINT................................1
Wombat....................................1
Top Node GCHART...............................2
D_Age.....................................2
D_Ht......................................2
[/pre]

So if you wanted to change D_Age to 1.1 and D_Ht to 1.2, that is do-able...by just changing DES=. If, however, you wanted to insert an arbitrary level 1.a between the Top Node and the first output object for D_Age -- then your only alternative is ODS DOCUMENT.

If you are generating multiple graphs and using SAS macro variables for the value of DES=, then your DES= value would be something like: DES="&mylev" -- as long as you make sure that &MYLEV has a value -- there used to be a Tech Support note about how it didn't work to use DES=" " -- which is what would happen if your macro variable didn't resolve correctly. You might want to check with Tech Support for sure on this point. Also remember that every new invocation of SAS/Graph will get a new Top Node that can be changed with ODS PROCLABEL.

It's still not clear to me whether you want to relabel the TOC nodes created by SAS procedures (in which case, you probably don't need ODS document) or if you want to insert arbitrary nodes not created by SAS procedures.

At this point, Tech Support might be your best bet for help.

cynthia
deleted_user
Not applicable
To answer your final question; your interpretation was correct I am trying to insert arbitrary nodes that are not created by the SAS procedure. And as you said it looks like my only option is ODS Document.

http://support.sas.com/forums/thread.jspa?messageID=9982⛾

In your code used in the link above I was unable to get it to work as expected, or interpret it correctly. Would you be able to provide an example that adds a bookmark using ODS Document, rather than removing the TOC?

Thanks as always,
Johnny
Cynthia_sas
SAS Super FREQ
Johnny:
Every bookmark in a PDF TOC is either a SAS folder or a SAS output object. That's the point of my previous posting. When you run a job, look in the SAS results window and compare what you see in the results window to the PDF TOC.

OK...now that you understand that every folder is going to become a bookmark and that every procedure you run will probably have a top folder and at least 1 output object, then your issue is how to insert more "levels" into the TOC structure.

That means in your new ODS document, you'd have to insert more "folders" into the ODS document. The MAKE command is like the MD or the makedir command-- it adds a folder into the ODS Document structure. Then when you replay the ODS Document, that folder becomes a level in the TOC.

When I make an ODS Document -- I like to keep the original ODS Document intact, the way ODS created it. That way, should it be necessary, I could prove to anyone that all I did was rearrange the structure -- not delete anything. (What can I say, in a previous life I worked for lawyers.)

So in my code, I have this scenario:

1) Create ODS Document from SAS Procedures -- sometimes, if I want to compare the "original" ODS result file to the replayed result file, I will also have an ODS HTML or ODS RTF step around #1. The objects and folders have funny names and you have to know these names in order to do the copying you want to do. That's the point of a PROC DOCUMENT step with the LIST statement. It reveals the internal names of the output objects and folders.

2) Make new ODS document with desired folder structure (have to use PROC DOCUMENT "batch" mode commands to do this -- like MAKE and COPY and DIR)

3) Copy objects and/or folders from #1 into #2 (DIR navigates through the ODS DOCUMENT to the folder you want, then COPY copies the objects)

4) Double check that #2 looks the way I want (I generally check this with the Document Window -- but a PROC DOCUMENT List works too) and then

5) Replay the ODS Document from #2 to whatever destination I want.

So that's how you interpret the code in the previous forum posting. If you are running SAS 9.1.3 SP4, then that code should work for you as long as you don't change it. If the code does NOT work for you, unchanged, then there's no point in going further until you can work with Tech Support to figure out why it's not working. (The only thing I can think of for why it doesn't work is that you are running SAS 8.2 or you're using EG and something in EG is interfering with ODS DOCUMENT.)

Here's a simple ODS DOCUMENT program to try. It has a BUNCH of arbitrary folder levels. I used PROC MEANS for the output object to copy into the new structure. I just copied the same output object into 3 different places.

When you run a procedure, it creates output objects. Your new document needs to have some output objects in it. You can't replay an ODS DOCUMENT that just has folders, but no output objects. This program follows the same general scenario as the 5 steps above.

To get the hang of ODS DOCUMENT, it is much easier to create an ODS DOCUMENT store to play around with and then pop open the ODS DOCUMENT window. Once you have a feel for making a new document store and making folders and copying/rearranging the objects and folders in the new document store, you'll have a much better understanding of what the batch syntax is doing.

To open the ODS DOCUMENT window in SAS 9.1.3, type odsdoc or odsdocument in the SAS command line. If you are running SAS 8.2, the ODS DOCUMENT window was not cooked yet, so it wasn't really available; although most of the batch syntax worked. Tech Support would have to help you with ODS DOCUMENT code that would run in SAS 8.2.

To find out more information on ODS DOCUMENT and read about the general concepts, search on the string:
"The DOCUMENT Procedure" (quotes included) in the SAS Help facility or online doc.

There are some things (graph device, graph catalog) to keep in mind when working with SAS/Graph and ODS Documents and the documentation contains a lot of good information on these topics. As you can see, the code syntax is lengthy and dense -- so if you need help with SAS/Graph and ODS Document, your best bet for help is to contact Tech Support.

cynthia
[pre]
title;
footnote;
options nodate nonumber center orientation=portrait;
ods noptitle;

**1) Make an ODS Document to start with;
ods document name=work.shoedoc(write);
proc means data=sashelp.shoes sum min mean median max;
var Sales;
run;
ods document close;

proc document name=work.shoedoc;
list / levels=all;
run;
quit;

** 2) make the new structure AND;
** 3) copy the same output object to 3 different places in the folder structure.;
proc document name=work.one_obj(write);
make F1, Wombat, Koala;
run;
dir;
run;
dir F1;
make FF1;
run;
dir FF1;
make FF2;
run;

dir FF2;
make FF3;
dir FF3;
copy \Work.shoedoc\Means#1\Summary#1 to ^;

run;
dir \Work.one_obj\;
run;

dir Wombat;
make newfolder;
dir newfolder;
copy \Work.shoedoc\Means#1\Summary#1 to ^;
run;

dir \Work.one_obj\Koala#1;
copy \Work.shoedoc\Means#1\Summary#1 to ^;
run;


setlabel \F1#1 "1.0";
setlabel \F1#1\FF1#1 "1.1";
setlabel \F1#1\FF1#1\FF2#1 "1.1.1" ;
setlabel \F1#1\FF1#1\FF2#1\FF3#1 "1.1.1.1";
setlabel \Wombat#1 "2.0" ;
setlabel \Wombat#1\newfolder#1 "2.1" ;
setlabel \Koala#1 "3.0";
obtitle1 \F1#1\FF1#1\FF2#1\FF3#1\Summary#1 "First display for this object";
obtitle1 \Wombat#1\newfolder#1\Summary#1 "Second display of Output Object from PROC MEANS";
obtitle1 \Koala#1\Summary#1 "Third display of MEANS object";

run;
quit;

** 4) Double check the levels in the new document store;
proc document name=work.one_obj;
list / levels=all;
run;
quit;

** 5) now replay the new document store to PDF with the contents= option;
ods pdf file='c:\temp\newtoc.pdf' contents=yes;
proc document name=work.one_obj;
replay;
run;
quit;
ods _all_ close;

ods listing;
[/pre]
Cynthia_sas
SAS Super FREQ
Hi,
Just an update. I found out that CONTENTS=YES does NOT work with ODS PDF when you have SAS/Graph objects that you are replaying. You can still get a PDF bookmark area, but you cannot get the separate TOC page. Also, the ODS ESCAPECHAR controls for Page X of Y do not currently play nice with ODS DOCUMENT and replaying.

Here's an updated version of my sample program with a SAS/Graph example and some arbitrary levels. Thanks for this updated example are due to the wonderful ODS Document person who helped me when I figuring out how to make SAS/Graph work with ODS Document.

cynthia
[pre]
options nodate nonumber orientation=landscape center;

** delete the prior gseg catalog so the graph name;
** always stays the same (GCHART);
proc datasets;
delete gseg;
run;
quit;

** First make a document store from the original procedures;
** This is the document store we will copy FROM.;

ods document name=work.newdoc(write) ;
ods proclabel 'Top Node PRINT';
proc print data=sashelp.class
contents='Wombat';
title 'PROC PRINT of SASHELP.CLASS';
run;

goptions reset=all device=javaimg;
ods proclabel 'Top Node GCHART';
proc gchart data=sashelp.class;
title 'PROC GCHART of Age in SASHELP.CLASS';
vbar age / discrete
des='Age';
run;
quit;
ods document close;

** Next, get a list of the "official" names of the folders and output objects;
** which is needed for the PROC DOCUMENT step.;
proc document name=work.newdoc;
list / levels=all;
run;
quit;

** Now, make a new ODS DOCUMENT and insert some arbitrary folders. ;
** Every folder will become a new indented "level" in the TOC.;
** A DIR command takes you to the "root" directory.;
** A DIR command with a folder name takes you "down" to that folder level.;
** Copy ... to ^ copies FROM the WORK.NEWDOC document store to the folder;
** where you are positioned in the WORK.MORELEVEL document store.;
proc document name=work.morelevel(write);
make F1;
run;
dir;
run;
dir F1;
make FF1;
run;
dir FF1;
make FF2;
dir FF2;
run;

copy \work.newdoc\Print#1\Print#1 to ^;

run;
make FF3;
run;
dir FF3;
copy \work.newdoc\Gchart#1\Gchart#1 to ^;

setlabel \F1 '1.0';
setlabel \F1#1\FF1#1 '1.1 Arbitrary Level';

setlabel \F1#1\FF1#1\FF2#1 '1.1.1 Arbitrary Level';
setlabel \F1#1\FF1#1\FF2#1\Print#1 '1.1.1.2 Print';

setlabel \F1#1\FF1#1\FF2#1\FF3#1 '1.1.2 Arbitrary Level';
setlabel \F1#1\FF1#1\FF2#1\FF3#1\Gchart#1 '1.1.2.1 Chart for Age';

run;
quit;

** Double check the levels in the new document store;
proc document name=work.morelevel;
list / levels=all;
run;
quit;

goptions reset=all device=png;

ods pdf file='c:\temp\newtoc.pdf';
proc document name=work.morelevel;
replay;
run;
quit;
ods _all_ close;

ods listing;

[/pre]
deleted_user
Not applicable
When using the ODS document function I am getting an error

ERROR: Java class generated an exception.

due to the use of the line

goptions device=javaimg;

I've researched this problem and there does not seem to be any real work around since it requires a Java Environment of 1.4 or lower and IT dictates my JRE. Documentation on this error does not say if it is benign or not.

http://support.sas.com/kb/11/863.html

Unfortunately, I get my titles and footers AND the folder structure that i desire but NO data. So the chart in your example generated by the gchart procedure initially outputs the data table but once the ODS document is replayed the data is no longer on the page. Is this a common problem associated with the error I mentioned above or could it be something else? Any input is appreciated.

johnny
Cynthia_sas
SAS Super FREQ
Hi:
The image is only created with the JAVAIMG driver for storing in the ODS DOCUMENT. Perhaps the ACTXIMG driver would work instead of the JAVAIMG driver. Tech Support could tell you for sure. The replay of the ODS DOCUMENT is done with PNG.

If you can't go back to a 1.4 JRE, then your best bet for help is to talk to Tech Support and if they don't know how to get around this with ODS DOCUMENT and different drivers, they will be able to forward your question to the right folks in R&D for comment and/or a workaround.

cynthia

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 9 replies
  • 1692 views
  • 0 likes
  • 3 in conversation