Hi, I couldn't understand why I got errors after running the following code. The errors can be replicated by running this sample code in your SAS environment.
/* The data importing macro I used */ %macro CsvExl_Import(location=, filename=, DBMS=, outfile=); proc import datafile="&location./&filename..&DBMS." DBMS= &DBMS. REPLACE out= work.&outfile.; getnames=yes; guessingrows=200000; run; %mend CsvExl_Import; /* The global macro variable existed in my environment */ %let deployMode = "dev"; /*##################################*/ /* create sample data sets for demo */ data one; input IDnumber $ Week1 Week16; WeightLoss2=Week1-Week16; datalines; 2477 195 163 2431 220 198 2456 173 155 2412 135 116 ; data two; input IDnumber $ Week1 Week16; WeightLoss2=Week1-Week16; datalines; 4321 321 768 3245 342 754 1324 123 546 6237 543 121 ; /* Write to csv files in a designed folder with the pattern I want */ proc export data=work.one outfile='C:/cctem/2020q3/dev/dev_sample_2019.csv' dbms=csv replace; run; proc export data=work.two outfile='C:/cctem/2020q3/dev/dev_sample_2020.csv' dbms=csv replace; run; /*##################################*/ /* I need to use the following macro variables in my programs */ %let env = %qsysfunc(compress(&deployMode.,%str(%"))); %let years = 19 20; %let impl = 2020q3; %put &env; /* Below is the code I need to use and got the error that I am asking */ %macro build_table(); %local i; %do i = 1 %to %sysfunc(countw(&years)); /* Define values for macro variables of Year(s) and File name(s)*/ %let years&i = %scan(&years, &i); %let File_&i = &env._sample_20&&years&i; data three; set sashelp.class; run; /* Read data of each year */ %CsvExl_Import(location= C:/cctem/&impl./&env. ,filename= &&File_&i. ,DBMS= csv ,outfile= &&File_&i.); %end; %mend; /* Run macro program */ %build_table();
The issue came from the %CsvExl_Import() inside the %macro build_table(). Here are the scenarios:
1) If I remove %CsvExl_Import() , no error.
2) If I replace
%let env = %qsysfunc(compress(&deployMode.,%str(%")));
with
%let env = dev;
then no error.
But, "%let env = %qsysfunc(compress(&deployMode.,%str(%")));" is the way I want to use in my program. I want to assign macro variable &env from a macro variable defined in a configuration program in the system. I believe something related to the macro variable that I didn't do it in the right way, and reach out for the help. Thanks a lot !
As you can see, the use of the unnecessary quotes already complicates your life, or you wouldn't be here. Letting it permeate is a loan you take out on your own future (and that of anybody else who needs to work in that environment). Correct it now.
Sometimes we need to bite the bullet and make corrections throughout a whole environment when such a mistake is unvovered, in order to guarantee a less complicated future. Been there, done that.
PS how many hundred programs would you need to change?
Hi, I couldn't understand why I got errors after running the following code.
Run the code again with the command options mprint; as the first line. Please show us the log. Paste the log as text into the window that appears when you click on the </> icon. DO NOT SKIP THIS STEP.
Thanks for the advice. I re-run the code with the first line "options mprint;". Here is the new code:
options mprint; %macro CsvExl_Import(location=, filename=, DBMS=, outfile=); proc import datafile="&location./&filename..&DBMS." DBMS= &DBMS. REPLACE out= work.&outfile.; getnames=yes; guessingrows=200000; run; %mend CsvExl_Import; %let deployMode = "dev"; /*##################################*/ /* create data sets */ data one; input IDnumber $ Week1 Week16; WeightLoss2=Week1-Week16; datalines; 2477 195 163 2431 220 198 2456 173 155 2412 135 116 ; data two; input IDnumber $ Week1 Week16; WeightLoss2=Week1-Week16; datalines; 4321 321 768 3245 342 754 1324 123 546 6237 543 121 ; /* Write to csv files */ proc export data=work.one outfile='C:/cctem/2020q3/dev/dev_sample_2019.csv' dbms=csv replace; run; proc export data=work.two outfile='C:/cctem/2020q3/dev/dev_sample_2020.csv' dbms=csv replace; run; /*##################################*/ %let env = %qsysfunc(compress(&deployMode.,%str(%"))); %let years = 19 20; %let impl = 2020q3; %put &env; %macro build_table(); %local i; %do i = 1 %to %sysfunc(countw(&years)); /* Define values for macro variables of Year(s) and File name(s)*/ %let years&i = %scan(&years, &i); %let File_&i = &env._sample_20&&years&i; data three; set sashelp.class; run; /* Read data of each year */ %CsvExl_Import(location= C:/cctem/&impl./&env. ,filename= &&File_&i. ,DBMS= csv ,outfile= &&File_&i.); %end; %mend; /* Run macro program */ %build_table();
Here is the log:
509 options mprint; 510 511 %macro CsvExl_Import(location=, filename=, DBMS=, outfile=); 512 proc import datafile="&location./&filename..&DBMS." 513 DBMS= &DBMS. 514 REPLACE 515 out= work.&outfile.; 516 getnames=yes; 517 guessingrows=200000; 518 run; 519 %mend CsvExl_Import; 520 521 %let deployMode = "dev"; 522 523 /*##################################*/ 524 /* create data sets */ 525 data one; 526 input IDnumber $ Week1 Week16; 527 WeightLoss2=Week1-Week16; 528 datalines; NOTE: The data set WORK.ONE has 4 observations and 4 variables. NOTE: DATA statement used (Total process time): real time 0.03 seconds cpu time 0.03 seconds 533 ; 534 535 data two; 536 input IDnumber $ Week1 Week16; 537 WeightLoss2=Week1-Week16; 538 datalines; NOTE: The data set WORK.TWO has 4 observations and 4 variables. NOTE: DATA statement used (Total process time): real time 0.02 seconds cpu time 0.01 seconds 543 ; 544 /* Write to csv files */ 545 546 proc export data=work.one 547 outfile='C:/cctem/2020q3/dev/dev_sample_2019.csv' 548 dbms=csv 549 replace; 550 run; 551 /********************************************************************** 552 * PRODUCT: SAS 553 * VERSION: 9.4 554 * CREATOR: External File Interface 555 * DATE: 17SEP20 556 * DESC: Generated SAS Datastep Code 557 * TEMPLATE SOURCE: (None Specified.) 558 ***********************************************************************/ 559 data _null_; 560 %let _EFIERR_ = 0; /* set the ERROR detection macro variable */ 561 %let _EFIREC_ = 0; /* clear export record count macro variable */ 562 file 'C:/cctem/2020q3/dev/dev_sample_2019.csv' delimiter=',' DSD DROPOVER lrecl=32767; 563 if _n_ = 1 then /* write column names or labels */ 564 do; 565 put 566 "IDnumber" 567 ',' 568 "Week1" 569 ',' 570 "Week16" 571 ',' 572 "WeightLoss2" 573 ; 574 end; 575 set WORK.ONE end=EFIEOD; 576 format IDnumber $8. ; 577 format Week1 best12. ; 578 format Week16 best12. ; 579 format WeightLoss2 best12. ; 580 do; 581 EFIOUT + 1; 582 put IDnumber $ @; 583 put Week1 @; 584 put Week16 @; 585 put WeightLoss2 ; 586 ; 587 end; 588 if _ERROR_ then call symputx('_EFIERR_',1); /* set ERROR detection macro variable */ 589 if EFIEOD then call symputx('_EFIREC_',EFIOUT); 590 run; NOTE: The file 'C:/cctem/2020q3/dev/dev_sample_2019.csv' is: Filename=C:\cctem\2020q3\dev\dev_sample_2019.csv, RECFM=V,LRECL=32767,File Size (bytes)=0, Last Modified=17Sep2020:11:51:40, Create Time=17Sep2020:10:50:30 NOTE: 5 records were written to the file 'C:/cctem/2020q3/dev/dev_sample_2019.csv'. The minimum record length was 15. The maximum record length was 33. NOTE: There were 4 observations read from the data set WORK.ONE. NOTE: DATA statement used (Total process time): real time 0.04 seconds cpu time 0.04 seconds 4 records created in C:/cctem/2020q3/dev/dev_sample_2019.csv from WORK.ONE. NOTE: "C:/cctem/2020q3/dev/dev_sample_2019.csv" file was successfully created. NOTE: PROCEDURE EXPORT used (Total process time): real time 0.23 seconds cpu time 0.12 seconds 591 592 proc export data=work.two 593 outfile='C:/cctem/2020q3/dev/dev_sample_2020.csv' 594 dbms=csv 595 replace; 596 run; 597 /********************************************************************** 598 * PRODUCT: SAS 599 * VERSION: 9.4 600 * CREATOR: External File Interface 601 * DATE: 17SEP20 602 * DESC: Generated SAS Datastep Code 603 * TEMPLATE SOURCE: (None Specified.) 604 ***********************************************************************/ 605 data _null_; 606 %let _EFIERR_ = 0; /* set the ERROR detection macro variable */ 607 %let _EFIREC_ = 0; /* clear export record count macro variable */ 608 file 'C:/cctem/2020q3/dev/dev_sample_2020.csv' delimiter=',' DSD DROPOVER lrecl=32767; 609 if _n_ = 1 then /* write column names or labels */ 610 do; 611 put 612 "IDnumber" 613 ',' 614 "Week1" 615 ',' 616 "Week16" 617 ',' 618 "WeightLoss2" 619 ; 620 end; 621 set WORK.TWO end=EFIEOD; 622 format IDnumber $8. ; 623 format Week1 best12. ; 624 format Week16 best12. ; 625 format WeightLoss2 best12. ; 626 do; 627 EFIOUT + 1; 628 put IDnumber $ @; 629 put Week1 @; 630 put Week16 @; 631 put WeightLoss2 ; 632 ; 633 end; 634 if _ERROR_ then call symputx('_EFIERR_',1); /* set ERROR detection macro variable */ 635 if EFIEOD then call symputx('_EFIREC_',EFIOUT); 636 run; NOTE: The file 'C:/cctem/2020q3/dev/dev_sample_2020.csv' is: Filename=C:\cctem\2020q3\dev\dev_sample_2020.csv, RECFM=V,LRECL=32767,File Size (bytes)=0, Last Modified=17Sep2020:11:51:41, Create Time=17Sep2020:10:50:30 NOTE: 5 records were written to the file 'C:/cctem/2020q3/dev/dev_sample_2020.csv'. The minimum record length was 16. The maximum record length was 33. NOTE: There were 4 observations read from the data set WORK.TWO. NOTE: DATA statement used (Total process time): real time 0.04 seconds cpu time 0.04 seconds 4 records created in C:/cctem/2020q3/dev/dev_sample_2020.csv from WORK.TWO. NOTE: "C:/cctem/2020q3/dev/dev_sample_2020.csv" file was successfully created. NOTE: PROCEDURE EXPORT used (Total process time): real time 0.21 seconds cpu time 0.11 seconds 637 638 /*##################################*/ 639 640 %let env = %qsysfunc(compress(&deployMode.,%str(%"))); 641 %let years = 19 20; 642 %let impl = 2020q3; 643 %put &env; dev 644 645 646 647 %macro build_table(); 648 %local i; 649 650 %do i = 1 %to %sysfunc(countw(&years)); 651 /* Define values for macro variables of Year(s) and File name(s)*/ 652 %let years&i = %scan(&years, &i); 653 %let File_&i = &env._sample_20&&years&i; 654 655 data three; 656 set sashelp.class; 657 run; 658 659 /* Read data of each year */ 660 %CsvExl_Import(location= C:/cctem/&impl./&env. 661 ,filename= &&File_&i. 662 ,DBMS= csv 663 ,outfile= &&File_&i.); 664 665 %end; 666 667 %mend; 668 669 /* Run macro program */ 670 %build_table(); MPRINT(BUILD_TABLE): data three; MPRINT(BUILD_TABLE): set sashelp.class; MPRINT(BUILD_TABLE): run; NOTE: There were 19 observations read from the data set SASHELP.CLASS. NOTE: The data set WORK.THREE has 19 observations and 5 variables. NOTE: DATA statement used (Total process time): real time 0.02 seconds cpu time 0.01 seconds ERROR: "WORK." is not a valid name. NOTE 138-205: Line generated by the macro variable "OUTFILE". 1 work.dev_sample_2019 ------------ 22 ERROR 22-322: Syntax error, expecting one of the following: ;, (, DATAFILE, DATATABLE, DBMS, DEBUG, FILE, OUT, REPLACE, TABLE, _DEBUG_. NOTE: Line generated by the macro variable "OUTFILE". 1 work.dev_sample_2019 ------------ 202 ERROR 202-322: The option or parameter is not recognized and will be ignored. NOTE: PROCEDURE IMPORT used (Total process time): real time 0.01 seconds cpu time 0.01 seconds NOTE: The SAS System stopped processing this step because of errors. MPRINT(CSVEXL_IMPORT): proc import datafile="C:/cctem/2020q3/dev/dev_sample_2019.csv" DBMS= csv REPLACE out= work.dev_sample_2019 getnames=yes; MPRINT(CSVEXL_IMPORT): guessingrows=200000; MPRINT(CSVEXL_IMPORT): run; MPRINT(BUILD_TABLE): ; MPRINT(BUILD_TABLE): data three; MPRINT(BUILD_TABLE): set sashelp.class; MPRINT(BUILD_TABLE): run; NOTE: There were 19 observations read from the data set SASHELP.CLASS. NOTE: The data set WORK.THREE has 19 observations and 5 variables. NOTE: DATA statement used (Total process time): real time 0.02 seconds cpu time 0.01 seconds ERROR: "WORK." is not a valid name. NOTE 138-205: Line generated by the macro variable "OUTFILE". 1 work.dev_sample_2020 ------------ 22 ERROR 22-322: Syntax error, expecting one of the following: ;, (, DATAFILE, DATATABLE, DBMS, DEBUG, FILE, OUT, REPLACE, TABLE, _DEBUG_. NOTE: Line generated by the macro variable "OUTFILE". 1 work.dev_sample_2020 ------------ 202 ERROR 202-322: The option or parameter is not recognized and will be ignored. NOTE: PROCEDURE IMPORT used (Total process time): real time 0.01 seconds cpu time 0.01 seconds NOTE: The SAS System stopped processing this step because of errors. MPRINT(CSVEXL_IMPORT): proc import datafile="C:/cctem/2020q3/dev/dev_sample_2020.csv" DBMS= csv REPLACE out= work.dev_sample_2020 getnames=yes; MPRINT(CSVEXL_IMPORT): guessingrows=200000; MPRINT(CSVEXL_IMPORT): run; MPRINT(BUILD_TABLE): ;
%let deployMode = "dev";
You almost never put macro variable values in quotes, its hard for me to think of a reason why you would need quotes around macro variable values. Even though you remove the quotes later, SAS sometimes gets all queasy about the whole thing where you have removed quotes, and you have to use %UNQUOTE to fix it. Or just not put the value in quotes to begin with.
This is most probably the cause of your problems:
%let deployMode = "dev";
%let env = %qsysfunc(compress(&deployMode.,%str(%")));
Don't complicate your life unnecessarily. Do this instead:
%let deployMode = dev;
%let env = &deployMode.;
@leehsin wrote:
I can't change &deployMode like this:
%let deployMode = dev;
because this macro variable already exists in our system, and is used for the entire infrastructure.
I did not complicate my life unnecessarily. On the contrary, this change will make the life of our group much complicated.
Well, @leehsin , I'm very skeptical. It's hard to see why you have to use this particular macro variable &DEPLOYMODE, why can't you name it something else? I also don't see why you can't just set &ENV as you want, rather than going through &deploymode. And you can also use %LOCAL macro variables to get around this. There are many solutions.
Nevertheless, if you insist, try this
out= work%unquote(&outfile)
As you can see, the use of the unnecessary quotes already complicates your life, or you wouldn't be here. Letting it permeate is a loan you take out on your own future (and that of anybody else who needs to work in that environment). Correct it now.
Sometimes we need to bite the bullet and make corrections throughout a whole environment when such a mistake is unvovered, in order to guarantee a less complicated future. Been there, done that.
PS how many hundred programs would you need to change?
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
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.
Ready to level-up your skills? Choose your own adventure.