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

Hi, please help.

I have a code like this macro inside a sas program, my problem is that the variable that i am declaring inside this macro is not properly initialized for use outside of this macro. Please help me or point me to the right direction. I have been using sas for 5 months now but this bit is really challenging. I have been stuck on this for 2 days now.: 

%macro Get_Delta_Period;
%if %sysfunc(EXIST(CONFIG.CONTROL_TABLE)) %then 
	%do;
		proc sql noprint;
		   select strip(Desc_Value)
		      into :desc_value01 - :desc_value03
		   from CONFIG.CFG_EXECUTION_CONTROL Order by Cod_Config asc;
		quit;

		%let RunDateID = &desc_value01;
		%let start_time = "&desc_value02"dt;
		%let end_time = "&desc_value03"dt;
		
	%end;
	%else 
		%do;
		%let RunDateID = "0";
		%let start_time = '01JAN2000:12:59:59.999'dt;
		%let end_time = '01JAN2000:00:00:00.000'dt;
	%end;
 
   data _null_;
     put 'LOOK HERE: ----> inside Get_Delta_Period ---- dttm_BeginDV: ' &dttm_BeginDV;
      call symput('RunDateID', &RunDateID);
	  call symput('start_time', &start_time);
	  call symput('end_time', &end_time);
	run;
	
%mend;
%Get_Delta_Period;


1 ACCEPTED SOLUTION

Accepted Solutions
PhiSlogan
Obsidian | Level 7

@PaigeMiller thanks it works fine when i declare the variables %global outside macro and eliminate the data _null_ step - with the data _null_ symputx()/symput - my declared variables loose its formatting, exactly what @PaigeMiller said in one of his replies. Below is the final correct code for anyone else following:

%global RunDateID start_time end_time; 
%macro Get_Delta_Period;
%if %sysfunc(EXIST(CONFIG.CONTROL_TABLE)) %then 
	%do;
		proc sql noprint;
		   select strip(Desc_Value)
		      into :desc_value01 - :desc_value03
		   from CONFIG.CONTROL_TABLE Order by Cod_Config asc;
		quit;

		%let RunDateID = "&desc_value01";
		%let start_time = "&desc_value02"dt;
		%let end_time = "&desc_value03"dt;
		
	%end;
	%else 
		%do;
		%let RunDateID = "0";
		%let start_time = '01JAN2000:12:59:59.999'dt;
		%let end_time = '01JAN2000:00:00:00.000'dt;
	%end;

%mend;
%Get_Delta_Period;

Thank you so much for the help!! i understand a bit more about macro variables! Hope this also helps someone!

 

View solution in original post

13 REPLIES 13
Astounding
PROC Star

You don't actually mention which macro variables are the problem, but here is a probable culprit:

 

call symput('RunDateID', &RunDateID);
call symput('start_time', &start_time); call symput('end_time', &end_time);

 

 To make these macro variables exist once your macro finishes executing:

call symputx('RunDateID', &RunDateID, 'global');
call symputx('start_time', &start_time, 'global');
call symputx('end_time', &end_time, 'global');

 

On second thought, that's useful in some cases but might cause trouble here.  Add these three lines at the very beginning of your macro definition:

 

%global RunDateID start_time end_time; 

PhiSlogan
Obsidian | Level 7

@Astounding I have done this and it has the same results ->  ERROR 253-185: The SYMPUTX subroutine call has too many arguments.

PaigeMiller
Diamond | Level 26

@PhiSlogan wrote:

@Astounding I have done this and it has the same results ->  ERROR 253-185: The SYMPUTX subroutine call has too many arguments.


Show us the code. Show us the values of your macro variables. Show us the SASLOG with options mprint; turned on.

--
Paige Miller
PhiSlogan
Obsidian | Level 7

@Astounding Thanks this helped and after also reading @PaigeMiller reply i now understand how it works the variable needed to have been declared before.. I have updated to something like this ...

%global RunDateID start_time end_time;

%macro Get_Delta_Period;
%if %sysfunc(EXIST(CONFIG.CONTROL_TABLE)) %then 
	%do;
		proc sql noprint;
		   select strip(Desc_Value)
		      into :desc_value01 - :desc_value03
		   from CONFIG.CFG_EXECUTION_CONTROL Order by Cod_Config asc;
		quit;

		%let RunDateID = &desc_value01;
		%let start_time = "&desc_value02"dt;
		%let end_time = "&desc_value03"dt;
		
	%end;
	%else 
		%do;
		%let RunDateID = "0";
		%let start_time = '01JAN2000:12:59:59.999'dt;
		%let end_time = '01JAN2000:00:00:00.000'dt;
	%end;
 
   data _null_;
     put 'LOOK HERE: ----> inside Get_Delta_Period ---- dttm_BeginDV: ' &dttm_BeginDV;
      call symputx('RunDateID', &RunDateID, 'global');
	  call symputx('start_time', &start_time, 'global');
	  call symputx('end_time', &end_time, 'global');
	run;
	
