|Date: ||Tue, 19 Nov 2002 17:21:40 -0500|
|Reply-To: ||Don Henderson <donaldjhenderson@HOTMAIL.COM>|
|Sender: ||"SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>|
|From: ||Don Henderson <donaldjhenderson@HOTMAIL.COM>|
|Subject: ||Re: proc report width=|
|Content-Type: ||text/plain; charset="iso-8859-1"|
Probably isn't terribly efficient, but if the data sets are not large, or if
the cycles are available, it might still be a reasonable thing to do.
I dug the following macro out that I used a while back when I was reading in
CSV data and all the lengths were defaulting to 255. The code queries
dictionary tables to identify the max length of all the character variables
(the SQL trick was "acquired" from a Peter Crawford post a while back),
followed by a data step to build format and informat statements, which is
then followed by a data step to reassign the length for the char vars to the
longest value (note that happens because the fomrat and informat statements
are before the SET statement).
This macro won't work for character variables that have a format already
defined (was not an issue in the problem I needed the macro for). It also
assume the total length of the format list is 1024 (again not an issue for
the quick and dirty data load I needed it for). So if you want to try this,
and either of these restrictions are an issue for you, you could either
tweak the code or you could just change the code to assign a length instead
of a format.
And for your problem, you might not need to rewrite the data set, you might
just need to use the format statement it builds in your proc report step.
%local format sqlcode format;
/* determine the max length for each character variable */
proc sql noprint;
select ' max( length(' || name || ' )) as ' || name
into :sqlcode separated by ', '
where libname = "%upcase( %scan( &data, 1, . ) )" and
memname = "%upcase( %scan( &data, 2, . ) )" and
type = "char"
create table lengths as select &sqlcode from &data;
length fmt $1024;
array lengths _numeric_;
do over lengths;
fmt = trim(fmt) || ' ' || vname(lengths) || ' $' ||
trim(left(put(lengths,4.))) || '.';
%if %length(&out) = 0 %then %let out = &data;
----- Original Message -----
From: "Suzanne D. McCoy" <smccoy@LUCIDAN.COM>
Sent: Tuesday, November 19, 2002 4:58 PM
Subject: Re: proc report width=
> You could also just shortcut the entire issue by using a default width for
> the columns and the flow option. The only macro alternative I can think
> off the top is my head is to bump through the entire dataset again to
> determine the lengths via a max(length(for each variable)) and set them to
> macro variables, using dictionary.columns to determine the character
> variables, but what is that going to do to the efficiency/runtime?
> Suzanne D. McCoy
> Lucid Analytics Corp.
> "Intelligence Unleashed"
> > I asked for this capability in PROC REPORT a while back; apparently
> > there's not enough perceived demand to warrant the programming effort.
> > If you want it, send mail to email@example.com.
> > --
> > JackHamilton@FirstHealth.com
> > Manager, Technical Development
> > METRICS Department, First Health
> > West Sacramento, California USA
> >>>> Kevin Auslander <kauslander@TERRECRS.COM> 11/19/2002 1:33 PM >>>
> > I find that I frequently need to set the width of each
> > character variable manually when using proc report. I usually set it
> > to
> > a value that is equal to max(the longest word in the label, the length
> > of the longest data value). Setting the width for each variable
> > becomes
> > very tedious when I have to create several reports with many variables
> > each. I read in the help files that proc report will automatically set
> > the column width to accommodate the format of the variable. So what I
> > need is a macro that will set the format of each variable to max(the
> > longest word in the label, the length of the longest data value).
> > Does
> > anyone out there have a macro that does this? Or does anyone have a
> > different solution to the problem. TIA
> > Kevin