From: =?ISO-8859-1?Q?Daniel_Fern=E1ndez?= on
Hi Ian,

I don�t see mistake with double quotes here (believe me, it works fine).
Anyway, they can give rise to confusion if I was what you meant.

I think, it avoids to create a macro, only creates a macrovariable.

Other way, it could be done with temp flat files;
what do you think about this method?:

filename fff temp;
data _null_;
file fff;
put 'data combined_states;' / @3 'set ';
do until (fin);
set states end=fin;
file fff;
put 'state_' state;
end;
file fff;
put '; run;';
stop;
run;
%inc fff/source2;

Daniel Fernandez.



El d�a 15 de diciembre de 2009 22:25, Ian Whitlock <iw1sas(a)gmail.com> escribi�:
> Daniel,
>
> I think you learned the wrong lesson. Sometimes it is worth avoiding the
> use of macros, but the desire to get a list of states into code does not
> strike me as one of them. The technique is important.
>
> Your double quotes are wrong and this is a macro error. Why introduce the
> macro variables if your point is to avoid macro. For a shorter and simpler
> one step non-macro try:
>
> filename code temp ;
>>
>> data states ;
>> input state $ @@ ;
>
> put "proc append base=combined_states data=" state "force; run;" ;
>>
>> cards ;
>> il nj pa nyc
>> ;
>
> %inc code ;
>
> Perhaps PROC APPEND is better, but it is very questionable. PROC APPEND
> will
> only use the variables from IL. The code the OP was trying to execute is
> more flexible and efficient.
>
> Incidentally, the line
>
>>> %let state_list = &state_list state_&&state_&loop /* NO ; */
>
> from my posting below is wrong. Of course it should be
>
> %let state_list = &state_list state_&&state_&loop ;
>
> Ian Whitlock
> ============
> On Dec 15, 2009, at 4:58 AM, Daniel Fern�ndez wrote:
>
>> After reading SAS-L experts to say to avoid writing SAS macros if
>> possible,
>> I come this time with a non-macro solution (but it uses a macrovariable):
>>
>> data states ;
>> input state $ @@ ;
>> cards ;
>> il nj pa nyc
>> ;
>> run;
>>
>> data _null_;
>> * for each row we pass the state name to the macrovariable 'state_loop';
>> do until (fin);
>> set states end=fin;
>> call symputx('state_loop','state_'||state);
>> *we append each dataset to the combined_states dataset, ONLY EXECUTE
>> ONCE!;
>> call execute("proc append base=combined_states data=&state_loop force;
>> run;");
>> end;
>> run;
>>
>> Daniel Fernandez
>>
>> 2009/12/15 Ian Whitlock <iw1sas(a)gmail.com>:
>>>
>>> Summary: Macro loop or list, and parameters
>>> #iw-value=1
>>>
>>> Swamy,
>>>
>>> You may want
>>>
>>> %macro combined_states();
>>> data combined_states;
>>> set
>>> %do loop = 1 %to &state_count;
>>> state_&&state_&loop /* NO ; */
>>> %end;
>>> ; /* end of set statement */
>>> run;
>>> %mend combined_states;
>>>
>>> %combined_states() /* NO ; */
>>>
>>> Another possibility, just a little better in terms of
>>> readability because it separates the SAS from the macro
>>> is given by the following.
>>>
>>> %macro combined_states();
>>> %local state_list ;
>>> %do loop = 1 %to &state_count;
>>> %let state_list = &state_list state_&&state_&loop /* NO ; */
>>> %end;
>>>
>>> data combined_states;
>>> set &state_list ;
>>> run;
>>> %mend combined_states;
>>>
>>> %combined_states() /* NO ; */
>>>
>>> You do not tell the source of the variables so let's make
>>> up one to indicate some better design elements.
>>>
>>> data states ;
>>> input state $ @@ ;
>>> cards ;
>>> il nj pa nyc
>>> ;
>>>
>>> %macro combined_states(cntl=);
>>> %local state_list ;
>>>
>>> proc sql noprint ;
>>> select "state_" || state into :state_list separated by " "
>>> from &cntl ;
>>> quit ;
>>>
>>> data combined_states;
>>> set &state_list ;
>>> run;
>>> %mend combined_states;
>>>
>>> %combined_states(cntl=states) /* NO ; */
>>>
>>> Parameters help the reader understand the flow of control,
>>> hence they make programs more readable. magic global variables
>>> become a nightmare once one gets beyond baby programs.
>>>
>>> Ian Whitlock
>>> --------------
>>>
>>> Date: Mon, 14 Dec 2009 14:44:39 -0500
>>> From: SAS Swamy <sasswamy(a)GMAIL.COM>
>>> Subject: Dynamic data set-Loop
>>>
>>> Hello everyone,
>>> Can someone help me out with the following I am trying to dynamically
>>> combine few data sets and create one final data sets.
>>> Let say , If I have the following data sets � State wise
>>> State_il
>>> State_nj
>>> State_pa �etc
>>> When I try with the normal code .
>>>
>>> data combined_st;
>>> set state_il state_ma state_nj state_pa state_NYC;
>>> run;
>>> this is working with no Issue ,
>>>
>>> If I try the same dynamically then I am able to assign only the last
>>> data
>>> set,
>>> &state_count � will be the count of end of the loop
>>> state_&&state_&loop - will be the values like state_il , state_nj �etc
>>>
>>> %macro combined_states();
>>> data combined_states;
>>> %do loop = 1 %to &state_count;
>>> set state_&&state_&loop;
>>> %end;
>>> run;
>>> %mend combined_states;
>>>
>>> %combined_states;
>>>
>>> With this logic as you could see what ever the last data set only that
>>> data set is assigned to the final data set,
>>> how can I do a while loop on this ? So that I can assign all the data
>>> sets
>>> from the loop to one final data set.
>>> Please advice
>>>
>>> Thanks,
>>> - Swamy
>>>
>
>
From: Ian Whitlock on
Daniel,

I am sorry to be responding so late. I missed your message in the
archives and
ignored my mail until tonight. You originally suggested:

>>> data states ;
>>> input state $ @@ ;
>>> cards ;
>>> il nj pa nyc
>>> ;
>>> run;
>>>
>>> data _null_;
>>> * for each row we pass the state name to the macrovariable
>>> 'state_loop';
>>> do until (fin);
>>> set states end=fin;
>>> call symputx('state_loop','state_'||state);
>>> *we append each dataset to the combined_states dataset, ONLY
>>> EXECUTE
>>> ONCE!;
>>> call execute("proc append base=combined_states data=&state_loop
>>> force;
>>> run;");
>>> end;
>>> run;
>>

I said that the double quotes are wrong because at the time the step
is compiled
the variable STATE_LOOP does not exist. This is verified by the message

WARNING: Apparent symbolic reference STATE_LOOP not resolved.

However, I was wrong in suggesting that this would prevent the correct
code from
going to the input stack since it &STATE_LOOP goes to the macro
facility (because
it could not be resolved) and at that time the variable does have a
value. On
the other hand, if the code is run interactively twice. Then the code
works the
first time as explained but fails the second time because the line
compiled is

call execute("proc append base=combined_states data=state_NYC
force; run;");

Hence the code is very unstable and I would not consider it an
appropriate way
to write code.

As for the question as to whether one should write code to a flat
file, use CALL
EXECUTE, make a list macro variable, or make an array of macro
variables and use
a %DO_LOOP; I would say it is somewhat a matter of style. When
written correctly
any of these strategies work and each has the advantage in some
problems. In
general, without any knowledge of the problem and its environment I
find the list
macro variable most readable and therefore a strategy that any good
SAS programmer
should have available.

Ian Whitlock
=============

On Dec 16, 2009, at 6:28 AM, Daniel Fern�ndez wrote:

> Hi Ian,
>
> I don�t see mistake with double quotes here (believe me, it works
> fine).
> Anyway, they can give rise to confusion if I was what you meant.
>
> I think, it avoids to create a macro, only creates a macrovariable.
>
> Other way, it could be done with temp flat files;
> what do you think about this method?:
>
> filename fff temp;
> data _null_;
> file fff;
> put 'data combined_states;' / @3 'set ';
> do until (fin);
> set states end=fin;
> file fff;
> put 'state_' state;
> end;
> file fff;
> put '; run;';
> stop;
> run;
> %inc fff/source2;
>
> Daniel Fernandez.
>
>
>
> El d�a 15 de diciembre de 2009 22:25, Ian Whitlock
> <iw1sas(a)gmail.com> escribi�:
>> Daniel,
>>
>> I think you learned the wrong lesson. Sometimes it is worth
>> avoiding the
>> use of macros, but the desire to get a list of states into code
>> does not
>> strike me as one of them. The technique is important.
>>
>> Your double quotes are wrong and this is a macro error. Why
>> introduce the
>> macro variables if your point is to avoid macro. For a shorter and
>> simpler
>> one step non-macro try:
>>
>> filename code temp ;
>>>
>>> data states ;
>>> input state $ @@ ;
>>
>> put "proc append base=combined_states data=" state "force; run;" ;
>>>
>>> cards ;
>>> il nj pa nyc
>>> ;
>>
>> %inc code ;
>>
>> Perhaps PROC APPEND is better, but it is very questionable. PROC
>> APPEND
>> will
>> only use the variables from IL. The code the OP was trying to
>> execute is
>> more flexible and efficient.
>>
>> Incidentally, the line
>>
>>>> %let state_list = &state_list state_&&state_&loop /* NO ; */
>>
>> from my posting below is wrong. Of course it should be
>>
>> %let state_list = &state_list state_&&state_&loop ;
>>
>> Ian Whitlock
>> ============
>> On Dec 15, 2009, at 4:58 AM, Daniel Fern�ndez wrote:
>>
>>> After reading SAS-L experts to say to avoid writing SAS macros if
>>> possible,
>>> I come this time with a non-macro solution (but it uses a
>>> macrovariable):
>>>
>>> data states ;
>>> input state $ @@ ;
>>> cards ;
>>> il nj pa nyc
>>> ;
>>> run;
>>>
>>> data _null_;
>>> * for each row we pass the state name to the macrovariable
>>> 'state_loop';
>>> do until (fin);
>>> set states end=fin;
>>> call symputx('state_loop','state_'||state);
>>> *we append each dataset to the combined_states dataset, ONLY
>>> EXECUTE
>>> ONCE!;
>>> call execute("proc append base=combined_states data=&state_loop
>>> force;
>>> run;");
>>> end;
>>> run;
>>>
>>> Daniel Fernandez
>>>
>>> 2009/12/15 Ian Whitlock <iw1sas(a)gmail.com>:
>>>>
>>>> Summary: Macro loop or list, and parameters
>>>> #iw-value=1
>>>>
>>>> Swamy,
>>>>
>>>> You may want
>>>>
>>>> %macro combined_states();
>>>> data combined_states;
>>>> set
>>>> %do loop = 1 %to &state_count;
>>>> state_&&state_&loop /* NO ; */
>>>> %end;
>>>> ; /* end of set statement */
>>>> run;
>>>> %mend combined_states;
>>>>
>>>> %combined_states() /* NO ; */
>>>>
>>>> Another possibility, just a little better in terms of
>>>> readability because it separates the SAS from the macro
>>>> is given by the following.
>>>>
>>>> %macro combined_states();
>>>> %local state_list ;
>>>> %do loop = 1 %to &state_count;
>>>> %let state_list = &state_list state_&&state_&loop /* NO ; */
>>>> %end;
>>>>
>>>> data combined_states;
>>>> set &state_list ;
>>>> run;
>>>> %mend combined_states;
>>>>
>>>> %combined_states() /* NO ; */
>>>>
>>>> You do not tell the source of the variables so let's make
>>>> up one to indicate some better design elements.
>>>>
>>>> data states ;
>>>> input state $ @@ ;
>>>> cards ;
>>>> il nj pa nyc
>>>> ;
>>>>
>>>> %macro combined_states(cntl=);
>>>> %local state_list ;
>>>>
>>>> proc sql noprint ;
>>>> select "state_" || state into :state_list separated by " "
>>>> from &cntl ;
>>>> quit ;
>>>>
>>>> data combined_states;
>>>> set &state_list ;
>>>> run;
>>>> %mend combined_states;
>>>>
>>>> %combined_states(cntl=states) /* NO ; */
>>>>
>>>> Parameters help the reader understand the flow of control,
>>>> hence they make programs more readable. magic global variables
>>>> become a nightmare once one gets beyond baby programs.
>>>>
>>>> Ian Whitlock
>>>> --------------
>>>>
>>>> Date: Mon, 14 Dec 2009 14:44:39 -0500
>>>> From: SAS Swamy <sasswamy(a)GMAIL.COM>
>>>> Subject: Dynamic data set-Loop
>>>>
>>>> Hello everyone,
>>>> Can someone help me out with the following I am trying to
>>>> dynamically
>>>> combine few data sets and create one final data sets.
>>>> Let say , If I have the following data sets � State wise
>>>> State_il
>>>> State_nj
>>>> State_pa �etc
>>>> When I try with the normal code .
>>>>
>>>> data combined_st;
>>>> set state_il state_ma state_nj state_pa state_NYC;
>>>> run;
>>>> this is working with no Issue ,
>>>>
>>>> If I try the same dynamically then I am able to assign only the
>>>> last
>>>> data
>>>> set,
>>>> &state_count � will be the count of end of the loop
>>>> state_&&state_&loop - will be the values like state_il ,
>>>> state_nj �etc
>>>>
>>>> %macro combined_states();
>>>> data combined_states;
>>>> %do loop = 1 %to &state_count;
>>>> set state_&&state_&loop;
>>>> %end;
>>>> run;
>>>> %mend combined_states;
>>>>
>>>> %combined_states;
>>>>
>>>> With this logic as you could see what ever the last data set only
>>>> that
>>>> data set is assigned to the final data set,
>>>> how can I do a while loop on this ? So that I can assign all the
>>>> data
>>>> sets
>>>> from the loop to one final data set.
>>>> Please advice
>>>>
>>>> Thanks,
>>>> - Swamy
>>>>
>>
>>
From: Ted Clay on
A macro I use frequently is "%DO_OVER", which enables a 1-line solution:

%do_over(values=il nj pa nyc,phrase=proc append base=combined_states
data=state_?;)

I would like to make this macro generally available. What is the best place
to put it?


Ted

-----Original Message-----
From: SAS(r) Discussion [mailto:SAS-L(a)LISTSERV.UGA.EDU] On Behalf Of Ian
Whitlock
Sent: Monday, December 21, 2009 5:59 PM
To: SAS-L(a)LISTSERV.UGA.EDU
Subject: Re: Dynamic data set-Loop

Daniel,

I am sorry to be responding so late. I missed your message in the
archives and
ignored my mail until tonight. You originally suggested:

>>> data states ;
>>> input state $ @@ ;
>>> cards ;
>>> il nj pa nyc
>>> ;
>>> run;
>>>
>>> data _null_;
>>> * for each row we pass the state name to the macrovariable
>>> 'state_loop';
>>> do until (fin);
>>> set states end=fin;
>>> call symputx('state_loop','state_'||state);
>>> *we append each dataset to the combined_states dataset, ONLY
>>> EXECUTE
>>> ONCE!;
>>> call execute("proc append base=combined_states data=&state_loop
>>> force;
>>> run;");
>>> end;
>>> run;
>>

I said that the double quotes are wrong because at the time the step
is compiled
the variable STATE_LOOP does not exist. This is verified by the message

WARNING: Apparent symbolic reference STATE_LOOP not resolved.

However, I was wrong in suggesting that this would prevent the correct
code from
going to the input stack since it &STATE_LOOP goes to the macro
facility (because
it could not be resolved) and at that time the variable does have a
value. On
the other hand, if the code is run interactively twice. Then the code
works the
first time as explained but fails the second time because the line
compiled is

call execute("proc append base=combined_states data=state_NYC
force; run;");

Hence the code is very unstable and I would not consider it an
appropriate way
to write code.

As for the question as to whether one should write code to a flat
file, use CALL
EXECUTE, make a list macro variable, or make an array of macro
variables and use
a %DO_LOOP; I would say it is somewhat a matter of style. When
written correctly
any of these strategies work and each has the advantage in some
problems. In
general, without any knowledge of the problem and its environment I
find the list
macro variable most readable and therefore a strategy that any good
SAS programmer
should have available.

Ian Whitlock
=============

On Dec 16, 2009, at 6:28 AM, Daniel Fern�ndez wrote:

> Hi Ian,
>
> I don�t see mistake with double quotes here (believe me, it works
> fine).
> Anyway, they can give rise to confusion if I was what you meant.
>
> I think, it avoids to create a macro, only creates a macrovariable.
>
> Other way, it could be done with temp flat files;
> what do you think about this method?:
>
> filename fff temp;
> data _null_;
> file fff;
> put 'data combined_states;' / @3 'set ';
> do until (fin);
> set states end=fin;
> file fff;
> put 'state_' state;
> end;
> file fff;
> put '; run;';
> stop;
> run;
> %inc fff/source2;
>
> Daniel Fernandez.
>
>
>
> El d�a 15 de diciembre de 2009 22:25, Ian Whitlock
> <iw1sas(a)gmail.com> escribi�:
>> Daniel,
>>
>> I think you learned the wrong lesson. Sometimes it is worth
>> avoiding the
>> use of macros, but the desire to get a list of states into code
>> does not
>> strike me as one of them. The technique is important.
>>
>> Your double quotes are wrong and this is a macro error. Why
>> introduce the
>> macro variables if your point is to avoid macro. For a shorter and
>> simpler
>> one step non-macro try:
>>
>> filename code temp ;
>>>
>>> data states ;
>>> input state $ @@ ;
>>
>> put "proc append base=combined_states data=" state "force; run;" ;
>>>
>>> cards ;
>>> il nj pa nyc
>>> ;
>>
>> %inc code ;
>>
>> Perhaps PROC APPEND is better, but it is very questionable. PROC
>> APPEND
>> will
>> only use the variables from IL. The code the OP was trying to
>> execute is
>> more flexible and efficient.
>>
>> Incidentally, the line
>>
>>>> %let state_list = &state_list state_&&state_&loop /* NO ; */
>>
>> from my posting below is wrong. Of course it should be
>>
>> %let state_list = &state_list state_&&state_&loop ;
>>
>> Ian Whitlock
>> ============
>> On Dec 15, 2009, at 4:58 AM, Daniel Fern�ndez wrote:
>>
>>> After reading SAS-L experts to say to avoid writing SAS macros if
>>> possible,
>>> I come this time with a non-macro solution (but it uses a
>>> macrovariable):
>>>
>>> data states ;
>>> input state $ @@ ;
>>> cards ;
>>> il nj pa nyc
>>> ;
>>> run;
>>>
>>> data _null_;
>>> * for each row we pass the state name to the macrovariable
>>> 'state_loop';
>>> do until (fin);
>>> set states end=fin;
>>> call symputx('state_loop','state_'||state);
>>> *we append each dataset to the combined_states dataset, ONLY
>>> EXECUTE
>>> ONCE!;
>>> call execute("proc append base=combined_states data=&state_loop
>>> force;
>>> run;");
>>> end;
>>> run;
>>>
>>> Daniel Fernandez
>>>
>>> 2009/12/15 Ian Whitlock <iw1sas(a)gmail.com>:
>>>>
>>>> Summary: Macro loop or list, and parameters
>>>> #iw-value=1
>>>>
>>>> Swamy,
>>>>
>>>> You may want
>>>>
>>>> %macro combined_states();
>>>> data combined_states;
>>>> set
>>>> %do loop = 1 %to &state_count;
>>>> state_&&state_&loop /* NO ; */
>>>> %end;
>>>> ; /* end of set statement */
>>>> run;
>>>> %mend combined_states;
>>>>
>>>> %combined_states() /* NO ; */
>>>>
>>>> Another possibility, just a little better in terms of
>>>> readability because it separates the SAS from the macro
>>>> is given by the following.
>>>>
>>>> %macro combined_states();
>>>> %local state_list ;
>>>> %do loop = 1 %to &state_count;
>>>> %let state_list = &state_list state_&&state_&loop /* NO ; */
>>>> %end;
>>>>
>>>> data combined_states;
>>>> set &state_list ;
>>>> run;
>>>> %mend combined_states;
>>>>
>>>> %combined_states() /* NO ; */
>>>>
>>>> You do not tell the source of the variables so let's make
>>>> up one to indicate some better design elements.
>>>>
>>>> data states ;
>>>> input state $ @@ ;
>>>> cards ;
>>>> il nj pa nyc
>>>> ;
>>>>
>>>> %macro combined_states(cntl=);
>>>> %local state_list ;
>>>>
>>>> proc sql noprint ;
>>>> select "state_" || state into :state_list separated by " "
>>>> from &cntl ;
>>>> quit ;
>>>>
>>>> data combined_states;
>>>> set &state_list ;
>>>> run;
>>>> %mend combined_states;
>>>>
>>>> %combined_states(cntl=states) /* NO ; */
>>>>
>>>> Parameters help the reader understand the flow of control,
>>>> hence they make programs more readable. magic global variables
>>>> become a nightmare once one gets beyond baby programs.
>>>>
>>>> Ian Whitlock
>>>> --------------
>>>>
>>>> Date: Mon, 14 Dec 2009 14:44:39 -0500
>>>> From: SAS Swamy <sasswamy(a)GMAIL.COM>
>>>> Subject: Dynamic data set-Loop
>>>>
>>>> Hello everyone,
>>>> Can someone help me out with the following I am trying to
>>>> dynamically
>>>> combine few data sets and create one final data sets.
>>>> Let say , If I have the following data sets � State wise
>>>> State_il
>>>> State_nj
>>>> State_pa �etc
>>>> When I try with the normal code .
>>>>
>>>> data combined_st;
>>>> set state_il state_ma state_nj state_pa state_NYC;
>>>> run;
>>>> this is working with no Issue ,
>>>>
>>>> If I try the same dynamically then I am able to assign only the
>>>> last
>>>> data
>>>> set,
>>>> &state_count � will be the count of end of the loop
>>>> state_&&state_&loop - will be the values like state_il ,
>>>> state_nj �etc
>>>>
>>>> %macro combined_states();
>>>> data combined_states;
>>>> %do loop = 1 %to &state_count;
>>>> set state_&&state_&loop;
>>>> %end;
>>>> run;
>>>> %mend combined_states;
>>>>
>>>> %combined_states;
>>>>
>>>> With this logic as you could see what ever the last data set only
>>>> that
>>>> data set is assigned to the final data set,
>>>> how can I do a while loop on this ? So that I can assign all the
>>>> data
>>>> sets
>>>> from the loop to one final data set.
>>>> Please advice
>>>>
>>>> Thanks,
>>>> - Swamy
>>>>
>>
>>
From: Tom Abernathy on
Ted -
For a similar utility to your DO_OVER macro look at the %FOR macro
that was recently discussed on SAS-L.
It is available on the SAS Communnity site.
http://www.sascommunity.org/wiki/Streamlining_Data-Driven_SAS_With_The_%25FOR_Macro
(Short url http://20.fi/2843 )


- Tom

On Dec 21, 11:06 pm, tc...(a)ASHLANDHOME.NET (Ted Clay) wrote:
> A macro I use frequently is "%DO_OVER", which enables a 1-line solution:
>
>  %do_over(values=il nj pa nyc,phrase=proc append base=combined_states
> data=state_?;)
>
> I would like to make this macro generally available.  What is the best place
> to put it?
>
> Ted
>
>
>
> -----Original Message-----
> From: SAS(r) Discussion [mailto:SA...(a)LISTSERV.UGA.EDU] On Behalf Of Ian
>
> Whitlock
> Sent: Monday, December 21, 2009 5:59 PM
> To: SA...(a)LISTSERV.UGA.EDU
> Subject: Re: Dynamic data set-Loop
>
> Daniel,
>
> I am sorry to be responding so late.  I missed your message in the
> archives and
> ignored my mail until tonight.  You originally suggested:
>
> >>> data states ;
> >>> input state $ @@ ;
> >>> cards ;
> >>> il nj pa nyc
> >>> ;
> >>> run;
>
> >>> data _null_;
> >>>  * for each row we pass the state name to the macrovariable
> >>> 'state_loop';
> >>>  do until (fin);
> >>>  set states end=fin;
> >>>  call symputx('state_loop','state_'||state);
> >>>  *we append each dataset to the combined_states dataset, ONLY
> >>> EXECUTE
> >>> ONCE!;
> >>>  call execute("proc append base=combined_states data=&state_loop
> >>> force;
> >>> run;");
> >>>  end;
> >>>  run;
>
> I said that the double quotes are wrong because at the time the step
> is compiled
> the variable STATE_LOOP does not exist.  This is verified by the message
>
>    WARNING: Apparent symbolic reference STATE_LOOP not resolved.
>
> However, I was wrong in suggesting that this would prevent the correct
> code from
> going to the input stack since it &STATE_LOOP goes to the macro
> facility (because
> it could not be resolved) and at that time the variable does have a
> value.  On
> the other hand, if the code is run interactively twice.  Then the code
> works the
> first time as explained but fails the second time because the line
> compiled is
>
>    call execute("proc append base=combined_states data=state_NYC
> force; run;");
>
> Hence the code is very unstable and I would not consider it an
> appropriate way
> to write code.
>
> As for the question as to whether one should write code to a flat
> file, use CALL
> EXECUTE, make a list macro variable, or make an array of macro
> variables and use
> a %DO_LOOP; I would say it is somewhat a matter of style.  When
> written correctly
> any of these strategies work and each has the advantage in some
> problems.  In
> general, without any knowledge of the problem and its environment I
> find the list
> macro variable most readable and therefore a strategy that any good
> SAS programmer
> should have available.
>
> Ian Whitlock
> =============
>
> On Dec 16, 2009, at 6:28 AM, Daniel Fernández wrote:
>
> > Hi Ian,
>
> > I don´t see mistake with double quotes here (believe me, it works
> > fine).
> > Anyway, they can give rise to confusion if I was what you meant.
>
> > I think, it avoids to create a macro, only creates a macrovariable.
>
> > Other way, it could be done with temp flat files;
> > what do you think about this method?:
>
> > filename fff temp;
> > data _null_;
> > file fff;
> > put 'data combined_states;' / @3 'set ';
> > do until (fin);
> > set states end=fin;
> > file fff;
> > put 'state_' state;
> > end;
> > file fff;
> > put '; run;';
> > stop;
> > run;
> > %inc fff/source2;
>
> > Daniel Fernandez.
>
> > El día 15 de diciembre de 2009 22:25, Ian Whitlock
> > <iw1...(a)gmail.com> escribió:
> >> Daniel,
>
> >> I think you learned the wrong lesson.  Sometimes it is worth
> >> avoiding the
> >> use of macros, but the desire to get a list of states into code
> >> does not
> >> strike me as one of them.  The technique is important.
>
> >> Your double quotes are wrong and this is a macro error.  Why
> >> introduce the
> >> macro variables if your point is to avoid macro.  For a shorter and
> >> simpler
> >> one step non-macro try:
>
> >>  filename code temp ;
>
> >>> data states ;
> >>> input state $ @@ ;
>
> >>  put "proc append base=combined_states data=" state "force; run;" ;
>
> >>> cards ;
> >>> il nj pa nyc
> >>> ;
>
> >>  %inc code ;
>
> >> Perhaps PROC APPEND is better, but it is very questionable.  PROC
> >> APPEND
> >> will
> >> only use the variables from IL.  The code the OP was trying to
> >> execute is
> >> more flexible and efficient.
>
> >> Incidentally, the line
>
> >>>>      %let state_list = &state_list state_&&state_&loop  /* NO ; */
>
> >> from my posting below is wrong.  Of course it should be
>
> >>        %let state_list = &state_list state_&&state_&loop ;
>
> >> Ian Whitlock
> >> ============
> >> On Dec 15, 2009, at 4:58 AM, Daniel Fernández wrote:
>
> >>> After reading SAS-L experts to say to avoid writing SAS macros if
> >>> possible,
> >>>  I come this time with a non-macro solution (but it uses a
> >>> macrovariable):
>
> >>> data states ;
> >>> input state $ @@ ;
> >>> cards ;
> >>> il nj pa nyc
> >>> ;
> >>> run;
>
> >>> data _null_;
> >>>  * for each row we pass the state name to the macrovariable
> >>> 'state_loop';
> >>>  do until (fin);
> >>>  set states end=fin;
> >>>  call symputx('state_loop','state_'||state);
> >>>  *we append each dataset to the combined_states dataset, ONLY
> >>> EXECUTE
> >>> ONCE!;
> >>>  call execute("proc append base=combined_states data=&state_loop
> >>> force;
> >>> run;");
> >>>  end;
> >>>  run;
>
> >>> Daniel Fernandez
>
> >>> 2009/12/15 Ian Whitlock <iw1...(a)gmail.com>:
>
> >>>> Summary: Macro loop or list, and parameters
> >>>> #iw-value=1
>
> >>>> Swamy,
>
> >>>> You may want
>
> >>>>  %macro combined_states();
> >>>>  data combined_states;
> >>>>   set
> >>>>     %do loop = 1 %to &state_count;
> >>>>       state_&&state_&loop  /* NO ; */
> >>>>     %end;
> >>>>   ;   /* end of set statement */
> >>>>  run;
> >>>>  %mend combined_states;
>
> >>>>  %combined_states()   /* NO ; */
>
> >>>> Another possibility, just a little better in terms of
> >>>> readability because it separates the SAS from the macro
> >>>> is given by the following.
>
> >>>>  %macro combined_states();
> >>>>   %local state_list ;
> >>>>   %do loop = 1 %to &state_count;
> >>>>      %let state_list = &state_list state_&&state_&loop  /* NO ; */
> >>>>   %end;
>
> >>>>   data combined_states;
> >>>>     set &state_list ;
> >>>>   run;
> >>>>  %mend combined_states;
>
> >>>>  %combined_states()   /* NO ; */
>
> >>>> You do not tell the source of the variables so let's make
> >>>> up one to indicate some better design elements.
>
> >>>>  data states ;
> >>>>     input state $ @@ ;
> >>>>  cards ;
> >>>>  il nj pa nyc
> >>>>  ;
>
> >>>>  %macro combined_states(cntl=);
> >>>>    %local state_list ;
>
> >>>>    proc sql noprint ;
> >>>>       select "state_" || state into :state_list separated by " "
> >>>>          from &cntl ;
> >>>>    quit ;
>
> >>>>    data combined_states;
> >>>>      set &state_list ;
> >>>>    run;
> >>>>  %mend combined_states;
>
> >>>>  %combined_states(cntl=states)   /* NO ; */
>
> >>>> Parameters help the reader understand the flow of control,
> >>>> hence they make programs more readable.  magic global variables
> >>>> become a nightmare once one gets beyond baby programs.
>
> >>>> Ian Whitlock
> >>>> --------------
>
> >>>> Date:         Mon, 14 Dec 2009 14:44:39 -0500
> >>>> From:         SAS Swamy <sassw...(a)GMAIL.COM>
> >>>> Subject:      Dynamic data set-Loop
>
> >>>> Hello everyone,
> >>>> Can someone help me out with the following  I am trying to
> >>>> dynamically
> >>>> combine few data sets and create one final data sets.
> >>>> Let say , If I have the following data sets – State wise
> >>>> State_il
> >>>> State_nj
> >>>> State_pa …etc
> >>>> When I try with the normal code .
>
> >>>> data combined_st;
> >>>> set state_il state_ma state_nj state_pa state_NYC;
> >>>> run;
> >>>> this is working with no Issue ,
>
> >>>> If I try the same dynamically then I am able to assign only the
> >>>> last
> >>>> data
> >>>> set,
> >>>> &state_count – will be the count of end of the loop
> >>>> state_&&state_&loop -  will be the values like state_il ,
> >>>> state_nj …etc
>
> >>>> %macro combined_states();
> >>>>  data combined_states;
> >>>>  %do loop = 1 %to &state_count;
> >>>>  set state_&&state_&loop;
> >>>>  %end;
> >>>>  run;
> >>>> %mend combined_states;
>
> >>>> %combined_states;
>
> >>>> With this logic as you could see what ever the last data set only
> >>>> that
> >>>> data set is assigned to the final data set,
> >>>> how can I do a while loop on this ? So that I can assign all the
> >>>> data
> >>>> sets
> >>>> from the loop to one final data set.
> >>>> Please advice
>
> >>>> Thanks,
> >>>> - Swamy- Hide quoted text -
>
> - Show quoted text -