SAS Programming

DATA Step, Macro, Functions and more
BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Squibbles
Fluorite | Level 6

Hi All, 

Hopefully, someone can help me, I've been searching the forums all day for a solution...

I am trying to change a %LET variable within a maco's DO loop, using %eval. However i only want the %eval line to work under a certain condition, unfortunately, the %eval statement is always operating. I've tried to use %symput but I can't get that to work. 

I've pasted an extract of code below. The issues is the variable j, which is used as an index variable. Essentially i have two types variables: Building_Claim_Cause_0 and Contents_Claim_Cause_0   (both of which go up to 4, i.e Contents_Claim_Cause_1, Contents_Claim_Cause_2...)

I need to combine these two variables into one variable (HOMELOSSTx) where the buildings and contents claim variables. i.e if there is a value in Building_Claim_Cause_0, then let HOMELOSST0 equal it, and if there is a value in Contents_Claim_Cause_0  as well let HOMELOSST1 equal it. I am using j to as the index value for HOMELOSS and k as the index value between buildings and contents claims, and i as the index value between 0 to 4 for the buildings/contents claims).

 

 

 

%MACRO CLAIMS(MAXNUM);
	/*INTIALISE CLAIMS VARIABLES*/
	
	%LET i = 0;   	/*CYCLE THROUGH THE Specific_ItemX VARIABLE. IF THERE IS AN ITEM THEN SPECIFIED ITEM COVER HAS BEEN SELECTED*/
	%LET j = 0; 	/*CLAIM FOUND COUNT - WE ARE COLLAPSING THE BUILDING CLAIM VARIABLES AND CONTENTS CLAIM VARIABLES INTO ONE ONE CLAIM VARIABLE*/
	
	%DO %UNTIL (&i. = &MAXNUM.*2+2);	/*we have 5 potential bld or cnt claims. count starts at 0 hence maxnum is 4*/
		FORMAT CLAIMCOVE&i. FMT_CLAIMCOVER.;
		FORMAT HOMELOSST&i. FMT_HOMELOSSTY.;
		FORMAT HMELOSOTT&i. FMT_HMELOSOTTY.;
		FORMAT DATEOFLOS&i. DDMMYY8.;
		FORMAT PROPCLAIM&i. FMT_PROPCLAIMX.;
		FORMAT AMTPAIDOS&i 	best32.;

		CLAIMCOVE&i. = 0; 		/*Was it a contents or building incident?*/
		HOMELOSST&i. = 0; 		/*What type of incident was it?*/
		HMELOSOTT&i. = 0; 		/*Please specify:*/
		DATEOFLOS&i. = .; 		/*When did the incident occur?*/			 
		PROPCLAIM&i. = 999;	/*Did you make a claim?*/
		AMTPAIDOS&i. = .;		/*How much was paid out (or you have received so far) for this claim?*/

		%LET i = %eval(&i.+1);
	%END;
	
	%LET i = 0;/*reset counter*/
	
	%DO %UNTIL (&i. = &MAXNUM. +1);
		%LET k = 0;/*reset claim type counter (bld or cts)*/
		IF CLAIMLAST5 = 1 THEN DO;
			%DO k = 1 %TO 2;
			
				%IF &k. = 1 %THEN %DO; 
					
					%LET QZ_CLMType = 	Building_Claim_Cause_		;
					%LET QZ_CLMDate = 	Building_Claim_QuteDate_	;
					%LET QZ_CLMLoc	=	Building_Claim_Location_ 	;
					%LET QZ_CLMAmt	=	Building_Claim_Amount_ 		; 
				%END;
				%ELSE %DO;
					
					%LET QZ_CLMType = 	Contents_Claim_Cause_		;
					%LET QZ_CLMDate = 	Contents_Claim_QuteDate_	;
					%LET QZ_CLMLoc	=	Contents_Claim_Location_ 	;
					%LET QZ_CLMAmt	=	Contents_Claim_Amount_ 		;
				%END;
				
				SELECT (&QZ_CLMType.&i.);
					WHEN ("", "N") DO;
					END; /* DO NOTHING*/
					OTHERWISE DO;
						IF &k. = 1 THEN DO; 
							CLAIMCOVE&j. = 1; 		/*Was it a contents or building incident?*/
						END;
						ELSE DO;
							CLAIMCOVE&j. = 2; 		/*Was it a contents or building incident?*/
						END;
						
						SELECT (&QZ_CLMType.&i.);  
								
							WHEN ("Flood Damage") 			HOMELOSST&j. = 1; 	/*Flood*/
							OTHERWISE 						HOMELOSST&j. = 9; 												/*Other*/
						END;
						
						IF HOMELOSST&j. < 9 THEN HMELOSOTT&j. = 0;
						ELSE DO;
							SELECT (&QZ_CLMType.&i.);
								WHEN ("Additional Expenses") 	HMELOSOTT&j. = 1; 			/*Additional Expenses*/							
								OTHERWISE 						HMELOSOTT&j. = 99;
	
							END; /*HMELOSOTTY - CLAIM CAUSE CODES*/							
						END;  
						
						DATEOFLOS&j. = &QZ_CLMDate.&i.; 	/*When did the incident occur?*/			 
						SELECT (&QZ_CLMLoc.&i.);
							WHEN ("N") PROPCLAIM&j. = 3;
							WHEN ("Y") PROPCLAIM&j. = 1;
							OTHERWISE PROPCLAIM&j. 	= 99;
						END;											
						AMTPAIDOS&j. = &QZ_CLMAmt.&i.;		/*How much was paid out (or you have received so far) for this claim?*/
						%LET j = %eval(&j.+ 1);				/*This is the index value for claim variable we are using.*/
					END; /*OTHERWISE DO;*/
				END; /*SELECT (&QZ_CLMType.&i.);*/
																		
			%END; /*LOOP ACROSS Building_Claim_QuteDate_&i. and  AND Contents_Claim_Cause_&i.*/
																	
		END; /*IF CLAIMLAST5 = 1 THEN DO;*/
		%LET i = %eval(&i.+ 1);		
	%END;
