BookmarkSubscribeRSS Feed
deleted_user
Not applicable
Hi everyone,
I want to know how to insert a 'charecter string' at a particular observation in PROC REPORT.

Thanks and regards.
V.Siva rami reddy.
12 REPLIES 12
Cynthia_sas
SAS Super FREQ
Hi:
PROC REPORT does not change your input data set or your input observations. PROC REPORT writes report rows based on the input data set and the type of usage you define for particular variables (DISPLAY, ORDER or GROUP). So, if you want to insert a character string into your report rows (using PROC REPORT), your choices are:
1) Insert text strings at the top or bottom of the report rows; or insert text strings at a break before of after a group of variables;
2) Compute a new variable for only certain report rows;
3) "Flag" a particular variable based on its observation position or on some other conditional criteria (in a compute block);
4) Change the value of a variable in a compute block.

If you need to alter an observation in a data set, then you should use a DATA step program to do that kind of data manipulation. If you need to insert text strings into report rows, then perhaps you can use SASHELP.CLASS to illustrate the kind of report you need to produce and where you would want the character string to be inserted.

For example, SASHELP.CLASS has 19 observations:
[pre]

Name Age Height
Alfred 14 69
Alice 13 56.5
Barbara 13 65.3
Carol 14 62.8
Henry 14 63.5
James 12 57.3
Jane 12 59.8
Janet 15 62.5
Jeffrey 13 62.5
John 12 59
Joyce 11 51.3
Judy 14 64.3
Louise 12 56.3
Mary 15 66.5
Philip 16 72
Robert 12 64.8
Ronald 15 67
Thomas 11 57.5
William 15 66.5
[/pre]

What kind of Text string would you want to insert into the above detail report? Using PROC REPORT Compute blocks, I could add '***' to the name on report row 5. So you'd see Henry*** or I could insert a line of text after the last observation for William that said "This is the end".

There are other ways to change the report. It is hard to show you any code without an idea of what you want to do.
cynthia
deleted_user
Not applicable
Hi Cynthia,
for example, i want to insert a string 'An American' before 'Jane' and a string 'An Indian' before 'John' .Now i think it is clear to you to solve my task.


Thanks
Cynthia_sas
SAS Super FREQ
Are those text strings coming from another variable in the row, or are they completely arbitrary???? When you modify or add text to a variable value on a PROC REPORT row, you are bound by the size of the original variable. So, for example, the NAME field in SASHELP.CLASS has a length of 8 --- so you could not add the string "An American" before 'Jane' because of this rule.

However, you can compute a new report item in the PROC REPORT row that used the name and my text string.

In this output example, there are 2 report items: ITEM1 and ITEM2. ITEM2 concatenates the value for SEX to the value for NAME on every row. On the other hand, for ITEM1, only the desired text strings have been put next to the desired names.
[pre]
Inserting Text

S
e
Name x item1 item2 Age Height
Alfred M Alfred M Alfred 14 69
Alice F Alice F Alice 13 56.5
Barbara F Barbara F Barbara 13 65.3
Carol F Carol F Carol 14 62.8
Henry M Henry M Henry 14 63.5
James M James M James 12 57.3
Jane F An American: Jane F Jane 12 59.8
Janet F Janet F Janet 15 62.5
Jeffrey M Jeffrey M Jeffrey 13 62.5
John M An Indian: John M John 12 59
Joyce F Joyce F Joyce 11 51.3
Judy F Judy F Judy 14 64.3
Louise F Louise F Louise 12 56.3
Mary F Mary F Mary 15 66.5
Philip M Philip M Philip 16 72
Robert M Robert M Robert 12 64.8
Ronald M Ronald M Ronald 15 67
Thomas M Thomas M Thomas 11 57.5
William M William M William 15 66.5

[/pre]

For ITEM1, the compute block was:
[pre]
compute item1 / character length=20;
if name='Jane' then
item1 = catx(' ','An American:',name);
else if name = 'John' then
item1 = catx(' ','An Indian:',name);
else
item1 = name;
endcomp;
[/pre]

