BookmarkSubscribeRSS Feed
theponcer
Quartz | Level 8

 

The Seven Dwarves are working on a coding project. Each has been assigned a piece of logic to code. Doc, Grumpy, and Happy are finished with their code, and saved each piece as a separate program. They would like to test that their code works together, but can't figure out how to loop through each piece in a single step. They are still adjusting to work outside of the mine, and suspect that they might not be referencing array variables correctly.

 

data scores;
   input test;
   datalines;
1
10
100
;

data test;
set scores;

*Doc Code;
Doc=test**2;

*Grumpy Code;
Grumpy = Doc - 10;

*Happy Code;
Happy = cat(Grumpy,"!");

run;

%let path = C:/Programs;

%let Doc = "Y";
%let Doc_path = "Doc Code.sas";
%let Grumpy = "Y";
%let Grumpy_path = "Grumpy Code.sas";
%let Happy = "Y";
%let Happy_path = "Happy Code.sas";

data test;
set scores;
array dwarves(*) $ Doc Grumpy Happy;
do i=1 to dim(dwarves);
	if dwarves[i] = 'Y' then
	%include(&path./&dwarves[i]_path.);
end;
run;

 

10 REPLIES 10
Reeza
Super User

That's not how arrays work in SAS.
You don't need arrays you don't need a data step. Is this a real issue or a homework assignment?

If you have working code and need to turn it into a macro, I recommend using DOSUBL or CALL EXECUTE.

I wrote a tutorial here on turning programs into macros:
https://github.com/statgeek/SAS-Tutorials/blob/master/Turning%20a%20program%20into%20a%20macro.md

 

 

EDIT: if you really want to use that type of approach look into SYMGET function and CALL EXECUTE.


@theponcer wrote:

 

The Seven Dwarves are working on a coding project. Each has been assigned a piece of logic to code. Doc, Grumpy, and Happy are finished with their code, and saved each piece as a separate program. They would like to test that their code works together, but can't figure out how to loop through each piece in a single step. They are still adjusting to work outside of the mine, and suspect that they might not be referencing array variables correctly.

 

data scores;
   input test;
   datalines;
1
10
100
;

data test;
set scores;

*Doc Code;
Doc=test**2;

*Grumpy Code;
Grumpy = Doc - 10;

*Happy Code;
Happy = cat(Grumpy,"!");

run;

%let path = C:/Programs;

%let Doc = "Y";
%let Doc_path = "Doc Code.sas";
%let Grumpy = "Y";
%let Grumpy_path = "Grumpy Code.sas";
%let Happy = "Y";
%let Happy_path = "Happy Code.sas";

data test;
set scores;
array dwarves(*) $ Doc Grumpy Happy;
do i=1 to dim(dwarves);
	if dwarves[i] = 'Y' then
	%include(&path./&dwarves[i]_path.);
end;
run;

 


 

theponcer
Quartz | Level 8

It's not a homework question, I'm just not allowed to show exactly what I am trying to do. I just need to know the general idea. I've done something like this in the past:

 

data _null_;
array steps(*) $ step1-step8;
do i=1 to dim(steps);
	if symget(cats('run',i)) = 'Y' then
	call execute(cats('%nrstr(%call)(&step',i,')'));
end;
run;

but I'm not sure why this way works and the array way doesn't.

VDD
Ammonite | Level 13 VDD
Ammonite | Level 13

@theponcer given your above logic code you have for Doc, grummy and the 5 other dwarfs and the knowledge of arrays you are requesting how do you know that this array works

 

data _null_;
array steps(*) $ step1-step8;
do i=1 to dim(steps);
	if symget(cats('run',i)) = 'Y' then
	call execute(cats('%nrstr(%call)(&step',i,')'));
end;
run;

the communities is not here to do project management.  Is that not what you hired on for

 

 

theponcer
Quartz | Level 8

You guys always get mad at me for asking questions without giving an exact example of what I am doing in my program, because it takes more time for you to figure out what I am doing and see where I went wrong. I took the time to make a self contained example of what I am talking about and you still get mad at me? Cool. What are you talking about, project management? I am asking, why does one way work and the other way doesn't? Because I don't understand. That's actually exactly what the community is here for, in case you forgot.

 

"Stuck on a problem? Ask the community for help. 
 
While you're here, get a SAS tip and share what you know. This community of SAS experts is here to help you to succeed!"

 

ballardw
Super User

@theponcer wrote:

You guys always get mad at me for asking questions without giving an exact example of what I am doing in my program, because it takes more time for you to figure out what I am doing and see where I went wrong. I took the time to make a self contained example of what I am talking about and you still get mad at me? Cool. What are you talking about, project management? I am asking, why does one way work and the other way doesn't? Because I don't understand. That's actually exactly what the community is here for, in case you forgot.

 

"Stuck on a problem? Ask the community for help. 
 
While you're here, get a SAS tip and share what you know. This community of SAS experts is here to help you to succeed!"

 


It does not need to be an exact example but a reasonable example that includes the constraints, the inputs and the desire output.

 

This part of your attempt makes no sense in terms of your implied values.