%mend;
%Get_Delta_Period;

%put &RunDateID; &start_time; &end_time;

  

 

NOTE: Line generated by the invoked macro "GET_DELTA_PERIOD".
287 data _null_; call symput('RunDateID', &RunDateID); call symput('dttm_BeginDV',
______
253
287 ! &dttm_BeginDV); call symput('dttm_EndDV', &dttm_EndDV); call symput('dt_BeginDMCO', &dt_BeginDMCO);
287 ! call symput
ERROR 253-185: The SYMPUT subroutine call has too many arguments.

 

 

NOTE: Line generated by the macro variable "RUNDATEID".
287 7d81899e-5788-3540-826a-cbafd1357337
_______ _
22 22

ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, ',', -, /, <, <=, <>, =, >, ><, >=, AND, EQ, GE,
GT, LE, LT, MAX, MIN, NE, NG, NL, OR, ^=, |, ||, ~=.

NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).
287:2 287:20 287:25 287:2 287:2 287:2 287:2 287:2 287:2 287:2
NOTE: The SAS System stopped processing this step because of errors.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

Tom
Super User Tom
Super User

Paste lines from LOG using the Insert Code pop-up to preserve the formatting. The icon looks like lowercase i inside of curly brackets.

 

The logic error that is most likely causing that error message is that you never did anything to handle the case when there are fewer than three records in your control dataset.  Add this line to the top of you macro:

%local desc_value01 desc_value02 desc_value03 ;

Your %PUT statement at the end has extra semi-colons in it. Try this instead:

%put &=RunDateID  &=start_time  &=end_time;

In your default value for one of the macro variables you are adding quotes, but you are not adding them to the real value.

%let RunDateID = &desc_value01;
%let RunDateID = "0";

What is the purpose of the final data step?

It looks like it is removing the formatting you have added to your macro variables and adding leading spaces to the numeric ones.

Is that what you want? Why?  You should at a minimum be using call symputX() instead of the older call symput().

 

What is the structure of your control table?  Does the COD_CONFIG variable value determine the meaning of the DESC_VALUE?

 

Why not just use a data step with CALL SYMPUTX() instead of the SQL select with INTO clause?

 

 

PhiSlogan
Obsidian | Level 7
1.The purpose of the final step is assign data step variable to global variable
2.Even using symputx() the result is the same
3. Structure of control table:
Cod_Config Numeric 8 (None) (None) true (None) (None)
Desc_Config Character 20 (None) (None) true (None) (None)
Desc_Value Character 100 (None) (None) true (None) (None)

4. I dont know how to yet, i am ew to sas programming

Tom
Super User Tom
Super User

@PhiSlogan wrote:
1.The purpose of the final step is assign data step variable to global variable
2.Even using symputx() the result is the same
3. Structure of control table:
Cod_Config Numeric 8 (None) (None) true (None) (None)
Desc_Config Character 20 (None) (None) true (None) (None)
Desc_Value Character 100 (None) (None) true (None) (None)

4. I dont know how to yet, i am ew to sas programming


How to use it depends on how the values of those three variables are populated.

It might be that DESC_CONFIG actually has the name of the macro variable you want to create.

In which case you might just do as simple as :

data _null_;
  set CONTROL_TABLE;
  call symputx(Desc_Config,Desc_Value);
run;
PaigeMiller
Diamond | Level 26

@PhiSlogan wrote:

 

 

NOTE: Line generated by the invoked macro "GET_DELTA_PERIOD".
287 data _null_; call symput('RunDateID', &RunDateID); call symput('dttm_BeginDV',
______
253
287 ! &dttm_BeginDV); call symput('dttm_EndDV', &dttm_EndDV); call symput('dt_BeginDMCO', &dt_BeginDMCO);
287 ! call symput
ERROR 253-185: The SYMPUT subroutine call has too many arguments.

 

 

NOTE: Line generated by the macro variable "RUNDATEID".
287 7d81899e-5788-3540-826a-cbafd1357337