%MEND; /*CLAIMS*/

data toto ;
set RAWDATA.QZDATA (KEEP = Had_Any_Building_Claims Had_Any_Contents_Claims
							Building_Claim:	Contents_Claim:
					/*OBS = 12*/);
	
/*Have you, or anyone living at your property had any incidents or made a home insurance claims in the last five years? (in this or another property)*/
	IF Had_Any_Building_Claims = "" OR Had_Any_Contents_Claims = "" THEN CLAIMLAST5 = 0;
	ELSE IF Had_Any_Building_Claims = "N" AND Had_Any_Contents_Claims = "N" THEN CLAIMLAST5 = 0;
	ELSE CLAIMLAST5 = 1;	
	
	%CLAIMS(MAXNUM = 4);  
RUN;

 

1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

You're making a fundamental mistake in the way that you treat macro language.  Macro language does not process your data.  Instead, it is supposed to generate SAS language statements.  Those are what process your data.  To give you an example, here is a rewrite of the beginning of your code:

 

%macro claims (maxnum);

   %local j;

   %let j = %eval(2 * &maxnum + 2);

   format claimcove1 - claimcove&j fmt_claimcover.;

   format homelosst1 - homelosst&j fmt_homelossty.;

   ...

   format amtpaidos1 - amtpaidos&j  best32.;

 

   array claimcove {&j};

   array homelosst {&j};

   ...

   array propclaim {&j};

   array amtpaidos {&j};

 

   do _i_ = 1 to &j;

      claimcove{_i_} = 0;

      homelosst {_i_} = 0;

      ...

      propclaim{_i_} = 999;

   end;

 

 

You need to use macro language to generate SAS language statements, and to do that you need to have a firm idea of what the SAS statements should look like.  That part becomes a little cloudy in the second half of your macro.

View solution in original post

3 REPLIES 3
ballardw
Super User

@Squibbles wrote:

Hi All, 

 

 Essentially i have two types variables: Building_Claim_Cause_0 and Contents_Claim_Cause_0   (both of which go up to 4, i.e Contents_Claim_Cause_1, Contents_Claim_Cause_2...)

I need to combine these two variables into one variable (HOMELOSSTx) where the buildings and contents claim variables. i.e if there is a value in Building_Claim_Cause_0, then let HOMELOSST0 equal it, and if there is a value in Contents_Claim_Cause_0  as well let HOMELOSST1 equal it. I am using j to as the index value for HOMELOSS and k as the index value between buildings and contents claims, and i as the index value between 0 to 4 for the buildings/contents claims).

 


It may help to provide a little example data start and end. But it looks like a few arrays would handle this without any macro logic needed at all, at least for that look at pairs(?) of values and assign a third.

Astounding
PROC Star

You're making a fundamental mistake in the way that you treat macro language.  Macro language does not process your data.  Instead, it is supposed to generate SAS language statements.  Those are what process your data.  To give you an example, here is a rewrite of the beginning of your code:

 

%macro claims (maxnum);

   %local j;

   %let j = %eval(2 * &maxnum + 2);

   format claimcove1 - claimcove&j fmt_claimcover.;

   format homelosst1 - homelosst&j fmt_homelossty.;

   ...

   format amtpaidos1 - amtpaidos&j  best32.;

 

   array claimcove {&j};

   array homelosst {&j};

   ...

   array propclaim {&j};

   array amtpaidos {&j};

 

   do _i_ = 1 to &j;

      claimcove{_i_} = 0;

      homelosst {_i_} = 0;

      ...

      propclaim{_i_} = 999;

   end;

 

 

You need to use macro language to generate SAS language statements, and to do that you need to have a firm idea of what the SAS statements should look like.  That part becomes a little cloudy in the second half of your macro.

Squibbles
Fluorite | Level 6

ok thanks both. 

i'll look into arrays & rethink the structure. 

sas-innovate-white.png

Special offer for SAS Communities members

Save $250 on SAS Innovate and get a free advance copy of the new SAS For Dummies book! Use the code "SASforDummies" to register. Don't miss out, May 6-9, in Orlando, Florida.

 

View the full agenda.

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 3 replies
  • 3673 views
  • 3 likes
  • 3 in conversation