Any time you find yourself writing the same code over and over,  you should be either thinking of a DO loop or a macro. Here is an example that jumped out at me yesterday.

The problem was this:

Every time a student answers a question in our game, it is stored in our database. After the beta-testing started, we discovered a problem with the JSON object that stored the username. In brief, it was not always recorded with the answer. How to get classroom-level data when we did not know which student was answering? We had a schedule and we knew what days and times each class was scheduled.

So, once I had my date and time separated into two different variables, all I need to do was program this logic,

If it is X date and time is between A and B, then it is this class. If time is between C and D, it is some other class.

Remember, we are in the middle of testing, so the days and times have been adjusted. At first, students used the game 3 days a week for half an hour, but then the school decided (correctly) that it would be more efficient to schedule 2 days at 45 minutes. Also, times and dates could be adjusted to accommodate holidays, teacher in-service and other reasons. To make it more complicated, we did not know the exact schedule of classes each day, just the order, for example, on October 30, Ms. Rubble’s class was using the game, followed by Ms. Flintstone’s class.

Anyway, the code looked like this:

Data findclass ;

Set inputdata ;

Minutes = round(timeoday/60) ;

Proc freq;

tables minutes ;

*** The SAS time part is the number of seconds since midnight. I rounded it to minutes to make it easier to spot a break. Then I did the frequency distribution. Since kids have to turn in the laptops and then the coordinator takes the laptops to another class and passes them out, there is going to be a break for several minutes where there is no input. That break gives the time for where one class ends and the other begins.

If date = 19290 then teacher = “Elmo” ;

ELSE if date = 19292 then DO ;

If minutes  > 800 & minutes < 850 then teacher = “Bert” ;

Else if minutes > 900 & minutes < 950 then teacher = “Big Bird” ;


ELSE if date = 19293 then DO ;

If minutes > 750 & minutes < 830 then teacher = “Elmo” ;

Else if minutes > 840 & minutes < 900 then teacher = “Big Bird” ;

Else if minutes > 840 & minutes < 900 then teacher = “Snuffy” ;


and so on .

This is an abbreviated form, but you get the idea. It didn’t take me too much typing before I thought to myself, hey, this would be an easy thing to turn into a macro. I could just give the date, the start time, end time and teacher. A little complication enters in because the same number of classes don’t occur each day, but there are couple of ways to handle that. I’ll discuss one really simple way tomorrow.

SO, I used a few DO loops, everything ran fine and I was able to create the report. This is a prime example when not to do a macro. I strongly believe that before you do a macro you need to run the code without it. See that it works exactly how you expect and then transform your working code into a macro. Never try to create a macro before seeing if it works as regular SAS code first. In that area, danger lies. Here there be dragons.

Map from very old globe

Fun fact courtesy of our friends at Wikipedia – click on the map for a larger version and you will see in the eastern part of Asia Hic Sunt Dracones (Latin for Here there be dragons) the only known use of that phrase on a map.

Having the code happily running, it is now time to turn it into a macro – tomorrow.


Leave a Reply