The problem IS NOT that you haven't declared the variable as %GLOBAL as the first step in the program (although that's a good thing to do).

 

Your step that begins with data _null_; serves no purpose, as I explained above, and causes an error. Take it out!

 

The specific error is that call symput is expecting a data set VARIABLE NAME as the 2nd argument. The value of &RunDateID is 7d81899e-5788-3540-826a-cbafd1357337 which is not a data set variable name.

--
Paige Miller
PhiSlogan
Obsidian | Level 7
Hi I finally understand what you were saying and it works ill post an answer soon thanks a lot
PhiSlogan
Obsidian | Level 7

@PaigeMiller thanks it works fine when i declare the variables %global outside macro and eliminate the data _null_ step - with the data _null_ symputx()/symput - my declared variables loose its formatting, exactly what @PaigeMiller said in one of his replies. Below is the final correct code for anyone else following:

%global RunDateID start_time end_time; 
%macro Get_Delta_Period;
%if %sysfunc(EXIST(CONFIG.CONTROL_TABLE)) %then 
	%do;
		proc sql noprint;
		   select strip(Desc_Value)
		      into :desc_value01 - :desc_value03
		   from CONFIG.CONTROL_TABLE Order by Cod_Config asc;
		quit;

		%let RunDateID = "&desc_value01";
		%let start_time = "&desc_value02"dt;
		%let end_time = "&desc_value03"dt;
		
	%end;
	%else 
		%do;
		%let RunDateID = "0";
		%let start_time = '01JAN2000:12:59:59.999'dt;
		%let end_time = '01JAN2000:00:00:00.000'dt;
	%end;

%mend;
%Get_Delta_Period;

Thank you so much for the help!! i understand a bit more about macro variables! Hope this also helps someone!

 

Astounding
PROC Star

It s likely that this should change:

 

call symput('RunDateID', &RunDateID);

 

The value being supplied should be in double-quotes:

 

call symput('RunDateID', "&RunDateID");

 

To compensate for that, remove the double quotes in this line:

 

%let RunDateID = "0";

PaigeMiller
Diamond | Level 26

@PhiSlogan wrote:

call symput('RunDateID', &RunDateID);

call symput('start_time', &start_time);

call symput('end_time', &end_time); run;


So, you have a macro variable named &RunDateID, and you are using call symput to assign the value of &RunDateID to a macro variable of the same name?

 

Agreeing with @Astounding's second thought.

 

This may or may not be the cause of your problems, but it seems to be code that serves no purpose at all. 

--
Paige Miller
ballardw
Super User

@PhiSlogan wrote:

Hi, please help.

I have a code like this macro inside a sas program, my problem is that the variable that i am declaring inside this macro is not properly initialized for use outside of this macro. Please help me or point me to the right direction. I have been using sas for 5 months now but this bit is really challenging. I have been stuck on this for 2 days now.: 

%macro Get_Delta_Period;
%if %sysfunc(EXIST(CONFIG.CONTROL_TABLE)) %then 
	%do;
		proc sql noprint;
		   select strip(Desc_Value)
		      into :desc_value01 - :desc_value03
		   from CONFIG.CFG_EXECUTION_CONTROL Order by Cod_Config asc;
		quit;

		%let RunDateID = &desc_value01;
		%let start_time = "&desc_value02"dt;
		%let end_time = "&desc_value03"dt;
		
	%end;
	%else 
		%do;
		%let RunDateID = "0";
		%let start_time = '01JAN2000:12:59:59.999'dt;
		%let end_time = '01JAN2000:00:00:00.000'dt;
	%end;
 
   data _null_;
     put 'LOOK HERE: ----> inside Get_Delta_Period ---- dttm_BeginDV: ' &dttm_BeginDV;
      call symput('RunDateID', &RunDateID);
	  call symput('start_time', &start_time);
	  call symput('end_time', &end_time);
	run;
	
%mend;
%Get_Delta_Period;



Show the actual resolved values of your macro variables.

See if this might be similar for your desc_value01

%let x=Something ,with,commas;
data junk;
   call symputx('somevar',&x);
run;
   

If your resolved variable contains commas not inside quotes then the commas become delimiters for the function and too many.

 

 

Set:  option mprint; run the macro and look closely that the resolved values of your macro variables, especially RunDateId.

If there are commas in the value that is likely the issue. If there are not quotes in the value then perhaps

 call symput('RunDateID', "&RunDateID.");

Maybe. Guessing without any data at all.

 

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 13 replies
  • 7174 views
  • 0 likes
  • 5 in conversation