And, for ITEM2, the compute block was much simpler (although an IF statement could have been used in the compute block for item 2:
[pre]
compute item2 / character length=20;
item2 = catx(' ',sex,name);
endcomp;
[/pre]

The column statement shows ITEM1 and ITEM2 after NAME and SEX: [pre] column name sex item1 item2 age height ; [/pre] Of course, once you figure out which method is better for your report, then you can adjust the COLUMN statement accordingly.

I did NOT use NOPRINT with NAME or SEX for this PROC REPORT step because I wanted to show how they were used in the creation of ITEM1 and ITEM2.

cynthia
JimLoughlin
Quartz | Level 8
Cynthia,

I tried your suggestion with the following code:

proc report nowindows data=sashelp.class;
columns name sex item1 item2 age height weight;
compute item1 / character length=20;
if name='Jane' then
item1 = catx(' ','An American:',name);
else if name = 'John' then
item1 = catx(' ','An Indian:',name);
else
item1 = name;
endcomp;
compute item2 / character length=20;
item2 = catx(' ',sex,name);
endcomp;
run;

When I ran it (with SAS v9.1.3 SP4 under WinXpPro SP2), item1 was blanked out when name equaled Jane or John and the following note appeared in the log:

WARNING: In a call to the CATX function, the buffer allocated for the result was not long enough to contain the
concatenation of all the arguments. The correct result would contain 17 characters, but the actual result
may either be truncated to 9 character(s) or be completely blank, depending on the calling environment.
The following note indicates the left-most argument that caused truncation.
NOTE: Argument 2 to function CATX at line 1 column 30 is invalid.

Increasing length to 30 didn't help.

Any ideas on how to get CATX to work in proc report? The if/else-if statements within the compute block code for item1 worked just fine in a datastep.

Thanks.

Jim
Cynthia_sas
SAS Super FREQ
Hi Jim,
That is so totally weird. Here's my log. I didn't have that problem (as you can see) and I am running SAS 9.1.3, SP4 on an XP Pro box with Service Pack 2:
[pre]
80 ods listing;
81 proc report data=sashelp.class nowd;
82 title 'Inserting Text';
83 column name sex item1 item2 age height ;
84 define name / display;
85 define sex / display;
86 define item1 / computed;
87 define item2 / computed;
88 define age / display;
89 define height /display;
90
91 compute item1 / character length=20;
92 if name='Jane' then
93 item1 = catx(' ','An American:',name);
94 else if name = 'John' then
95 item1 = catx(' ','An Indian:',name);
96 else
97 item1 = name;
98 endcomp;
99 compute item2 / character length=20;
100 item2 = catx(' ',sex,name);
101 endcomp;
102
103 run;

NOTE: There were 19 observations read from the data set SASHELP.CLASS.
NOTE: PROCEDURE REPORT used (Total process time):
real time 1.04 seconds
cpu time 0.04 seconds
[/pre]

I suppose you could always fall back on the concatenate operator, as shown in Example 1 in this note: http://support.sas.com/kb/24/514.html. But... I don't think it's CATX that's the issue.

It troubles me that you're getting that warning message. I can duplicate the warning if I take out the DEFINE statements for ITEM1 and ITEM2. However, I don't recommend taking out the DEFINE statements for ITEM1 and ITEM2.

I would never write a COMPUTE block for a COMPUTED variable and NOT have the DEFINE statements because the DEFINE statment links the computed report item with the compute block. In the absence of a DEFINE statement for ITEM1 and ITEM2, PROC REPORT probably expects that those report items are coming from the dataset and will assign them a default usage of DISPLAY, which they're not -- not DISPLAY, and not in the dataset. And not having a DEFINE statement with COMPUTED usage also seems to confuse PROC REPORT when it is setting up the buffer area for the report row.

Did you leave out the DEFINE statements for ITEM1 and ITEM2 on purpose or did you just snip them from your posting???

[pre]
define item1 / computed;
define item2 / computed;
[/pre]
If you left them out, then put them back in and see if the warning goes away. If you have them in the code and just didn't show them, then I think perhaps you need to contact Tech Support.

cynthia
JimLoughlin
Quartz | Level 8
Cynthia,

Putting the define statements in fixed the CATX issue. Normally, I use define statements for all variables but was trying to keep the example simple and thereby unwittingly caused the problem.

Thanks again for your help.

Jim
Cynthia_sas
SAS Super FREQ
Hi Jim,
Glad that solved the problem. I probably should have posted the complete code. But I hoped that, having posted all 19 lines of the output, it would be OK to only post the COMPUTE blocks. My thinking was that someone who knew PROC REPORT would be able to construct the program that went with the COMPUTE blocks.

Keeping it simple only goes so far with PROC REPORT. Once you've signed up to the COMPUTE block, then you've also signed up for the DEFINE statement, too.

cynthia
deleted_user
Not applicable
Hi cynthia,
thanks for reply and i don't want to place 'An american' before the 'Jane' i want to place 'An american' above the 'Jane' as shown below.

James
An American
Jane
Janett

unlike An american:Jane and 'An american' is a arbitrary.
Cynthia_sas
SAS Super FREQ
Hi:
I misunderstood how you used the word "before". When you said

"for example, i want to insert a string 'An American' before 'Jane' and a string 'An Indian' before 'John' ."

...in your posting, you meant "above/before" and not "next to/before"??

It sounds like you want to stack the text string with the values in the cell. That means putting a LINE FEED character into the string. Not all destinations support the recognition of a LINE FEED character. The mechanism for inserting a Line Feed or Line Break character is supported in ODS HTML, PDF and RTF -- but NOT in the LISTING destination. You'll have to run the code in order to see the ODS results.

The ODS ESCAPECHAR statement
[pre]
ODS ESCAPECHAR='#';
[/pre]
defines a special character that can precede certain functions or instructions in order to change the report appearance in ODS destinations. For example, ESCAPECHAR + n is the LINE FEED or Carriage Return control string. ESCAPECHAR + S={attribute=value} is the STYLE override syntax. If the ESCAPECHAR is set to # (as shown above) then #n is the string for inserting a LINE FEED that is recognized by HTML, RTF and PDF. And, #S={foreground=yellow} will be the STYLE override to change the foreground color of the word "Computed" to yellow.

Remember that ODS ESCAPECHAR and the STYLE syntax or the Line Feed syntax are NOT supported in the LISTING destination.

cynthia
[pre]
ods listing;
ods html file='c:\temp\linefeed.html' style=sasweb;
ods pdf file='c:\temp\linefeed.pdf';
ods rtf file='c:\temp\linefeed.rtf';

ods escapechar='#';

proc report data=sashelp.class nowd;
title 'Inserting Text and Changing Style';
column name sex
('#S={foreground=yellow}Computed'item1 item2)
age height ;
define name / display;
define sex / display;
define item1 / computed;
define item2 / computed;
define age / display;
define height /display;

compute item1 / character length=20;
if name='Jane' then
item1 = catx(' ','An American:#n',name);
else if name = 'John' then
item1 = catx(' ','An Indian:#n',name);
else
item1 = name;
endcomp;
compute item2 / character length=20;
item2 = catx(' ',sex,'#n',name);
endcomp;
run;
ods _all_ close;

[/pre]
deleted_user
Not applicable
Hi Cynthia,
After executing the code that you provided,it puts 'An American' and 'Jane' in the same observation but i want them in separate observations and also one skip after the observation that contains the vaue 'An American'.Can you please help me to solve this task.

Thanks.
Cynthia_sas
SAS Super FREQ
Hi:
I have not explained PROC REPORT very well. Proc Report is not creating "observations" it is writing report rows based on observations. The documentation contains a topic called "How PROC REPORT Builds a Report" which outlines this process step-by-step. It is a very useful explanation.

The report rows for a detail report do show you ALL the observations, but, PROC REPORT can only display the observations that are in the DATA= data set. PROC REPORT can "insert" extra/blank lines into the report -- but only at specific places, called break points (as described above in my first post). The break points where you can insert extra or blank lines are:
1) at the top of the whole report or page for some destinations (COMPUTE BEFORE/COMPUTE BEFORE _PAGE_)
2) at the bottom of the whole report or page for some destinations (COMPUTE AFTER/COMPUTE AFTER _PAGE_)
3) at the top of a group of observations or at the top of a summary for a group of observations (COMPUTE BEFORE brkvar)
4) at the bottom of a group of observations or at the bottom of a summary for a group of observations (COMPUTE AFTER brkvar)

