BookmarkSubscribeRSS Feed
Aexor
Lapis Lazuli | Level 10

Hi All

 

I have one requirement of migration activity where I need to store this code  in a macro variables. 

ods noproctitle;
ods graphics / imagemap=on;
libname _tmpcas_ cas caslib="CASUSER";

proc cas;
	session %sysfunc(getlsessref(MYCAS));
	loadactionset "timeData";
	action runTimeCode / table={caslib="%sysfunc(getlcaslib( MYCAS))", 
		name="PRICEDATA"} objOut={{table={caslib="%sysfunc(getlcaslib(_tmpcas_))", 
		name="outStatTemp"

		                                           , replace="true"}, 
		objRef='outStat'} , {table={caslib="%sysfunc(getlcaslib(_tmpcas_))", 
		name="outFcastTemp"

		                                           , replace="true"}, 
		objRef='outFcast'} } seasonality=12 timeId={name='date', FORMAT="_DATA_"} 
		interval="Month" nlFormat=true series={'sale'} require={{pkg='TSM'}} code=' array diff[1]/nosymbols; 
     declare object myModel(TSM);
     declare object mySpec(ARIMASpec);

     rc = mySpec.Open( );

/* Specify differencing orders */
    diff[1] = 1;
    rc = mySpec.SetDiff(diff);

 rc = mySpec.SetOption(''noint'',1);      rc = mySpec.SetOption(''method'',''CLS'');
     rc = mySpec.Close( );

     /* Setup and run the TSM model object */
     rc = myModel.Initialize(mySpec);
     rc = myModel.SetY(sale);
  rc = myModel.SetOption(''lead'',12);      rc = myModel.SetOption(''alpha'',0.05);
     rc = myModel.Run( );

     /* Output model forecasts and estimates */
     declare object outFcast(TSMFor);
     rc = outFcast.Collect(myModel);


     declare object outStat(TSMSTAT);
     rc = outStat.Collect(myModel);

';
	run;

proc print data=_tmpcas_.outStatTemp label contents="Fit statistics";
	title 'Fit statistics';
run;

ods exclude all;

proc sql;
	select max(date) into :maxTimeID from MYCAS.PRICEDATA;
quit;

ods exclude none;

proc sgplot data=_tmpcas_.outFcastTemp noautolegend 
		description="Predicted and actual values of sale";
	title 'Predicted and actual values of sale';
	xaxis label='date';
	yaxis label='sale';
	series x=date y=ACTUAL /lineattrs=(color=black) name="actual" 
		legendlabel="Actual";
	series x=date y=PREDICT /name="predict" legendlabel="Predicted";
	band x=date lower=LOWER upper=UPPER / transparency=0.5 name="pband" 
		legendlabel="95% Confidence Limits";
	refline &maxTimeID /axis=x label="Forecast Start";
	keylegend "actual" "predict" "pband" / across=4 noborder position=TopLeft 
		location=inside;
run;

proc delete data=_tmpcas_.outFcastTemp _tmpcas_.outStatTemp;
run;

libname _tmpcas_;

 We are using these macro call to print exact same program as part of migration 

for e.g 