do i=1 to dim(dwarves);
	if dwarves[i] = 'Y' then
	%include(&path./&dwarves[i]_path.);
end;

since the %INCLUDE is supposed to be called when dwarves[i] = 'Y' 

The you are generating an undefined string because there is not macro variable &dwarves defined. So you would be getting something that attempted to look like

%include (c:/path/1_path) which is not even close to your file name.

 

To top that off, you have no values for the array variables Doc Grumpy and Happy because the only input data, the set SCORES does not have those variables. It use TEST instead of Scores, which would give you those variables then you would get all sorts of errors trying to compare the value of "test**2" to 'Y'.

 

You need to spend some time with the character and array functions to build strings that actually match your files and compare to correct values.

 

You can get the name of a variable represented by an array with the function VNAME. You can concatenate a lot of bits with a CATS, CATT or CATX function.

 

Provide the ACTUAL last data step code this was supposed to generate given you Scores data set and we might be able to help.

ChrisNZ
Tourmaline | Level 20

Very creative post indeed.

 

1. >You guys ...

Rule # 1 in conflict communication: don't start the sentence with You but with I 

 

2. This can't work

set scores;
array dwarves(*) $ Doc Grumpy Happy;

 because the first 2 variables are numeric in data set SCORES.

 

3. This can't work

%include(&path./&dwarves[i]_path.);

as it would generate (if it could be resolved, see prior comment) something like 

C:/Programs/"Happy Code.sas"

which I is invalid.

 

4. Your goal seems unclear to all of us here.

 

 

Reeza
Super User

@theponcer wrote:

You guys always get mad at me for asking questions without giving an exact example of what I am doing in my program, because it takes more time for you to figure out what I am doing and see where I went wrong. I took the time to make a self contained example of what I am talking about and you still get mad at me? Cool. What are you talking about, project management? I am asking, why does one way work and the other way doesn't? Because I don't understand. That's actually exactly what the community is here for, in case you forgot.

 

"Stuck on a problem? Ask the community for help. 
 
While you're here, get a SAS tip and share what you know. This community of SAS experts is here to help you to succeed!"

 


 

 

The reason people get frustrated with your posts is because you're obfuscating the actual question by doing what you think is the right approach rather than asking what is the right approach. You question asks about running code but then your code seems to try to run things conditionally and you're trying to use arrays in a method that makes no sense within SAS. If you ask how to approach a situation such as:

 

"several people on my team are all working on the same project but different sections. Sometimes we'll need to run some sections and sometimes we'll need to run others conditionally. How do I design a process that allows me to control which programs run in a sequence?" -> Which is how I'm interpreting your question. 

 

So the answer to that question for me, would be to create a data set via a datelines statements and then use CALL EXECUTE to include the programs. 

 

data run_list;
infile cards dlm=',';
input Run_Now $1. Program $256.;
cards;
Y, C:\path to program 1.sas
N, C:\what is this program.sas
Y, C:thi sis ok.sas
;;;;

data _null_;
set run_list;
str = catt('%include "', program, '";');
if run_now = 'Y' then call execute(str);
run;

At least that's one approach. There are others but this is a pretty basic way. Instead of having that data step that creates the run commands you could also query for that or you could read it from an Excel file to have a more user driven process. 

 

If you are having people work on different parts of the same program I highly recommend they all clean up macro variables at the beginning and end fo the program as well as erasing all temporary data sets at the end that are not needed. I'm assuming you have naming conventions to avoid having named conflicts in your output. 

 

Oh, and if you're using EG, ordered lists are something you should look into. 

 

Good Luck. 

Tom
Super User Tom
Super User

The reason people get frustrated with your posts is because you're obfuscating the actual question by doing what you think is the right approach rather than asking what is the right approach. 

 

There is a name for that.  See this link:   an XY problem.

 

Tom
Super User Tom
Super User

Very creative post.

One key question that is not answered in the text is what type of programs have been created?

Normally when you talk about a "program" you mean a complete process that could include multiple steps.

But your first little data step with the comment lines looks more like you want to create little snippets of code that could be included into a single data step.

So which problem do you need to solve?  Combining multiple snippets into a single data step?  Or running a series of complete programs?  If the later is it possible that these programs have side effects that could effect the other programs?  Like deleting datasets? Or changing values or global macro variables or system options?  Would it be better to run each program in its own SAS session?

 

Also I have no idea where an ARRAY of data step variables would have any role in this problem.

ScottBass
Rhodochrosite | Level 12

%include is a macro function and, as such, resolves during program compilation, not program execution.  IOW, %included code will not get conditionally included, unless further wrapped in macro code.

 

Your attempt to intersperse data step code (array) and macro code (%include) is doomed to failure due to the timing issue of program compilation vs. program execution.

 

See if https://github.com/scottbass/SAS/blob/master/Macro/loop.sas helps.  See macro header for use cases.


Please post your question as a self-contained data step in the form of "have" (source) and "want" (desired results).
I won't contribute to your post if I can't cut-and-paste your syntactically correct code into SAS.

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
  • 10 replies
  • 1134 views
  • 1 like
  • 7 in conversation