I need to create a prompt. Actually I created another two with no problem, but one of the variable is different while I was creating prompt. I needed to do macro with that as below:
%macro param_list;
%global
list_selected
;
%let i=1;
%let p_lst_tmp = %scan(&VID,&i);
%do %while(&p_lst_tmp ne);
%let list_selected = &list_selected "%scan(&VID,&i)";
%let i = %eval(&i+1);
%let p_lst_tmp = %scan(&VID,&i);
%end;
%put list_selected = &list_selected;
%mend;
Then in the code I created
PROC SQL;
CREATE TABLE Student_Pre AS
SELECT t1.personid LABEL="PIDM" AS PIDM,
t1.V_ID as VID,
t1.FIRST_NAME
FROM ENROLL.Student_Dim t1
WHERE t1.v_id = &list_selected
ORDER BY t1.personid;
QUIT;
But this code gives an error, ERROR 22-322: Syntax error, expecting one of the following: ;, !, !!, &, (, , *, +, -, '.', /, <, <=, <>, =, >, >=, AND, EQ, EQT, EXCEPT, GE, GET, GROUP, GT, GTT, HAVING, INTERSECT, LE, LET,
LT, LTT, NE, NET, NOT, OR, ORDER, OUTER, UNION, ^, ^=, |, ||, ~, ~=.
ERROR 76-322: Syntax error, statement will be ignored.
How should I change the code?
Related
I'd like to loop through a comma separated macro variable like the following, which I also use in the where condition of a proc sql statement:
%let example = (1, 2, 3, 4)
I found the following syntax which almost covers my case:
%macro px;
%let value = 1 2 3 4;
%local i next_value;
%let i=1;
%do %while (%scan(&value, &i) ne );
%let next_value = %scan(&value, &i);
%put&=next_value;
%let i = %eval(&i + 1);
%end;
%mend;
%px;
Unforunately, I don't know how to modify that syntax such that it works for my example. If I add commas to the 'value' variable I get the error "Macro function %SCAN has too many arguments" which doesn't make sense to me.
User str% to wrap string. And you can simplify code:
%macro px;
%let value = (1, 2, 3, 4);
%let value = %sysfunc(compress(&value, %str(%(%))));
%let value = %str(%bquote(&value));
%do mvI=1 %to %sysfunc(countw(&value, %str(,)));
%let next_value = %scan(&value, &mvI, %str(,));
%put&=next_value;
%end;
%mend;
%px;
You need to protect the comma so that %SCAN() does not see it as separator between the arguments. If you used the actual EXAMPLE value your existing code would work because the parentheses enclosing the comma separated list of numbers would do that.
Note that since you didn't tell %SCAN() what delimiter characters to use the parentheses commas and spaces are all considered delimiters.
If your value does not have the parentheses around it then you can protect the comma with macro quoting.
%let value=%quote(&value);
If you pass the value to the macro as an actual parameter, then the onus of ensuring the commas are protected will fall on the code that calls the macro. Also there is no need write code to increment the loop counter. The %DO loop supports that, just use the COUNTW() function to determine the upper bound.
%macro px(list);
%local i next_value;
%do i=1 %to %sysfunc(countw(&list));
%let next_value = %scan(&list, &i);
%put &=i &=next_value;
%end;
%mend;
%let example = (1, 2, 3, 4);
%px( &example );
%px( %str(1,2,3,4) );
I have the following code in a macro:
...
data HE2update (drop=sum_values n_values);
set dst_end_update;
by short_date HE;
%if HE=2 or 3 %then %do;
sum_values+value;
n_values+1;
%if HE=2 %then delete;
%else %if HE=3 %then %do;
value = round(sum_values/n_values);
HE=2;
%end;
%end;
%if HE>3 %then HE=HE-1;
%else HE;
run;
I am getting the following Error: ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, -, /, <, <=, <>, =, >, ><, >=, AND, EQ, GE, GT, IN,
LE, LT, MAX, MIN, NE, NG, NL, NOTIN, OR, ^=, |, ||, ~=.
The error seems to be with the last if/then/else statement I don't see what I need to correct. Any help would be greatly appreciated.
The macro processor is used to generate code, not operate on data.
Your first %IF is testing whether the string HE is equal to 2 (which is false) and then OR ing the result with the number 3 (which is true) so the test is true which means these two statements are generated to include in your data step.
sum_values+value;
n_values+1;
The other two %IF tests in that %IF/%THEN/%DO/%END block are both false since the string HE does not equal either the digit 2 or the digit 3.
Then finally you test if the string HE is larger than the digit 3 which is TRUE since H is after 3 in the ASCII collating sequence. This means your program will generate the code
HE=HE-1
Notice that there is no closing semi-colon for that assignment statement. The semi-colon in the program marks the end of the %IF/%THEN statement.
So the code you generated is:
data HE2update (drop=sum_values n_values);
set dst_end_update;
by short_date HE;
sum_values+value;
n_values+1;
HE=HE-1 run;
That last assignment statement is not valid SAS syntax. Plus there is no RUN; to end the data step.
I don't think you need macro logic here at all.
data HE2update (drop=sum_values n_values);
set dst_end_update;
by short_date HE;
if HE in (2, 3) then do;
sum_values+value;
n_values+1;
if HE=2 then delete;
else if HE=3 then do;
value = round(sum_values/n_values);
HE=2;
end;
end;
if HE>3 then HE=HE-1;
run;
Try again. This code will not work. It is a stupid code but still do not work.
data work.colnames;
input cols $;
cards;
U1
B1
;
run;
data work.test;
input rp_U1 $ rp_B1 $;
cards;
col1 col2
;
run;
%macro maketest;
proc sql;
select cols
into :col separated by " "
from colnames;
quit;
%do i=1 %to 2;
%let c = %qscan(&col,&i);
%put rp_&c;
proc sql;
create table test&i as
select
rp_&c
from work.test;
quit;
%end;
%mend;
%maketest;
I do get this error:
ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, ',', -, '.', /, <, <=, <>, =, >, >=, ?, AND, AS,
CONTAINS, EQ, EQT, GE, GET, GT, GTT, LE, LET, LIKE, LT, LTT, NE, NET, OR, ^=, |, ||, ~=.
Which I find strange is if I try to get the columns without the rp_ this code works find. Also change
select
rp_&c
to
select
&c
The macro quoting you introduced by using %QSCAN() function instead of the %SCAN() function is probably causing trouble for the SAS parser.
In your code the macro variable C gets assigned the values of U1 and B1, respectively. But the values are macro quoted. So when the parser sees rp_&c it thinks that those are two separate tokens so it treats it like token rp_ followed by the token U1 instead of a single token of rp_U1.
You should not need to quote a string that will be part of a variable name, so you should change
%let c = %qscan(&col,&i);
to
%let c = %scan(&col,&i);
But if you do need to have the macro quoting then you can use the %unquote() function to remove it. So change
select rp_&c
to
select %unquote(rp_&c)
I have the following piece of code that works, but I'd like to know if anyone can come up with a better way of 'removing' the %nrquote. I have had to add a %SUBSTR function, which works, but I'm keen to know if there are any other suggestions, and if anyone can help explain why the code doesn't work without the %let statement within the mvar macro definition.
/* Automatically generated by DI Studio - cannot change */
%let _where_clause = %nrquote(name = %'Henry%');
%let _mac1 = %nrquote(lemk);
%let _variable = weight;
%let _input0 = sashelp.class;
/* End of auto-generated code */
options mprint;
%macro mvar;
%if &_where_clause ^= %then %do;
/* Re-assign the _where_clause variable to 'remove' %nrquote */
%let _where_clause = %substr(&_where_clause,1);
where &_where_clause
%end;
%mend mvar;
proc sql;
select &_variable into :&_mac1
from &_input0
%mvar
;
quit;
Without the %let statement, the code fails with this error:
NOTE: Line generated by the macro variable "_WHERE_CLAUSE".
1 name = 'Henry'
-
22
MPRINT(MVAR): where name = '
NOTE: Line generated by the macro variable "_WHERE_CLAUSE".
1 name = 'Henry'
-
200
ERROR 22-322: Syntax error, expecting one of the following: a name, a quoted string,
a numeric constant, a datetime constant, a missing value, (, *, +, -, ALL, ANY,
BTRIM, CALCULATED, CASE, INPUT, PUT, SELECT, SOME, SUBSTRING, TRANSLATE, USER.
ERROR 200-322: The symbol is not recognized and will be ignored.
114 ;
MPRINT(MVAR): Henry'
You need %UNQUOTE which is what is happening with %LET, it is un-quoting the quoted quotes.
Change
where &_where_clause
to
where %unquote(&_where_clause)
I am trying to run a program with a prompt for a date in Enterprise Guide. I have the prompt configured, and it appears when I run the program. At the top of the program log I get the following lines that seem to show the macro values for the prompt are populating correctly:
7 %LET Processing_Month_end = 30Nov2015;
8 %LET Processing_Month = 01Nov2015;
9 %LET Processing_Month_label = November 2015;
My question is how to use these macro values as a date later in my program. If I try a simple data step:
data dates;
refDate = &Processing_Month;
run;
I get the following error:
24 GOPTIONS ACCESSIBLE;
25 data dates;
26 refDate = &Processing_Month;
NOTE: Line generated by the macro variable "PROCESSING_MONTH".
26 01Nov2015
_______
22
ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, -, /, <, <=, <>, =, >, ><, >=, AND, EQ, GE, GT, IN,
LE, LT, MAX, MIN, NE, NG, NL, NOTIN, OR, ^=, |, ||, ~=.
27 run;
If I try to use input to format the value into a date:
data dates;
refDate = input(&Processing_Month, date9.);
run;
I get a similar error:
24 GOPTIONS ACCESSIBLE;
25 data dates;
26 refDate = input(&Processing_Month, date9.);
NOTE: Line generated by the macro variable "PROCESSING_MONTH".
26 01Nov2015
_______
22
ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, -, /, <, <=, <>, =, >, ><, >=, AND, EQ, GE, GT, IN,
LE, LT, MAX, MIN, NE, NG, NL, NOTIN, OR, ^=, |, ||, ~=.
27 run;
If I try to wrap the macro value in a date literal:
data dates;
refDate = '&Processing_Month'd;
run;
Error:
24 GOPTIONS ACCESSIBLE;
25 data dates;
26 refDate = '&Processing_Month'd;
____________________
77
ERROR: Invalid date/time/datetime constant '&Processing_Month'd.
ERROR 77-185: Invalid number conversion on '&Processing_Month'd.
27 run;
What syntax or function do I need to use with this prompt macro variable for it to function as a sas date?
You're almost there. Date literal is the right answer, except you're missing one thing: '&mvar.' won't resolve, only "&mvar." will resolve. So switch to double quotes and trailing d, and you'll be right.
data dates;
refdate = "&processing_month."d;
run;