%__code(libname _tmpcas_ cas caslib="CASUSER")
    		%__code(proc cas)
   			%__code(session %sysfunc(getlsessref(MYCAS)))
   			%__code(loadactionset "timeData")
   		   %__code( action runTimeCode / table={caslib="%sysfunc(getlcaslib( MYCAS))", 
		          name="PRICEDATA"} objOut={{table={caslib="%sysfunc(getlcaslib(_tmpcas_))", 
		          name='outStatTemp' , replace='true'}, objRef='outStat'} , {table={caslib="%sysfunc(getlcaslib(_tmpcas_))", 
		          name="outFcastTemp" , replace="true"}, objRef='outFcast'} } seasonality=12 timeId={name='date', FORMAT="_DATA_"} 
		          interval="Month" nlFormat=true series={'sale'} require={{pkg='TSM'}} code=' array diff[1]/nosymbols; 
                  declare object myModel(TSM);
                  declare object mySpec(ARIMASpec);
                  rc = mySpec.Open( );
                  /* Specify differencing orders */
                 diff[1] = 1;
                 rc = mySpec.SetDiff(diff);
                 rc = mySpec.SetOption(''noint'',1);      
                 rc = mySpec.SetOption(''method'',''CLS'');
                 rc = mySpec.Close( );
            /* Setup and run the TSM model object */
                rc = myModel.Initialize(mySpec);
              rc = myModel.SetY(sale);
              rc = myModel.SetOption(''lead'',12);      
              rc = myModel.SetOption(''alpha'',0.05);
              rc = myModel.Run( );
           /* Output model forecasts and estimates */
     declare object outFcast(TSMFor);
     rc = outFcast.Collect(myModel);
      declare object outStat(TSMSTAT);
     rc = outStat.Collect(myModel);%nrstr(%'))
    %__code( &_procStatementVar4)

I am facing issue while storing  and calling %__code( action runTimeCode .......... macro . I  have use %let of each and every line too but same isue. can anyone pls suggest any wayout..

the errors I got 

a. bad listing 

b. open code recursion , this is because of single(') . Please help me in resolving this issue. Thanks!

8 REPLIES 8
PaigeMiller
Diamond | Level 26

@Aexor wrote:

 

I have one requirement of migration activity where I need to store this code  in a macro variables. 

I don't even understand the requirement of storing a program in a macro variable. Programs can be stored as simple text files, why can't you just do that?

--
Paige Miller
Aexor
Lapis Lazuli | Level 10
this is a part of migration activity . I cant give much detail .. i tried using %let to store lines as text , but due to single ' getting issue
PaigeMiller
Diamond | Level 26

It sounds like someone has invented a very complicated way of doing something very simple.

--
Paige Miller
Tom
Super User Tom
Super User

@Aexor wrote:
this is a part of migration activity . I cant give much detail .. i tried using %let to store lines as text , but due to single ' getting issue

Define what you mean be "line of code"?  Give concrete examples. They can be fake as long as they are similar in terms of their usage of characters like ; ' " & % ( ) that are important to parsing macro code and regular SAS code.

 

Where are some examples of how to store SAS statements in a macro variable.

You could use %NRSTR().

%let mycode=%nrstr(proc print data=sashelp.class; where sex='M'; run;) ;
&mycode.

Results

1    %let mycode=%nrstr(proc print data=sashelp.class; where sex='M'; run;) ;
2    &mycode.

NOTE: There were 10 observations read from the data set SASHELP.CLASS.
      WHERE sex='M';
NOTE: PROCEDURE PRINT used (Total process time):
      real time           0.03 seconds
      cpu time            0.03 seconds

You could use data step code.  Perhaps storing a string literal into the macro variable.

data _null_;
  call symputx('mycode',"proc print data=sashelp.class; where sex='M'; run;");
run;

Or by reading from a file.  Say for example by storing each line into a different macro variable.

data _null_;
  infile mycode ;
  input;
  call symputx(cats('mycode',_n_),_infile_);
run;
Tom
Super User Tom
Super User

I do not see any %LET statements in the code you posted.  Can you show us what you actually tried to do?

 

If you want to see an example of storing code in macro variable look at this macro: 

https://github.com/sasutils/macros/blob/master/subnet.sas

Tom_0-1733491171567.png

 

Ksharp
Super User
Why not directly run this code by %include statement?
For example:
Your code has been included in file 'c:\temp\code.sas' .
And you can run it directly:
......main code........
%include 'c:\temp\code.sas' ;
........main code.......
Patrick
Opal | Level 21

Migration from what to what? 

Without really understanding what this is about it feels to me like a bad re-design done by someone with likely an object oriented background who doesn't know much about SAS and what SAS macros are. If I'm right then this will not only lead to a very significant increase in migration effort (with a risk of failure) but also to way more complicated code and a maintenance nightmare later on.

Tom
Super User Tom
Super User

@Aexor wrote:

Hi All

 

I have one requirement of migration activity where I need to store this code  in a macro variables. 

 

Spoiler
ods noproctitle;
ods graphics / imagemap=on;
libname _tmpcas_ cas caslib="CASUSER";

proc cas;
	session %sysfunc(getlsessref(MYCAS));
	loadactionset "timeData";
	action runTimeCode / table={caslib="%sysfunc(getlcaslib( MYCAS))", 
		name="PRICEDATA"} objOut={{table={caslib="%sysfunc(getlcaslib(_tmpcas_))", 
		name="outStatTemp"

		                                           , replace="true"}, 
		objRef='outStat'} , {table={caslib="%sysfunc(getlcaslib(_tmpcas_))", 
		name="outFcastTemp"

		                                           , replace="true"}, 
		objRef='outFcast'} } seasonality=12 timeId={name='date', FORMAT="_DATA_"} 
		interval="Month" nlFormat=true series={'sale'} require={{pkg='TSM'}} code=' array diff[1]/nosymbols; 
     declare object myModel(TSM);
     declare object mySpec(ARIMASpec);

     rc = mySpec.Open( );

/* Specify differencing orders */
    diff[1] = 1;
    rc = mySpec.SetDiff(diff);

 rc = mySpec.SetOption(''noint'',1);      rc = mySpec.SetOption(''method'',''CLS'');
     rc = mySpec.Close( );

     /* Setup and run the TSM model object */
     rc = myModel.Initialize(mySpec);
     rc = myModel.SetY(sale);
  rc = myModel.SetOption(''lead'',12);      rc = myModel.SetOption(''alpha'',0.05);
     rc = myModel.Run( );

     /* Output model forecasts and estimates */
     declare object outFcast(TSMFor);
     rc = outFcast.Collect(myModel);


     declare object outStat(TSMSTAT);
     rc = outStat.Collect(myModel);

';
	run;

proc print data=_tmpcas_.outStatTemp label contents="Fit statistics";
	title 'Fit statistics';
run;

ods exclude all;

proc sql;
	select max(date) into :maxTimeID from MYCAS.PRICEDATA;
quit;

ods exclude none;

proc sgplot data=_tmpcas_.outFcastTemp noautolegend 
		description="Predicted and actual values of sale";
	title 'Predicted and actual values of sale';
	xaxis label='date';
	yaxis label='sale';
	series x=date y=ACTUAL /lineattrs=(color=black) name="actual" 
		legendlabel="Actual";
	series x=date y=PREDICT /name="predict" legendlabel="Predicted";
	band x=date lower=LOWER upper=UPPER / transparency=0.5 name="pband" 
		legendlabel="95% Confidence Limits";
	refline &maxTimeID /axis=x label="Forecast Start";
	keylegend "actual" "predict" "pband" / across=4 noborder position=TopLeft 
		location=inside;
run;

proc delete data=_tmpcas_.outFcastTemp _tmpcas_.outStatTemp;
run;

libname _tmpcas_;
 We are using these macro call to print exact same program as part of migration 

for e.g 

Spoiler
%__code(libname _tmpcas_ cas caslib="CASUSER")
    		%__code(proc cas)
   			%__code(session %sysfunc(getlsessref(MYCAS)))
   			%__code(loadactionset "timeData")
   		   %__code( action runTimeCode / table={caslib="%sysfunc(getlcaslib( MYCAS))", 
		          name="PRICEDATA"} objOut={{table={caslib="%sysfunc(getlcaslib(_tmpcas_))", 
		          name='outStatTemp' , replace='true'}, objRef='outStat'} , {table={caslib="%sysfunc(getlcaslib(_tmpcas_))", 
		          name="outFcastTemp" , replace="true"}, objRef='outFcast'} } seasonality=12 timeId={name='date', FORMAT="_DATA_"} 
		          interval="Month" nlFormat=true series={'sale'} require={{pkg='TSM'}} code=' array diff[1]/nosymbols; 
                  declare object myModel(TSM);
                  declare object mySpec(ARIMASpec);
                  rc = mySpec.Open( );
                  /* Specify differencing orders */
                 diff[1] = 1;
                 rc = mySpec.SetDiff(diff);
                 rc = mySpec.SetOption(''noint'',1);      
                 rc = mySpec.SetOption(''method'',''CLS'');
                 rc = mySpec.Close( );
            /* Setup and run the TSM model object */
                rc = myModel.Initialize(mySpec);
              rc = myModel.SetY(sale);
              rc = myModel.SetOption(''lead'',12);      
              rc = myModel.SetOption(''alpha'',0.05);
              rc = myModel.Run( );
           /* Output model forecasts and estimates */
     declare object outFcast(TSMFor);
     rc = outFcast.Collect(myModel);
      declare object outStat(TSMSTAT);
     rc = outStat.Collect(myModel);%nrstr(%'))
    %__code( &_procStatementVar4)

I am facing issue while storing  and calling %__code( action runTimeCode .......... macro . I  have use %let of each and every line too but same isue. can anyone pls suggest any wayout..

the errors I got 

a. bad listing 

b. open code recursion , this is because of single(') . Please help me in resolving this issue. Thanks!


Please explain what you are doing.

Where do you have the original program stored?

Why do you want to pass pieces of the program to the macro _CODE?

Show the definition of your __CODE macro. 

What is is supposed to do?

What parameters does it take as INPUT?  

I suspect that there is another way to perform your migration, but you will need explain what you are doing in more detail to get useful help.  For example if you want to copy a file from one machine to another you could use sftp or if you have SAS/Connect licenses on both machines PROC UPLOAD (or PROC DOWNLOAD depending on the direction.)

 

If you want to pass lines of text into a macro it is best to design to macro to expect the lines to be quoted.  That way you can use a string literal quoted with single quotes to hide any macro triggers (& and % characters) in the text and get the actual text into the macro.  The macro could then use the DEQUOTE() function to remove the quotes.

 

Then you could easily use a data step to generate one call to the macro for each line of text in a file.

data _null_;
  infile codefile ;
  input;
  call execute(cats('%nrstr(%__code)(',quote(trim(_infile_),"'"),')'));
run;

Would generate and run code lines like:

%__code('ods noproctitle;')
%__code('ods graphics / imagemap=on;')
%__code('libname _tmpcas_ cas caslib="CASUSER";')
%__code(' ')
%__code('proc cas;')
%__code('	session %sysfunc(getlsessref(MYCAS));')

 

hackathon24-white-horiz.png

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

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
  • 8 replies
  • 1430 views
  • 7 likes
  • 5 in conversation