Link to home
Start Free TrialLog in
Avatar of labradorchik
labradorchikFlag for United States of America

asked on

How can I create SAS macro with parameters?

Hello,
I will not be able to run below program for the next 2-4 days but I am trying to see if my syntax is correct or maybe if this program can be written differently/ in a better way? Any help will be greatly appreciated!  

I am trying to input two SAS datasets (parameters "indata1" and "indata2") and then I am trying to create two SAS datasets (parameters "outdata1" and "outdata2") with using macro. Below are the steps that I am trying to accomplish in order to have a correct output information in my two output datasets:
 
1.  I need to create SAS macro MAINMACRO with three parameters - input dataset ($indata1" and "$indata2"), output dataset ("$outdata1" and "$outdata2"), and type ("typea" and "typeb").

2. .      For every record in input dataset:
  2.1 Calculate the number of input record
  2.2 Assign value to variable "Var5"
      If car1=car1a and car2=car2a and car3=car3a
        then Var5 = 1
       Else If car1=car1a and car2=car2a
        then Var5 = 3
       Else If car1=car1a
         then Var5 = 4
      Else Var5 = 5
 
   2.3 Calculate the counters ("count1", "count3", "count4", and "count5") for each Var5 value (1,3,4,5) and total read_in and write_out.
   2.4. Output to output dataset.

3.      Then write “Assign Var5 value for &type” as title, total number of read_in from input files and total number of write_out to output files and the counters for various value of Var5 to process log file ("process.log").


 %macro MACRO1;
  data _null_;
   set $indata1 $indata2;
   length dsin $16. dsout $17.;

   dsin='outdata.&outdata1;
   dsout='outdata.&outdata2;

   call symput("inset",dsin);
   call symput("outset",dsout);
   call execute('%MACRO2(&inset, &outset)');
  run;
%mend MACRO1;

%macro MACRO2(dsin, dsout);
data var5data;
 set &dsin;
 
 if  car1||car2||car3 = 
     car1a||car2a||car3a  then do;
  Var5 = '1';
 end;
 
 else if car1||car2 = 
            car1a||car2a then do;
   Var5 = '3';
 end;
 
 else if car1 = 
            car1a then do;
   Var5 = '4';
 end;

 else do;
   Var5 = '5';
 end;

   output var5data;
run;

data counts (keep= Var1 Var2 Var3 Va4 Var5 Var6 Var7);
     length count1 count3 count4 count5 count_in count_out; 
     retain count1 count3 count4 count5 count_in count_out;
    count_in = count_in +1;   

 set var5data end=lastrec;

      if Var5 = '1' then count1+1;
      else if Var5 = '3' then count3+1;
      else if Var5 = '4' then count4+1;
      else if Var5 = '5' then count5+1;
      
     count_in= count_out+1; 
      output;
    end;

 if lastrec then
    do;
      file process.log mod;
      put 'Assign Var5 value for &type';
      put 'Total number of records with Var5 = 1: ' count1;
      put 'Total number of records with Var5 = 3: ' count3;
      put 'Total number of records with Var5 = 4: ' count4;
      put 'Total number of records with Var5 = 5: ' count5;
      put 'Total number of records read in:            ' count_in;
      put 'Total number of records read out:         ' count_out;
      put '*****************************************************';  
      put ' ';    
 end;
run;

/* create the permanent dataset */
data &dsout;
  set counts;
run;

%mend MACRO2;

/* Below macro calls the above macros according to value of TYPE */
%macro MAINMACRO;

 /* Run Program for TYPE */ 

%if "&type" = "typea " %then %do;
   %MACRO2("&indata1", "&outdata1", "&typea"); 
 %end;

 %else %if "&type" = "typeb " %then %do;
  %MACRO2("&indata2", "&outdata2", "&typeb"); 
 %end;

%mend MAINMACRO;
%MAINMACRO;

Open in new window


Thank you!
Avatar of Aloysius Low
Aloysius Low
Flag of Singapore image

I suppose you need help only to achieve point 1 above?

But I've got the following questions
1. What is MACRO1 supposed to achieve?
2. Why do you need to execute MACRO2 within MAINMACRO?
3. Where are the values for DSIN, DSOUT and TYPE coming from i.e. where is the assignment? Are they global variables?

I'm not making sense of your code from your description - something is not right.

Assuming the way you have written your macros is correctly, you need to change it to include 1 more parameter - TYPE - so that it can be passed in from MAINMACRO:
%MACRO MACRO2(DSIN, DSOUT, TYPE);

Then you need to allow macros to be passed into MAINMACRO can call MACRO2 from MAINMACRO as follow:
%MACRO MAINMACRO(DSIN, DSOUT, TYPE);
  %MACRO2(&DSIN, &DSOUT, &TYPE)
%MEND;
But doing this begs my second question above.

Hope you can clarify so that I can help you further.
Avatar of labradorchik

ASKER

Hello lowaloysius! Thank you very much for your comments!!

Here some background on the program. There is a control script, which has a control panel with selections #1 and #2
#1 is for files with typea
#2 is for files with typeb
   
So every time #1 is selected: this SAS program will be running with &indata1, &outdata1, &typea parameters
And every time #2 is selected: this SAS program will be running with &indata2, &outdata2, &typeb parameters

So every time this SAS program is called from #1 or #2 selection from the script it should choose correct parameters.  The script is already written with its own process and I am just trying to pass these parameters through MAINMACRO with all step 2 and step 3 processes for each input files (indata1 and indata2) that has MACRO2.

Answers to your questions:
3. Yes, all below parameters or logicals are global variables.
indata1, outdata1, typea
indata2, outdata2, typeb

1. I used MACRO1 to read parameters (these are actually SAS datasets) indata1 and indata2 and then create/output to outdata1 and outdata2 parameters (also SAS datatsets).

Note: I already have my two input files (indata1 and indata2) but I am still trying to create my output files (outdata1 and outdata2) so that's why I thought MACRO1 would be necessary before I start with step 2 and 3.

I am just trying to see how can I do all three steps in more efficient way for this program and get my two output files (outdata1 and outdata2) correctly.  

2. I am trying to execute MACRO2 within MAINMACRO because I thought this would be more efficient way since there are two selections in the script (#1 and #2) but I am not sure if my logic is correct. And since I can not test my code yet I am puzzled.

Please let me know if you have any additional questions and I will reply today.
Thank you in advance!
I thought about what I said before and I am not sure if all those parameters can be described as global variables, those parameters just passed from a bash script.

I am trying to rewrite my SAS code and see if this will makes any sense.
Please note: all 3 requirements steps are the same


%let typea=%sysget(type);

/*Get needed parameters from script */
%macro getparamtrs;
 data _null_;
   length type $4;
   type="&typea ";
   call symput ("type", type);
  run;
%mend getparamtrs;

%macro MACRO1(indata1, outdata1, typea);
data var5data;
 set "&indata1";
 
 if  car1||car2||car3 = 
     car1a||car2a||car3a  then do;
  Var5 = '1';
 end;
 
 else if car1||car2 = 
            car1a||car2a then do;
   Var5 = '3';
 end;
 
 else if car1 = 
            car1a then do;
   Var5 = '4';
 end;

 else do;
   Var5 = '5';
 end;

   output var5data;
run;

data counts (keep= Var1 Var2 Var3 Va4 Var5 Var6 Var7);
     length count1 count3 count4 count5 count_in count_out; 
     retain count1 count3 count4 count5 count_in count_out;
    count_in = count_in +1;   

 set var5data end=lastrec;

      if Var5 = '1' then count1+1;
      else if Var5 = '3' then count3+1;
      else if Var5 = '4' then count4+1;
      else if Var5 = '5' then count5+1;
      
     count_in= count_out+1; 
      output;
    end;

 if lastrec then
    do;
      file process.log mod;
      put 'Assign Var5 value for &type';
      put 'Total number of records with Var5 = 1: ' count1;
      put 'Total number of records with Var5 = 3: ' count3;
      put 'Total number of records with Var5 = 4: ' count4;
      put 'Total number of records with Var5 = 5: ' count5;
      put 'Total number of records read in:            ' count_in;
      put 'Total number of records read out:         ' count_out;
      put '*****************************************************';  
      put ' ';    
 end;
run;

 /* create the permanent dataset */
 data &outdata1;
   set counts;
 run;
%mend MACRO1;

%macro MACRO2(indata2, outdata2, typeb);
data var5data;
 set "&indata2";
 
 if  car1||car2||car3 = 
     car1a||car2a||car3a  then do;
  Var5 = '1';
 end;
 
 else if car1||car2 = 
            car1a||car2a then do;
   Var5 = '3';
 end;
 
 else if car1 = 
            car1a then do;
   Var5 = '4';
 end;

 else do;
   Var5 = '5';
 end;

   output var5data;
run;

data counts (keep= Var1 Var2 Var3 Va4 Var5 Var6 Var7);
     length count1 count3 count4 count5 count_in count_out; 
     retain count1 count3 count4 count5 count_in count_out;
    count_in = count_in +1;   

 set var5data end=lastrec;

      if Var5 = '1' then count1+1;
      else if Var5 = '3' then count3+1;
      else if Var5 = '4' then count4+1;
      else if Var5 = '5' then count5+1;
      
     count_in= count_out+1; 
      output;
    end;

 if lastrec then
    do;
      file process.log mod;
      put 'Assign Var5 value for &type';
      put 'Total number of records with Var5 = 1: ' count1;
      put 'Total number of records with Var5 = 3: ' count3;
      put 'Total number of records with Var5 = 4: ' count4;
      put 'Total number of records with Var5 = 5: ' count5;
      put 'Total number of records read in:            ' count_in;
      put 'Total number of records read out:         ' count_out;
      put '*****************************************************';  
      put ' ';    
 end;
run;

 /* create the permanent dataset */
 data &outdata2;
   set counts;
 run;
%mend MACRO2;

/* Below macro calls the above macros according to value of TYPE */
%macro MAINMACRO;
 %getparamtrs;

 /* Run Program for TYPE */ 
%if "&type" = "typea " %then %do;
 %let type = typea;
   %MACRO1("&indata1", "&outdata1", "&typea"); 
 %end;

 %else %if "&type" = "typeb " %then %do;
 %let type = typeb;
  %MACRO2("&indata2", "&outdata2", "&typeb"); 
 %end;

%mend MAINMACRO;
%MAINMACRO;

Open in new window


Please let me know if you know any easier or efficient way to accomplish all 3 requirements steps. Maybe all code can be placed in just one macro?
My opinion is that there's no need for MACRO1 and MACRO2. The codes are essentially the same, except for the variables, which is already being passed into the macro in the first place. Thus, there's really no need to duplicate the macros.

What you need to do is to write a macro with a generic code, which then also means that there's no need for a separate macro. MAINMACRO is sufficient, and it replaces MACRO1 and MACRO2. And to make it compliant with your point 1, it should have 3 parameters. I would write it as thus:

%macro MAINMACRO(indata, outdata, type);
data var5data;
 set &indata;
 
 if  car1||car2||car3 = 
     car1a||car2a||car3a  then do;
  Var5 = '1';
 end;
 
 else if car1||car2 = 
            car1a||car2a then do;
   Var5 = '3';
 end;
 
 else if car1 = 
            car1a then do;
   Var5 = '4';
 end;

 else do;
   Var5 = '5';
 end;

   output var5data;
run;

data counts (keep= Var1 Var2 Var3 Va4 Var5 Var6 Var7);
     length count1 count3 count4 count5 count_in count_out; 
     retain count1 count3 count4 count5 count_in count_out;
    count_in = count_in +1;   

 set var5data end=lastrec;

      if Var5 = '1' then count1+1;
      else if Var5 = '3' then count3+1;
      else if Var5 = '4' then count4+1;
      else if Var5 = '5' then count5+1;
      
     count_in= count_out+1; 
      output;
    end;

 if lastrec then
    do;
      file process.log mod;
      put "Assign Var5 value for &type";
      put 'Total number of records with Var5 = 1: ' count1;
      put 'Total number of records with Var5 = 3: ' count3;
      put 'Total number of records with Var5 = 4: ' count4;
      put 'Total number of records with Var5 = 5: ' count5;
      put 'Total number of records read in:            ' count_in;
      put 'Total number of records read out:         ' count_out;
      put '*****************************************************';  
      put ' ';    
 end;
run;

 /* create the permanent dataset */
 data &outdata;
   set counts;
 run;
%mend;

Open in new window

Note that I have removed quotation marks around indata1 (which I have changed it to indata to align with the macro parameters).
Also note that I have changed the quotation marks surrounding &type to that of double quotation marks instead of single quotation marks as SAS will treat them as literal values instead of variables.

One thing I have not tried before is the assignment of variables from batch scripts. I know it can work but I'm not sure how. So I'm assuming that the %sysget gets the job done, and going by what you have said, the parameters come in from a batch script, I'm taking it as all 3 values comes from the script. In which case, you just need to do:
%let type=%sysget(type);
%let indata=%sysget(indata);
%let outdata=%sysget(outdata);

Open in new window


And there is no further need for the macro GETPARAMTRS.

Your main execution code would thus be just
%MAINMACRO(&indata, &outdata, &type);

Open in new window

Thank you very much for your comments!!

I think having just one macro makes sense to me now just one thing. Since there are 6 in total parameters that are passed from the Unix bash script to this SAS program, so how would I implement all 6 parameters in just one macro?

6 parameters are:
indata1, outdata1, typea
and
indata2, outdata2, typeb

Note about these parameters: indata1 and indata2 are input SAS datasets and outdata1 and outdata2 are output SAS datasets.
typea and typeb are just variables for different type of selection based on the content of datasets.
Wait - you mean there's 6 parameters coming in?? I was under the impression there'd be one set of 3!

But in any case, you could call the macro twice? Like
%let type=%sysget(typea);
%let indata=%sysget(indata1);
%let outdata=%sysget(outdata1);
%MAINMACRO(&indata, &outdata, &type);

%let type=%sysget(typeb);
%let indata=%sysget(indata2);
%let outdata=%sysget(outdata2);
%MAINMACRO(&indata, &outdata, &type);

Open in new window

Thank you very much!

Great! I will have just one MAINMACRO but I will call it twice as below:

%let type=%sysget(typea);
%let indata=%sysget(indata1);
%let outdata=%sysget(outdata1);
%MAINMACRO(&indata, &outdata, &type);

%let type=%sysget(typeb);
%let indata=%sysget(indata2);
%let outdata=%sysget(outdata2);
%MAINMACRO(&indata, &outdata, &type);

%macro MAINMACRO(indata, outdata, type);
data var5data;
 set &indata;
 
 if  car1||car2||car3 = 
     car1a||car2a||car3a  then do;
  Var5 = '1';
 end;
 
 else if car1||car2 = 
            car1a||car2a then do;
   Var5 = '3';
 end;
 
 else if car1 = 
            car1a then do;
   Var5 = '4';
 end;

 else do;
   Var5 = '5';
 end;

   output var5data;
run;

data counts (keep= Var1 Var2 Var3 Va4 Var5 Var6 Var7);
     length count1 count3 count4 count5 count_in count_out; 
     retain count1 count3 count4 count5 count_in count_out;
    count_in = count_in +1;   

 set var5data end=lastrec;

      if Var5 = '1' then count1+1;
      else if Var5 = '3' then count3+1;
      else if Var5 = '4' then count4+1;
      else if Var5 = '5' then count5+1;
      
     count_in= count_out+1; 
      output;
    end;

 if lastrec then
    do;
      file process.log mod;
      put "Assign Var5 value for &type";
      put 'Total number of records with Var5 = 1: ' count1;
      put 'Total number of records with Var5 = 3: ' count3;
      put 'Total number of records with Var5 = 4: ' count4;
      put 'Total number of records with Var5 = 5: ' count5;
      put 'Total number of records read in:            ' count_in;
      put 'Total number of records read out:         ' count_out;
      put '*****************************************************';  
      put ' ';    
 end;
run;

 /* create the permanent dataset */
 data &outdata;
   set counts;
 run;
%mend;

Open in new window


I will run above code this upcoming Monday and let you know how it went.

One more question: could you please see if the logic of count_in and count_out are correct? In this program I am trying to calculate counters for "count1, count3, count4, and count5 for each Var5 value and total count_in and count_out for each of two output datasets.

Thank you!
ASKER CERTIFIED SOLUTION
Avatar of Aloysius Low
Aloysius Low
Flag of Singapore image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Wow  
Thank you very much for all your comments!!
Yes, you are correct! It should be
count_out = count_out + 1;
Although, both count_in and count_out should be the same in this scenario but I still would like to count both counts separately.

I don't think I have ever wrote this kind of counts process in just one data step but I think now I see what you mean. This really can be very efficient since both of my input files (indata1 and indata2)  have data with running over 2 hours. I am also amazed that I can just use one macro to accomplish all steps for this program!

I added your suggestions in the code below but I am still not sure if count_out = count_out + 1; will work correctly?

%macro MAINMACRO(indata, outdata, type);
data &output;
 set &indata end=lastrec;

    if _N_ = 1 then count_in = 1; 
      else count_in = count_in + 1;

 if  car1||car2||car3 = 
     car1a||car2a||car3a  then do;
  Var5 = '1';
   if _N_ = 1 then count1 = 1; 
      else count1 = count1 + 1;
 end;
 
 else if car1||car2 = 
            car1a||car2a then do;
   Var5 = '3';
   if _N_ = 1 then count3 = 1; 
      else count3 = count3 + 1;
 end;
 
 else if car1 = 
            car1a then do;
   Var5 = '4';
   if _N_ = 1 then count4 = 1; 
      else count4 = count4 + 1;
 end;

 else do;
   Var5 = '5';
    if _N_ = 1 then count5 = 1; 
      else count5 = count5 + 1;
end;

   count_out = count_out + 1;

 if lastrec then
    do;
      file process.log mod;
      put "Assign Var5 value for &type";
      put 'Total number of records with Var5 = 1: ' count1;
      put 'Total number of records with Var5 = 3: ' count3;
      put 'Total number of records with Var5 = 4: ' count4;
      put 'Total number of records with Var5 = 5: ' count5;
      put 'Total number of records read in:            ' count_in;
      put 'Total number of records read out:         ' count_out;
      put '*****************************************************';  
      put ' ';    
 end;
run;

Open in new window

not exactly correct..

_N_ = 1 means first record.. u can't possibly have Var5 = 1, Var5 = 3, Var5 = 4 and Var5 = 5 all on the same first record right?

it should look like:
if _N_ = 1 then do;
  count_in = 0;
  count1 = 0;
  count3 = 0;
  count4 = 0;
  count5 = 0;
  count_out = 0;
end;

Open in new window

This will initialize all variables to 0.

Then subsequently, you can do count_in = count_in + 1; and count_out = count_out + 1;

And don't forget to include your retain statement (hint: retain count_in count_out count1 count3 count4 count5;) or your counts will not be correct.

And I suppose you forgot to include the %mend in your code above, but actually have it in your actual code?

Otherwise, it *should* be OK.
Thank you, lowaloysius!
You are correct, I forgot to initialize all variables to 0.  Would I need to include the length statement as well before the retain statement and define the number from 3 to 8 for the length ?

%let type=%sysget(typea);
%let indata=%sysget(indata1);
%let outdata=%sysget(outdata1);
%MAINMACRO(&indata, &outdata, &type);

%let type=%sysget(typeb);
%let indata=%sysget(indata2);
%let outdata=%sysget(outdata2);
%MAINMACRO(&indata, &outdata, &type);

%macro MAINMACRO(indata, outdata, type);
data &output;
  retain count1 count3 count4 count5 count_in count_out;

 set &indata end=lastrec;

   if _N_ = 1 then do;
      count_in = 0;
      count1 = 0;
      count3 = 0;
      count4 = 0;
      count5 = 0;
      count_out = 0;
   end;

count_in = count_in + 1;

 if  car1||car2||car3 = 
     car1a||car2a||car3a  then do;
  Var5 = '1'; 
      count1 = count1 + 1;
 end;
 
 else if car1||car2 = 
            car1a||car2a then do;
   Var5 = '3';
      count3 = count3 + 1;
 end;
 
 else if car1 = 
            car1a then do;
   Var5 = '4';
      count4 = count4 + 1;
 end;

 else do;
   Var5 = '5';
      count5 = count5 + 1;
 end;

      count_out = count_out + 1;

 if lastrec then
    do;
      file process.log mod;
      put "Assign Var5 value for &type";
      put 'Total number of records with Var5 = 1: ' count1;
      put 'Total number of records with Var5 = 3: ' count3;
      put 'Total number of records with Var5 = 4: ' count4;
      put 'Total number of records with Var5 = 5: ' count5;
      put 'Total number of records read in:            ' count_in;
      put 'Total number of records read out:         ' count_out;
      put '*****************************************************';  
      put ' ';    
 end;
run;
%mend;

Open in new window


Is there way to write just one if-else-end statement for counts 1, 3, 4 and 5?
length statement is optional. if it's there, SAS will use what you defined; if it isn't, SAS will default the length to 8.

i don't see any other way about writing the if-else statements - that's how i'd do it too!
Great! Thank you so much!!
I will test above code this Monday and let you know what errors if any I will get. I just hope code works well.

Have a great weekend!
I think my macro is not defined correctly or my macro logic is not correct.  
I have run below SAS code multiple times today and keep getting the following Warning in my sas.log file:
The argument to macro function %SYSGET is not defined as a system variable.
%MAINMACRO("&indata", "&outdata", "&type");
   
following by an another Warning:
Apparent invocation of macro MAINMACRO not resolved.

and then Error:
% in %MAINMACRO - Statement is not valid or it is used out of proper order.

So,  when I am running the below script, which invokes below SAS code, I am not outputting my two output SAS datasets (OUTDATA1 and OUTDATA2) and none of counters are written to the process.log when MAINMACRO macro is running. Actually, I am not even sure if macro runs at all. Maybe SAS code stops processing before even it gets to MAINMACRO macro?

My Unix bash script
#!/bin/bash
export INDATA1=/maindir/mydir/myindata1.sas7bdat 
export OUTDATA1=/maindir/mydir/myoutdata1.sas7bdat 
export INDATA2=/maindir/mydir/myindata2.sas7bdat 
export OUTDATA2=/maindir/mydir/myoutdata2.sas7bdat 
export type="typea " 
export type="typeb "

$sas mysascode.sas

Open in new window


My SAS code
%let type=%sysget(typea);
%let indata=%sysget(INDATA1);
%let outdata=%sysget(OUTDATA1);
%MAINMACRO("&indata", "&outdata", "&type");

%let type=%sysget(typeb);
%let indata=%sysget(INDATA2);
%let outdata=%sysget(OUTDATA2);
%MAINMACRO("&indata", "&outdata", "&type");

%macro MAINMACRO(indata, outdata, type);
data "&oudata";
  retain count1 count3 count4 count5 count_in count_out;

 set "&indata" end=lastrec;

   if _N_ = 1 then do;
      count_in = 0;
      count1 = 0;
      count3 = 0;
      count4 = 0;
      count5 = 0;
      count_out = 0;
   end;

count_in = count_in + 1;

 if  car1||car2||car3 = 
     car1a||car2a||car3a  then do;
  Var5 = '1'; 
      count1 = count1 + 1;
 end;
 
 else if car1||car2 = 
            car1a||car2a then do;
   Var5 = '3';
      count3 = count3 + 1;
 end;
 
 else if car1 = 
            car1a then do;
   Var5 = '4';
      count4 = count4 + 1;
 end;

 else do;
   Var5 = '5';
      count5 = count5 + 1;
 end;

      count_out = count_out + 1;

 if lastrec then
    do;
      file dir.process.log mod;
      put "Assign Var5 value for &type";
      put 'Total number of records with Var5 = 1: ' count1;
      put 'Total number of records with Var5 = 3: ' count3;
      put 'Total number of records with Var5 = 4: ' count4;
      put 'Total number of records with Var5 = 5: ' count5;
      put 'Total number of records read in:            ' count_in;
      put 'Total number of records read out:         ' count_out;
      put '*****************************************************';  
      put ' ';    
 end;
run;
%mend;

Open in new window


I tried different ways of using below line of code with no quotes, single quotes, and double quotes as below but I still receive below Warming each time:
The argument to macro function %SYSGET is not defined as a system variable.

%MAINMACRO("&indata", "&outdata", "&type");

Open in new window


Please let me know if you have any comments or suggestions. I really can not figure out what I am defining incorrectly. I thought I defined variables correctly in the Unix shell script.
I had to create a second macro, so all parameters would go through MAINMACRO macro. Still in testing but I am already getting my two output files and process.log with all counts.  

Thank you very much,  lowaloysius!
Your comments and suggestions really helped!!

%macro MAINMACRO(ind, outd, tp);
data "&oud";
  retain count1 count3 count4 count5 count_in count_out;

 set "&ind" end=lastrec;

   if _N_ = 1 then do;
      count_in = 0;
      count1 = 0;
      count3 = 0;
      count4 = 0;
      count5 = 0;
      count_out = 0;
   end;

count_in = count_in + 1;

 if  car1||car2||car3 = 
     car1a||car2a||car3a  then do;
  Var5 = '1'; 
      count1 = count1 + 1;
 end;
 
 else if car1||car2 = 
            car1a||car2a then do;
   Var5 = '3';
      count3 = count3 + 1;
 end;
 
 else if car1 = 
            car1a then do;
   Var5 = '4';
      count4 = count4 + 1;
 end;

 else do;
   Var5 = '5';
      count5 = count5 + 1;
 end;

      count_out = count_out + 1;

 if lastrec then
    do;
      file dir.process.log mod;
      put 'Assign Var5 value for ' "&tp";
      put 'Total number of records with Var5 = 1: ' count1;
      put 'Total number of records with Var5 = 3: ' count3;
      put 'Total number of records with Var5 = 4: ' count4;
      put 'Total number of records with Var5 = 5: ' count5;
      put 'Total number of records read in:            ' count_in;
      put 'Total number of records read out:         ' count_out;
      put '*****************************************************';  
      put ' ';    
 end;
run;
%mend;

%macro final;
%let type=%sysget(type1);
%if "&type" = "typea" %then %do;
%let indata=%sysget(INDATA1);
%let outdata=%sysget(OUTDATA1);
%MAINMACRO("&indata", "&outdata", "&type");
%end;

%let type=%sysget(type1);
%if "&type" = "typeb" %then %do;
%let indata=%sysget(INDATA2);
%let outdata=%sysget(OUTDATA2);
%MAINMACRO("&indata", "&outdata", "&type");
%end;

%mend;
%final;

Open in new window

glad to be of help, though i'm not able to help much with the last bit regarding passing of input parameters from ksh as i've never done this before.

on a separate note, i still think that there's no need to duplicate the assignment of variables although it might be necessary to have another wrapping macro..

in theory, the following should work as fine..
%macro final;
%let type=%sysget(type1);
%let indata=%sysget(INDATA1);
%let outdata=%sysget(OUTDATA1);
%MAINMACRO("&indata", "&outdata", "&type");

%let type=%sysget(type1);
%let indata=%sysget(INDATA2);
%let outdata=%sysget(OUTDATA2);
%MAINMACRO("&indata", "&outdata", "&type");
%mend;

Open in new window


Also, i'm not sure about the usage of double quotation marks surrounding &indata, &outdata and &type, both in the macro call as well as within MAINMACRO itself.. but if it works, that's great :)