In a detail report, on SASHELP.CLASS, the report row with "Jane" is NOT at a break point on the report, so there's no way to insert a line with text or a blank line into the report rows being built, using PROC REPORT. What I showed you -- putting the string "An American" into the same report cell on the report row with "Jane" is what you can do with PROC REPORT. (I've put a program at the bottom that illustrates exactly where you can insert lines into the report rows using PROC REPORT.)

I'm still not sure I understand -exactly- what you want or why the insertion of arbitrary text is needed, but I think you have 2 choices --
1) Insert "new" observations into the data, you would would have to manipulate the data with a DATA STEP program and then pass the changed data to a report procedure (like PRINT or REPORT).
2) Or, you could take control of report writing and use a DATA step program to write out report rows based on the observations in the input data set and the conditional logic you use in the program.

At this point, we've gone back and forth several times and seem to be no closer to a solution for you. Perhaps the answer is PROC REPORT, perhaps the answer is data manipulation and inserting observations, perhaps the answer is a DATA _NULL_ report -- I think your best bet for help is to contact Tech Support. They can look at your data and your requirements and help you come up with the best solution.

To send a question to Tech Support, go to http://support.sas.com/ and in the left-hand navigation pane, click on the link entitled "Submit a Problem".

cynthia
[pre]
ods listing;
ods html file='c:\temp\shoes.html' style=sasweb;

proc report data=sashelp.shoes nowd;
column region product sales note;
where region in ('Asia', 'Canada');
define region /group;
define product / group;
define sales / sum;
define note /computed 'Manager Note';
break after region / summarize;
rbreak after / summarize;
compute note / character length=25;
if sales.sum lt 10000 then
note = 'Discontinue Item???';
endcomp;
compute before _page_;
line 'COMPUTE BEFORE _PAGE_';
endcomp;
compute before;
line 'COMPUTE BEFORE';
endcomp;
compute before region;
line 'COMPUTE BEFORE REGION';
endcomp;
compute after region;
region = 'SubTotal';
line 'COMPUTE AFTER REGION';
endcomp;
compute after;
region = 'Total';
line 'COMPUTE AFTER';
endcomp;
compute after _page_;
line 'COMPUTE AFTER _PAGE_';
endcomp;
run;
ods html close;
[/pre]
deleted_user
Not applicable
Hi cynthia,
In data manipulation i am getting my desired result,i posted the forum just to know whether it is possible by using PROC REPORT ot not.From your reply i came to know that it is not possible by PROC REPORT .

Thank you very much for your kind respose.

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