- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I want to get listing output_1(shown below, the subcat lines should be indented). However when I ran my below code I got output_2 (shown below). I tried to use 'style' to control the output, and 'style' worked for rtf output, but not for listing output. Can someone help me out about how to control indent for listing output? Thanks
output_1 output_2
data x;
format x $100.;
x='cat_A';
output;
x=repeat("Subcat ", 30);
output;
run;
ods listing file="xxx\try_1.lst";
proc report data=x;
column x;
define x / 'HEADER' width=50 flow;
run;
ods listing close;
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Like I said. Write your own wrapping logic.
Here is such a program from years ago. You would need to post-process the output of this to prepend the leading spaces for the indentation.
%macro wrap
/*------------------------------------------------------------------------------
Wrap long string into mulitple observations
------------------------------------------------------------------------------*/
(dsnin= /* Input dataset */
,dsnout= /* Output dataset */
,invar= /* Variable to wrap */
,outvar= /* Name of wrapped variable */
,len=80 /* Length to wrap */
,split='0d'x /* Character(s) to use for forcing new observation */
,break=",- " /* Character(s) used to break long words across lines */
);
/*------------------------------------------------------------------------------
Wrap a long variable into multiple lines. Split characters will cause
the starting of a new line. Break characters will control where words can be
broken to fit into a line.
------------------------------------------------------------------------------*/
%local macro parmerr varlen vartype;
%let macro=WRAP;
%parmv(dsnin,_req=1)
%parmv(dsnout,_req=1)
%parmv(invar,_req=1)
%parmv(outvar,_req=1)
%parmv(len,_val=positive,_req=1)
%let varlen=%varexist(&dsnin,&outvar,len);
%let vartype=%varexist(&dsnin,&outvar,type);
%if (&vartype = C) %then %do;
%if (&varlen and (&varlen < &len) ) %then
%parmv(len,_msg=&outvar already is defined in &dsnin as length &varlen)
;
%end;
%else %do;
%parmv(outvar,_msg=&outvar is defined in &dsnin as numeric)
%let vartype=%str(numeric );
%end;
%if (&parmerr) %then %goto quit;
*------------------------------------------------------------------------------;
* Wrap variable into multiple observations ;
*------------------------------------------------------------------------------;
data &dsnout;
&outvar = repeat(' ',&len-1);
set &dsnin;
drop _save _pnum _done _split _para _lnum;
_save=&invar;
_pnum=0;
_done=0;
do until (_done);
_pnum+1;
%if %length(&split) %then %do;
_split = indexc(_save,&split);
%end;
%else %do;
_split=0;
%end;
if (_split > 1) then do;
_para = substr(_save,1,_split-1);
_save = substr(_save,_split+1);
end;
else if (_split = 1) then do;
_para = ' ';
_save = substr(_save,2);
end;
else do;
_para = _save;
_done=1;
end;
_lnum=1;
do while (length(_para) > &len);
&outvar = substr(_para,1,&len);
_split =indexc(&outvar,&break);
* ? Need to move a broken word from current line to next line ? ;
if length(compress(substr(_para,&len,2))) = 2 and (_split > 0) then do;
_split = indexc( reverse(trim(&outvar)) ,&break);
&outvar = substr(&outvar,1,&len - _split + 1);
end;
output;
_lnum+1;
_para = left(substr(_para,length(&outvar)+1));
end;
if (_lnum=1) or (_para ne ' ') then do;
&outvar = _para;
output;
end;
end;
run;
%quit:
%mend wrap;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
That really looks like you want the long text to be a different variable. ANY property applied to the long text will be the same for the Cat_A unless you do something by parsing the values in a COMPUTE block, and I'm not sure what that compute block would look like.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
To indent the value just add spaces in the front of the value.
If you want the flowed lines to also indent then you probably need to wrap the text yourself.
Example :
data x;
length x $100;
x='cat_A';
output;
x=substr(' ' || repeat('lorum ipsum ',4),1,50);
output;
x=substr(' ' || repeat('lorum ipsum ',4),1,50);
output;
run;
Result:
HEADER cat_A lorum ipsum lorum ipsum lorum ipsum lorum ipsum lorum ipsum lorum ipsum lorum ipsum lorum ipsum
PS Why did you attach the $100. format specification to the variable X? If you want to define a variable use the LENGTH statement or the LENGTH= attribute of the ATTRIB statement.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your suggestion. Adding spaces is what I used in my report.
However, if the 'subcat ' text is very long and show in multiple lines, only the first line is indented, which makes the report difficult to read. In your output, if you set the width is small (eg. width=30 in define) in your proc report, you will find the issue.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Like I said. Write your own wrapping logic.
Here is such a program from years ago. You would need to post-process the output of this to prepend the leading spaces for the indentation.
%macro wrap
/*------------------------------------------------------------------------------
Wrap long string into mulitple observations
------------------------------------------------------------------------------*/
(dsnin= /* Input dataset */
,dsnout= /* Output dataset */
,invar= /* Variable to wrap */
,outvar= /* Name of wrapped variable */
,len=80 /* Length to wrap */
,split='0d'x /* Character(s) to use for forcing new observation */
,break=",- " /* Character(s) used to break long words across lines */
);
/*------------------------------------------------------------------------------
Wrap a long variable into multiple lines. Split characters will cause
the starting of a new line. Break characters will control where words can be
broken to fit into a line.
------------------------------------------------------------------------------*/
%local macro parmerr varlen vartype;
%let macro=WRAP;
%parmv(dsnin,_req=1)
%parmv(dsnout,_req=1)
%parmv(invar,_req=1)
%parmv(outvar,_req=1)
%parmv(len,_val=positive,_req=1)
%let varlen=%varexist(&dsnin,&outvar,len);
%let vartype=%varexist(&dsnin,&outvar,type);
%if (&vartype = C) %then %do;
%if (&varlen and (&varlen < &len) ) %then
%parmv(len,_msg=&outvar already is defined in &dsnin as length &varlen)
;
%end;
%else %do;
%parmv(outvar,_msg=&outvar is defined in &dsnin as numeric)
%let vartype=%str(numeric );
%end;
%if (&parmerr) %then %goto quit;
*------------------------------------------------------------------------------;
* Wrap variable into multiple observations ;
*------------------------------------------------------------------------------;
data &dsnout;
&outvar = repeat(' ',&len-1);
set &dsnin;
drop _save _pnum _done _split _para _lnum;
_save=&invar;
_pnum=0;
_done=0;
do until (_done);
_pnum+1;
%if %length(&split) %then %do;
_split = indexc(_save,&split);
%end;
%else %do;
_split=0;
%end;
if (_split > 1) then do;
_para = substr(_save,1,_split-1);
_save = substr(_save,_split+1);
end;
else if (_split = 1) then do;
_para = ' ';
_save = substr(_save,2);
end;
else do;
_para = _save;
_done=1;
end;
_lnum=1;
do while (length(_para) > &len);
&outvar = substr(_para,1,&len);
_split =indexc(&outvar,&break);
* ? Need to move a broken word from current line to next line ? ;
if length(compress(substr(_para,&len,2))) = 2 and (_split > 0) then do;
_split = indexc( reverse(trim(&outvar)) ,&break);
&outvar = substr(&outvar,1,&len - _split + 1);
end;
output;
_lnum+1;
_para = left(substr(_para,length(&outvar)+1));
end;
if (_lnum=1) or (_para ne ' ') then do;
&outvar = _para;
output;
end;
end;
run;
%quit:
%mend wrap;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
@Niugg2010 wrote:
I an trying to use your macro, and it has errors. I guess I missed %parmv and %varexist macros.
You should be able to comment out the parameter validation section of the macro. Or you could get those macros from GITHUB.
Here is an example:
data test1;
length invar $ 4000 outvar $40;
input invar $80.;
*---+----10---+----20---+----30---+----40---+----50 ;
cards;
This is a line that is long, and should wrap
This is two paragraphs./This is a line that is long-And should wrap
This is two splits in a row.//How does it work?
This hyphen is right at the b-oundary.
Try it when a word ends right. On the boundry.
Check if a word_is_longer_than_a_single_line. What will it do?
/First character is split.
Last character is split./
run;
options mprint;
%wrap
(dsnin=test1
,dsnout=test2
,invar=invar
,outvar=outvar
,len=30
,split="/"
);
proc print;
var outvar invar;
run;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
To get PROC REPORT to insert group heading lines use COMPUTE blocks.
data x;
length group $50 x $100;
group='cat_A';
x = repeat('lorum ipsum ',20);
space=' ';
run;
proc report data=x;
column space group x;
define space / width=2 spacing=0 ' ' ;
define group / group noprint;
compute before group;
line @1 group $50. ;
endcomp;
define x / 'HEADER' width=50 flow;
run;
HEADER cat_A lorum ipsum lorum ipsum lorum ipsum lorum ipsum lorum ipsum lorum ipsum lorum ipsum lorum ipsum loru
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Thanks a lot.
That is interesting. I should gave a more closer example.
Please see below example. This example only have 2 groups (group 1 and 2), but actually we have more groups, so the "System Organ Class ...." column can not be wider. The Yellow marked part is SOC, and gray marked part is PT. The blue circled items have two rows due to the column width is not enough, and I want the two rows indented, not only the first row, so that the output should look better. If output is rft, it is easy to do. But if output is listing, I have not figured out a good method.