BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
SasStatistics
Pyrite | Level 9

I am creating a macro, and would like to validate a parameter, i.e. to check if a list of values is contained in another list of values. If this is NOT the case, I will put an error message to the user.

The code I was trying:

%macro ValidateCountries(country, countrylist) /minoperator mindelimiter=' ';
	%if %upcase(&country.) in (USA UK ENG) and %upcase(&countrylist.) in (USA UK ENG) %then %do;
		%local answer;
		%if &country. in &countrylist. %then %do; 
		  %let answer= 1; 
		%end; 
		%else %do;
		  %let answer= 0; 
		%end;
		&answer; 
	%end;

	%else %do; 
		%put Error: country should be one of: USA UK ENG. 
					countrylist may only contain some of USA UK ENG. ;
	%end; 	
%mend; 

I believe the problem is in this code: 

 

 

and %upcase(&countrylist.) in (USA UK ENG) %then %do;

Thanks for the help. 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

When you are done compare to this:

 

Spoiler

 

%macro ValidateCountries(country, countrylist) /minoperator mindelimiter=' ';
  %local answer i next list;
  %let list=%qupcase(USA UK ENG);
  %let answer=1;
  %if not (%qupcase(&country) in &list) %then %do;
    %let answer=0;
    %put ERROR: COUNTRY value "&country" is not in &=list;
  %end;
  %do i=1 %to %sysfunc(countw(&countrylist));
    %let next=%qscan(&countrylist,&i,%str( ));
    %if not (%qupcase(&next) in &list) %then %do;
       %let answer=0;
       %put ERROR: COUNTRYLIST value "&next" is not in &=list;
    %end;
  %end;
&answer
%mend; 

 

 

Results:

283   %put %ValidateCountries(uk,usa uk);
1
284   %put %validateCountries(usa uk ,france usa uk);
ERROR: COUNTRY value "usa uk" is not in LIST=USA UK ENG
ERROR: COUNTRYLIST value "france" is not in LIST=USA UK ENG
0

View solution in original post

15 REPLIES 15
PaigeMiller
Diamond | Level 26

@SasStatistics wrote:

I believe the problem is in this code: 

 

 

and %upcase(&countrylist.) in (USA UK ENG) %then %do;

Thanks for the help. 

 


It's not  clear what the purpose of this part of the code is. But it is not a syntax error.

--
Paige Miller
SasStatistics
Pyrite | Level 9

Thanks @PaigeMiller . I hope this example makes it more clear: 

%let MyRes1 = %ValidateCountries(USA, USA UK); * Program goes to the %else %do statement, but USA and UK is in the list of USA, UK and ENG so I would like it to return the answer 1. ;
PaigeMiller
Diamond | Level 26
%macro ValidateCountries(country, countrylist) /minoperator mindelimiter=' ';
	%if %upcase(&country.) in (&countrylist) %then 1;
    %else 0;
%mend; 

%put ANSWER %validateCountries(uk,USA UK ENG);
%put ANSWER2 %validateCountries(turkey,USA UK ENG);

Would this work for you?

--
Paige Miller
SasStatistics
Pyrite | Level 9
Unfortunately not, I must beforehand validate that countrylist is a list only containing the combinations of (USA, UK, ENG). For example (USA and UK) would be valid as would USA alone.

But USA, UK, GER would not be valid and should return an error.
PaigeMiller
Diamond | Level 26

@SasStatistics wrote:
Unfortunately not, I must beforehand validate that countrylist is a list only containing the combinations of (USA, UK, ENG). For example (USA and UK) would be valid as would USA alone.

But USA, UK, GER would not be valid and should return an error.

Why then don't you just hardcode the country list instead of making a variable that could have values you don't want?

 

%macro ValidateCountries(country) /minoperator mindelimiter=' ';
	%if %upcase(&country.) in (USA UK ENG) %then 1;
    %else 0;
%mend; 

%put ANSWER %validateCountries(uk);
%put ANSWER2 %validateCountries(turkey);
--
Paige Miller
SasStatistics
Pyrite | Level 9
Since different scripts require different cases.

In one script i want to check that the country list is USA or UK and make sure the user does no misstake such as USA, UK and GER.
In another script I want to check that the country list is UK, ENG and make sure the user does no misstake such as UK, ENG and AUS.

Any ideas?

PaigeMiller
Diamond | Level 26

Going back to your original code which has this:

 

%if %upcase(&country.) in (USA UK ENG) and %upcase(&countrylist.) in (USA UK ENG) %then %do;

You need to check &countrylist is valid in one %IF block, and check if the &Country is contained in &countrylist in a different %IF block.

To check if &countrylist is valid, you would need to specifically loop through each element of &countrylist.

