DATA Step, Macro, Functions and more

Limiting the lines of code needed to call macro

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 14
Accepted Solution

Limiting the lines of code needed to call macro

I want to make my code more parsimonious.  My Macro uses two variables: Y and Z and they ranges as follows:

Y = {1-4}

Z = {1-50}

When calling the MACRO I am currently doing it like this:

%MACRO One (Y, Z);

Code code code

%MEND;

%One (1,1);

%One (1,2);

%One (1,3);

....

%One (4,50);

It takes up 200 lines of code to call the macro.  There has to be a better way.  I tried using %do i = 1 %to 4 and %do j=1 %to 50 between where I mend the macro and where I call it; but it did not work.  Any ideas?  Thanks as always SAS experts!!!


Accepted Solutions
Solution
‎11-26-2012 12:37 PM
Super User
Posts: 17,750

Re: Limiting the lines of code needed to call macro

Create another macro to loop through it.

But ideally you should change your original macro to handle it.

%macro one(ymin=1, ymax=4, zmin=1, zmax=50);

%do i=&ymin %to &ymax;

% do j=&zmin %to &zmax;

%one(&i, &j);

*OR Original  macro code goes here;

%end;

%end;

%mend;

View solution in original post


All Replies
Solution
‎11-26-2012 12:37 PM
Super User
Posts: 17,750

Re: Limiting the lines of code needed to call macro

Create another macro to loop through it.

But ideally you should change your original macro to handle it.

%macro one(ymin=1, ymax=4, zmin=1, zmax=50);

%do i=&ymin %to &ymax;

% do j=&zmin %to &zmax;

%one(&i, &j);

*OR Original  macro code goes here;

%end;

%end;

%mend;

Occasional Contributor
Posts: 14

Re: Limiting the lines of code needed to call macro

I went with your solution once I figured it out...  Thank you!!!  As always this forum is a great resource for relative SAS novices like myself.

PROC Star
Posts: 7,356

Re: Limiting the lines of code needed to call macro

The question, I think, is why you couldn't get it to work using a %do loop.  What kind of error(s) did you get?  I think the problem is probably within the macro that you wrote.  It would help if you posted it and some example data you are addressing.

Occasional Contributor
Posts: 14

Re: Limiting the lines of code needed to call macro

%MACRO BIGfile (form, Version);

data _null_;

    set List;

    file "&winsteps.\Project_V&version._&form..big" Lrecl=50000;

    if _n_ = 1 then do;

    put '&INST';

    put "TITLE=Project Anchor Run Calibration: Version &version. Form &form.";

    put "ITEM1=1";

    put "LCONV=0.000001";

    put "RCONV=0.001";

    put "DATA=Project_V&version._&form..dat";

    put "NI=38";

    put "XWIDE = 1";

    put "CODES = 0123456789";

    put "GROUPS=0";

    put 'MUCON=50';

    put 'STKEEP=Y';

    put "IFILE=Project_V&version._&form..itm";

    put "SFILE=Project_V&version._&form..san";

    put "DISFILE=Project_V&version._&form..dis";

    put "IAFILE=Project.iaf";

    put "SAFILE=Project.saf";

    put 'TFILE=*';

    put '0';

    put '3';

    put '12';

    put '14';

    put '20';

    put '*';

    put 'BATCH=Y';

    put '&END';

    end;

    put    @1 Name;

    if _n_ = 38 then put "END NAMES";

run;

data BatchFile;

    format ANC_Batch $120.;

    ANC_Batch = "c:\winsteps374\winsteps.exe Project_V&version._&form..big Project_V&version._&form..out";

run;

Proc Append Base = BatchFile2 new = BatchFile;

run;

data _null_;

    set BatchFile2;

    file "&winsteps.\Anchor Run.bat" Lrecl=50000;

    put

        @1 ANC_Batch;

run;

   

%MEND BIGFILE;

%Do i=1 %to 4;

    %Do j=1 %to 50;

%BIGFile (&j, &i);

    %end;

%end;

There is my code <for the most part>.  I am attempting to create 200 different files and then create a .bat file to run them for me.  I have everything running fine, I just figured there had to be a way I could do it differently and more efficiently.  The error I get concerns the %end statements.  It says the %end statement is not valid in open code.  

Super User
Super User
Posts: 6,497

Re: Limiting the lines of code needed to call macro

You can probably eliminate the macro code completely. You can use the FILEVAR option of the FILE statement to have a single DATA step create multiple files. 

Occasional Contributor
Posts: 14

Re: Limiting the lines of code needed to call macro

My apologies Tom.  I have never used a filevar option before, thus I am unfamiliar with it.  Would it be possible for you to show me an example using my example code above?  Thank you as always for all your help!!!

PROC Star
Posts: 7,356

Re: Limiting the lines of code needed to call macro

I think it would be easier for Tom, or any of us, to answer the question about using the filevar option if you posted a small example file and what you were trying to do with it.

As for the errors, I'm surprised they were the only errors, as your macro also includes a couple of global macro variables that would have had to have been created before the macro could run.

Like Fareeza had suggested, you would just have to put the two %do loops at the start of your macro, and the two %end statements at the bottom of your macro.  %do can only be used within a SAS macro.

Super User
Super User
Posts: 6,497

Re: Limiting the lines of code needed to call macro

Not sure if creating the dataset with the list of the lines written to the .BAT file is important.  If not then just use data _NULL_ instead.

One advantage of using DATA step to generate the files is that you have more flexibility with the DO statement than the %DO statement.

You can combine iterated lists with just lists of values. For example: DO form=1 to 5,10,20,100;

I also added code to use the NOBS option on the SET statement for the input dataset LIST so that it will output all of the names in the dataset into each of the generated BIG files and the number of records in LIST does not always have to be exactly 38.  I had it replace the 38 in the value of NI= with the number of obs from the LIST dataset.

data batchfile ;

  length filename bigfilename $200 ;

  do form=1 to 4;

    do version=1 to 50 ;

      filename = cats("Project_V",version,'_',form);

      bigfilename = cats("&winsteps\",filename,'.big');

* Write BIG file ;

      file big filevar=bigfilename lrecl=50000;

      put

  '&INST'

/ 'TITLE=Project Anchor Run Calibration: Version ' version 'Form' form'

/ 'ITEM1=1'

/ 'LCONV=0.000001'

/ 'RCONV=0.001'

/ 'DATA=' filename +(-1) '.dat'

/ 'NI=' nobs

/ 'XWIDE = 1'

/ 'CODES = 0123456789'

/ 'GROUPS=0'

/ 'MUCON=50'

/ 'STKEEP=Y'

/ 'IFILE=' filename +(-1) '.itm'

/ 'SFILE=' filename +(-1) '.san'

/ 'DISFILE=' filename +(-1) '.dis'

/ 'IAFILE=Project.iaf'

/ 'SAFILE=Project.saf'

/ 'TFILE=*'

/ '0'

/ '3'

/ '12'

/ '14'

/ '20'

/ '*'

/ 'BATCH=Y'

/ '&END'

      ;

      do p=1 to nobs;

        set List point=p nobs=nobs;

        put @1 Name;

      end;

      put "END NAMES";

* Write line to batch file. ;

      file "&winsteps.\Anchor Run.bat" Lrecl=50000;

      put "c:\winsteps374\winsteps.exe " bigfilename filename +(-1) '.out';

    end;

  end;

   stop;

run;

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 8 replies
  • 281 views
  • 0 likes
  • 4 in conversation