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

I am working on generate a PDF file with several listings with TOC. It is several PROC REPORT in one ODS PDF destination. After referenced some papers and searched in the community about managing TOC by ODS Document and proc document. I can get what I needed if the individual listing can be displayed in one page. And the issues come when the individual listing has multiple pages. 

 

The PROC REPORT generated one bookmark with same name specified at CONTENTS="" for each page when BREAK statement used for page break. However, these bookmarks for each page just has one node (such as \Report#1\Report#1\Report#1), which cannot be delete. And I have to let the page break if the row number large than>18. which means, if one listing has 25 rows, then I want there are 2 pages, the first page has 17 rows and has one bookmark, the second page has 8 rows and has no bookmark.

 

http://support.sas.com/kb/31/278.html, the way in the support web cannot help me, above issues come if I have to use two breaks.

 

Is there a way to suppress the unexpected bookmarks in above situation?

 

Thanks a lot for any help !

1 ACCEPTED SOLUTION

Accepted Solutions
Li_Laura
Fluorite | Level 6

Thanks for your suggestion, SAS Tech support provide an way to meet my need. The key is  CONTENTS=' ' in BREAK statement, then the bookmark will only show in the first page after set label and copy the path in PROC DOCUMENT.

View solution in original post

8 REPLIES 8
Cynthia_sas
SAS Super FREQ

Hi:
I'm not sure what you mean by unexpected bookmarks. You referred to some kind of problem with the code to suppress the extra TABLE1 node, but you didn't post any code, any data or any picture of what the issue is.

When you describe "each page" as having a bookmark, I'm not sure I understand what you mean, ODS PDF only makes bookmarks based on the options you specify in CONTENTS=.

PROC REPORT is dealing with "objects", not physical pages, so if you have a group of 25 rows and that is one "object" which gets one "bookmark" then if that object displays on multiple physical pages, you would not get a bookmark for each physical page. For example, in the screenshot below, I have used BY group processing to create a bookmark for every Region in my subset of SASHELP.SHOES. Pacific uses more than 1 page for the report rows. But the link for Second Node, is only designed to take me to the TOP of that group, just as the second node for Canada takes me to the TOP of that group. There is nothing in the way bookmarks function to take me to each page within a group.
bookmarks.png
But you haven't posted anything that really explains what you're getting, and how your getting it or what's wrong with it. Here's some code to test that produced the above screen shot. Note that I did NOT get rid of Third Node, just to illustrate that there are 3 bookmarks possible with PROC REPORT -- note that the BY group processing caused a bookmark too, but the BY group bookmarks are nested underneath the First Node bookmark:

data test; 
   set sashelp.shoes;
   where region in ('Canada', 'Pacific'); 
   count=1; 
run; 

proc sort data=test;
by region product;
run;

ods pdf file="c:\temp\testtoc.pdf"; 
                                                                                                                                        
ods proclabel="First Node";
proc report nowd data=test contents="Second Node"; 
by region;
   column count region product sales; 
   define count / group noprint; 
   break before count / contents="Third Node" page; 
run; 
 
ods _all_ close; 

If, in my example, you would want a bookmark for page 1 of Pacific and a different bookmark to page 2 of Pacific, that is not something that PROC REPORT or ODS PDF would give you by default.

cynthia

Cynthia_sas
SAS Super FREQ

Hi:

  In thinking more about it, I wonder whether you want something like this, where you get a certain number of obs (like 35) per page and you really want a separate bookmark for every internal page in a group??

show_internal_pagecount.png

which was produced with this code:

data test; 
   set newshoes; by region;
   retain pgcntr grpobs;
   count=1; 
   if first.region then do; PageNumber=0; grpobs=0; end;
   grpobs + 1;
   PageNumber = int(divide(grpobs,35))+1;
run; 

proc sort data=test;
by region PageNumber;
run;
title;

ods pdf file="c:\temp\toc_pages.pdf"; 
                                                                                                                                        
ods proclabel="Region report";
proc report nowd data=test contents=""; 
by Region PageNumber;
   column count region product sales; 
   define count / group noprint; 
   break before count / contents="" page; 
run; 
 
ods _all_ close; 

cynthia

Li_Laura
Fluorite | Level 6

Hi Cynthia,

 

Thanks a lot for your reply. I will give you more details and see if there is way to do it.

 

Let me explain my needs in your second example? I don't want the bookmark for PageNumber=2, but I do need the content of PageNumber=2 show in the physical page = 2 and 4 in the PDF.

 

 

bk.PNG

 

When I use BY in the PROC REPORT I will get an NODE for PageNumber=2, but if I remove the NODE, the contents of PageNumber=2 will go. When I use second BREAK (after break before count), there is no NODE for PageNumber=2.

 

My testing code is:

Li_Laura
Fluorite | Level 6
Oh, forget to say when using second BREAK in PROC REPORT, there is an bookmark for the object but no node.
Cynthia_sas
SAS Super FREQ
Hi-- You also forgot to say that you were using PROC DOCUMENT in your first post. However, I still don't understand the structure you want. If you don't want a node for page 2, then the first code I posted seems to do what you want without using PROC DOCUMENT.

I would never code a PROC DOCUMENT the way you are coding it. My approach is always to preserve the original DOCUMENT object that corresponds to my original output. Then I make a new document object and copy the objects I want into the new document store, giving it the bookmark/node structure I want and using the labels I want.

Finally, I replay the new structure to the destination I want. It is the same framework I described in this paper, in detail, with code examples:
https://support.sas.com/resources/papers/sgf09/318-2009.pdf

Unfortunately, I am teaching this week and not in a position to revise your example, however, I think the framework I show in the paper would be a better approach, then your approach to alter the original document store.

When you delete an object from the original document store, you are also deleting the objects that are linked to that object. That's why I feel a better approach is to make your new structure and then copy objects into the new structure.

Cynthia
Li_Laura
Fluorite | Level 6

Hi Cynthia,

 

Really thanks for your input. I agree your way to code PROC DOCUMENT, but this is a simple example, so I just try the simplest code.

 

I have a long listing with more than 100 records, and only want to show 20 records in every physical page, which I think can be done by BY or BREAK in PROC REPORT. And I want only one bookmark shown in the first physical page. Am I explaining my need clear?

 

Your paper is quite detailed, but it hasn't offer an idea how to remove the bookmarks in every physical page after first page but not remove page break.

 

If using BY in PROC REPORT for page break, copy the level-3 path (path of Type=Table) after first physical page is useless, due to the bookmark is still there.

 

If using BREAK in PROC REPORT for page break, copy the level-3 path (only one can see in the path, but bookmarks show in every physical page) to new structure cannot change anything, the bookmarks still show in each physical page.

 

I test in this way:

proc document name=reorder;
list / levels=all;
run;

quit;

proc document;
  doc name=work.neworder(write);
 make report;
 dir \;
 dir report;
 dir;
 copy \work.reorder\Report#1\Report#1 to ^;
 copy \work.reorder\Report#1\Report#1\Report#1 to \work.reorder\Report#1\Report#1;
   ods pdf file="testpdf.pdf";
    replay;
   run;
   ods pdf close;
 run;
quit;
ods _all_ close;

 

Thanks a lot.

Cynthia_sas
SAS Super FREQ

Hi:
  I think that anything you do to force a separate object for every physical page you want (such as only 20 obs per page for each group) is going to cause a separate node for the page -- whether you use BY groups or internal Breaks with PROC REPORT. The challenge is that I don't believe you can have the output without the node/bookmark. So this might be a question you have to ask of Tech Support -- whether ODS DOCUMENT nodes can be constructed in such as way that you can copy the output but suppress the node in the Bookmarks. They can look at all of your data and all of your code and advise you whether what you want can be done with ODS PDF and ODS DOCUMENT.

cynthia

Li_Laura
Fluorite | Level 6

Thanks for your suggestion, SAS Tech support provide an way to meet my need. The key is  CONTENTS=' ' in BREAK statement, then the bookmark will only show in the first page after set label and copy the path in PROC DOCUMENT.

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 8 replies
  • 3646 views
  • 6 likes
  • 2 in conversation