--
Paige Miller
SasStatistics
Pyrite | Level 9
Problem is, both if conditions must fulfilled at the same time. This logic only looks at one at the time?
PaigeMiller
Diamond | Level 26

@SasStatistics wrote:
Problem is, both if conditions must fulfilled at the same time. This logic only looks at one at the time?

Sequential testing of each condition gets you to the same end result. If the countrylist is wrong, you get notified. If the country is not in the countrylist, you get notified.

--
Paige Miller
Tom
Super User Tom
Super User

Are you just trying to check if ONE value is in a list of possible values?  Or are you trying to check if all of a list of values in in another list?

 

Set the result to GOOD and then loop over the list of words to check and set it BAD for any failure.

Example:

%macro ValidateCountries(country, countrylist) /minoperator mindelimiter=' ';
  %local answer i next;
  %let answer=1;
  %do i=1 %to %sysfunc(countw(&country));
    %let next=%qscan(&country,&i,%str( ));
    %if not (%qupcase(&next) in %qupcase(&countrylist)) %then %do;
       %let answer=0;
       %put ERROR: Value &next is not in list: &countrylist;
    %end;
  %end;
  %if not &answer %then %put ERROR: Invalid list of countries: &=country;
&answer
%mend; 

%put %ValidateCountries(uk,usa uk);
%put %validateCountries(usa uk france,usa uk);

 

 

SasStatistics
Pyrite | Level 9

The purpose of the validation code: 

%if %upcase(&country.) in (USA UK ENG) and %upcase(&countrylist.) in (USA UK ENG) %then %do;

is to: 

1. &country may only be ONE of the value USA, UK, ENG. For example: country = USA UK is invalid since it is two values, it may only be one. Country = USA is valid. Country = GER is invalid. 
2. Countrylist is a "list" and may only contain USA, UK, ENG. For example: countrylist  = USA UK is valid. Countrylist = USA UK ENG is valid. Countrylist = USA GER is invalid. Countrylist = USA USA UK is valid although it is bad programming (or perhaps a misstake).

 

Thanks @Tom and hope it is clear. 

Tom
Super User Tom
Super User

So modify my version to do what you want.

If you have trouble post your code so we can see how to help you.

SasStatistics
Pyrite | Level 9

My try which I know is wrong, but I have trouble implementing the check for two conditions when one of the condition involves looping. 


/*Validation 1: &country may only be ONE of the value USA, UK, ENG.*/

/*Validation 2: Countrylist is a "list" and may only contain USA, UK, ENG. For example: countrylist  = USA UK is valid. 
Countrylist = USA UK ENG is valid. Countrylist = USA GER is invalid. 
Countrylist = USA USA UK is valid although it is bad programming (or perhaps a misstake).*/

/* These two validation conditions must both be fullfilled at the same time*/

%macro ValidateCountries(country, countrylist) /minoperator mindelimiter=' ';
	%if %upcase(&country.) in (USA UK ENG) 
		AND   /* Have trouble how to check that all the looping cases are true in an AND statement? */
			%do i=1 %to %sysfunc(countw(&countrylist.));
				%let next=%qscan(&countrylist.,&i,%str( ));
				%if (%qupcase(&next) in %qupcase(&countrylist)) %then %do;
	    	%end;

	%then %do;
		%local answer;
		%if &country. in &countrylist. %then %do; 
		  %let answer= 1; 
		%end; 
		%else %do;
		  %let answer= 0; 
		%end;
		&answer; 
	%end;


	%else %do; 
		%put Error: country should be one of: USA UK ENG. 
					countrylist may only contain some of USA UK ENG. ;
	%end; 	


%mend; 
Tom
Super User Tom
Super User

When you are done compare to this:

 

Spoiler

 

%macro ValidateCountries(country, countrylist) /minoperator mindelimiter=' ';
  %local answer i next list;
  %let list=%qupcase(USA UK ENG);
  %let answer=1;
  %if not (%qupcase(&country) in &list) %then %do;
    %let answer=0;
    %put ERROR: COUNTRY value "&country" is not in &=list;
  %end;
  %do i=1 %to %sysfunc(countw(&countrylist));
    %let next=%qscan(&countrylist,&i,%str( ));
    %if not (%qupcase(&next) in &list) %then %do;
       %let answer=0;
       %put ERROR: COUNTRYLIST value "&next" is not in &=list;
    %end;
  %end;
&answer
%mend; 

 

 

Results:

283   %put %ValidateCountries(uk,usa uk);
1
284   %put %validateCountries(usa uk ,france usa uk);
ERROR: COUNTRY value "usa uk" is not in LIST=USA UK ENG
ERROR: COUNTRYLIST value "france" is not in LIST=USA UK ENG
0

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 15 replies
  • 1575 views
  • 2 likes
  • 3 in conversation