The SAS Output Delivery System and reporting techniques

Selective alignment and 'compute block'

Reply
Regular Contributor
Posts: 214

Selective alignment and 'compute block'

Hi all,

 

I have a question regarding justification within cell in proc report. I am using the following code  - rtf commands for 'decimal' justification:

 

 

proc report data=test
style(column)={asis=on}
style(header)={asis=on} split="*" ;
by pgn;

column A B var1 - var2;

define A / id order order=internal ;
define B / id order order=internal ;

define var1 / " *Group 1" style(column)=[just=c protectspecialchars=off pretext="\qj\tqdec\tx200 "] left; 
define var2 / " *Group 2" style(column)=[just=c protectspecialchars=off pretext="\qj\tqdec\tx200 "] left; 

run;

The text inside cell - 

"\qj\tqdec\tx200 "

helps to align as below:

1.jpg

 

I actually need the following alignment:

2.jpg

Does a "compute block" exist like this one or any other:

compute var1;
      if varB='F' then do;
         call define(_col_,....,....);
      end;
      else do;
         call define (_col_,....,....);
      end;    
endcomp;

to perform seleсtive alignment (depending of values of other variable or even on computed variable).

 

Thank you!

 

 

Super User
Super User
Posts: 9,840

Re: Selective alignment and 'compute block'

Posted in reply to DmytroYermak

I don't do alignment like that.  In your dataset test, I would have all the printable variables as characters, with the correct spacing and alignment, and a few non-printed variables for page break, spacing and orders.  I do this for all my outputs, makes it easier to QC, and a far simpler proc report statement.  Report is not the best tool to be doing data manipulation.  So a data structure like:

page ord1 value

1       1       "  89"

1       2       "    85 (95.5)"

1       3       "      4   (4.5)"

 

Can be achieved in a datastep, and then the proc report is simple.  Personally I tend to simplfy the alignment by putting() the value into a set format which would result in:

1       2       "    85 (95.5)"

1       3       "      4 (  4.5)"

So put(value,5.1) would achieve this, up to you though, you can compress out spaces.

 

Also note, to display the value with the spaces then use:

define value / style={asis=on};

Otherwise it will compress out the leading spaces.

So takeaway is that it is easier to manipulate strings in a datastep before a report than try to work with it in proc report.

 

Regular Contributor
Posts: 214

Re: Selective alignment and 'compute block'

[ Edited ]

I think you are right, but it would be a сatch if simple pretest worked, or something like this. Now I have to calculate all variants of the length of counts-percents ( .

Super User
Posts: 13,941

Re: Selective alignment and 'compute block'

Posted in reply to DmytroYermak

Don't force the percents into the same cell as the count or what ever, have it as a separate value and left align it in its own cell so it is close to the other value. Set the right/left borderwidth to 0 and see how close you can get. Reducing CeLLPADDING may also be a good idea for those adjacent cells.

Regular Contributor
Posts: 214

Re: Selective alignment and 'compute block'

Finally I have done how RW6 recommended. But my question concerned the flexibility of Proc report. It seemed to me that Proc report allows to perform the selective alignment. I would be grateful if an experienced programmer or SAS employee could share her/his experience.
SAS Super FREQ
Posts: 9,433

Re: Selective alignment and 'compute block'

Posted in reply to DmytroYermak

Hi, This approach worked for me to produce this:

align_d_c.png

 

 I did not fiddle much with individual cells alignment other than to switch anything without a '(' to center.

data align;
  length string $15;
  infile datalines dlm=',' dsd;
  input name $ string $;
return;
datalines;
Alan, "89"
Barb,  "85 (95.5)"
Carl,   "4 (4.5)"
Diane, "81 (23.9)"
Ed,"83 (6.7)"
Fran,  "0" 
Gary,"67"
;
run;

ods rtf file='c:\temp\test_align.rtf';
proc report data=align;
  column name string;
  define name / order;
  define string / display 
         style(column)={width=.75in just=d};
  compute string;
    if index(string,'(') = 0 then
	   call define(_col_,'style','style={just=c}');
  endcomp;
run;
ods rtf close;

Cynthia

Regular Contributor
Posts: 214

Re: Selective alignment and 'compute block'

[ Edited ]
Posted in reply to Cynthia_sas

Thank you, Cynthia. It is exactly what I need. I have slightly modified the code and have just a few questions regarding options (it is not working in herein): 

 

1. Is it possible to use condition depending on a variable 'access' that is not printed? Should it be mentioned in 'proc report'.

2. Could you please put a link on useful documentation on 'call define'. What are the options and so on? It seems to me that using of 'compute+rtf language' is much more convenient that any macroses that align by decimal, or draw any lines under values, or hyphen etc.. I can be wrong of course ).

 

data align;
  length string $15;
  infile datalines dlm=',' dsd;
  input name $ string $ access $;
return;
datalines;
Alan, "89", A
Barb,  "85 (95.5)", B
Carl,   "4 (4.5)", B
Diane, "81 (23.9)", B
Ed,"83 (6.7)", B
Fran,  "0", A
Gary,"67", A
;
run;

ods rtf file='C:\temp\test_align.rtf';
ods escapechar = "^";

proc report data=align;
  column name string /*access*/;
  define name / order display 
         style(column)={width=2.00in just=c};
  define string / display 
         style(column)={width=2.00in just=c};
  /*define access / display style(column)={width=2.00in just=d};*/
  compute string;
    if access="B" then
	   call define(_col_,'style',' style=[just=c protectspecialchars=off pretext="\qj\tqdec\tx700 "]');
	endcomp;
run;

ods rtf close;

 

SAS Super FREQ
Posts: 9,433

Re: Selective alignment and 'compute block'

[ Edited ]
Posted in reply to DmytroYermak

Hi: If you want to use CALL DEFINE on the STRING variable, based on the value for the ACCESS Variable, then ACCESS has to appear BEFORE the STRING variable in the COLUMN statement. So, not this:
column name string access ;
but instead, this:
column name access string;

The reason for this is that PROC REPORT works to build the report row working from LEFT to RIGHT. This means if ACCESS is placed to the right side of STRING, then the COMPUTE block will NOT see the value for ACCESS. But if ACCESS is placed to the left side of STRING, then at the point in time when the COMPUTE block is handling STRING, it will know what the value for ACCESS, on the report row is.

I can't speak to whether using RTF control strings is better than other methods. If you are ONLY, ever, ever going to want RTF output, and, you absolutely know exactly the correct RTF control string to specify, then by all means, use PRETEXT and RTF control strings to accomplish what you want.

My only warning about this is
1) if you have any mismatched { or \ in the control string you specify, Word will not be able to open the RTF file;
2) If you ever want to send the output to PDF or HTML or Excel, then you have to use other methods to accomplish the cosmetic change you want because RTF control strings are not recognized by those destinations.

The PROC REPORT documentation is here: http://go.documentation.sas.com/?docsetId=proc&docsetTarget=p0bqogcics9o4xn17yvt2qjbgdpi.htm&docsetV...

You could search on www.lexjansen.com for free papers about PROC REPORT. Some names to look up for papers on PROC REPORT are:
Allison Booth (or Allison McMahill Booth)
Daphne Ewing
Art Carpenter
Jane Eslinger
(and, of course, I have more than a few papers out there too)

For books about PROC REPORT, I can recommend those by Art Carpenter, Jane Eslinger and Lisa Fine. You should find them in the SAS Bookstore: https://support.sas.com/en/books.html .

Cynthia

 

Also, we cover PROC REPORT, along with PROC TABULATE in our Report Writing 1 class: https://support.sas.com/edu/schedules.html?ctry=us&crs=RPT1

Ask a Question
Discussion stats
  • 7 replies
  • 223 views
  • 0 likes
  • 4 in conversation