If you do want to hide the text in the program, here is how I generated the hex lines that I read.
data _null_;
input line $ 1-20;
put line $hex40.;
datalines;
My Darling,
Will
You
Marry
Me
;
data words;
input line $hex40.;
datalines;
... put the hex log lines here ...
;
I am going to defer to someone else on working directories in University edition.
This document briefly discusses Shared Folders in SAS University Edition:
SAS University Edition: Help Center
What is a shared folder?
https://support.sas.com/software/products/university-edition/faq/shared_folder_whatis.htm
The links in the "Additional topics" box toward the bottom of the page tell you how to set up the shared folders, and how to reference them from your SAS program.
Vince DelGobbo
SAS R&D
How is she running SAS? If she is using SAS Display Manager then you need to put the files in one place. If using SAS Enterprise Guide with SAS on a remote server, then the files need to be placed somewhere else. Both of these locations are quite different from each other and from the SAS University Edition location.
It can get tricky and is prone to error, so if you go that route, test, test, test!
Vince DelGobbo
SAS R&D
Hi, @grandpastyle13. I don't have anything technical to add but wanted to commend you on this fun and original idea!
Randy
So, I really like the way that this program works, @WarrenKuhfeld. This one is exactly what I was hoping to achieve with this. You're okay with me using it?
There's only one other thing that I want to know - is it possible to have the program kind of "pause" for a few frames after the full message is displayed? It quickly just starts to rewrite the message once it completes.
You can specify animloop=1 in the OPTIONS statement to stop the animation after it runs for a single cycle.
Vince DelGobbo
SAS R&D
I made that change in the code, but it still loops the animation after it completes.
I'm using a different version of @WarrenKuhfeld's code (below) and it worked for me. I like this version because everything is obfuscated.
You can tell her that you've been learning SAS in your spare time and that you would like to show her a program. But before you do, go to the Results section in SAS Studio Preferences dialog and deselect Automatically open generated output data. You don't want SAS Studio to display the data set with the unobfuscated message.
Then:
Vince DelGobbo
SAS R&D
ods _all_ close;
title;
footnote;
data work.words;
input line $hex40.;
datalines;
4D79204461726C696E672C202020202020202020
57696C6C20202020202020202020202020202020
596F752020202020202020202020202020202020
4D61727279202020202020202020202020202020
4D653F2020202020202020202020202020202020
;
run;
data work.message(drop=i line inc max);
length draw $ 20;
set words;
x = 5; inc = 2.0; max = 11;
do i = 1 to length(line);
order + 1; y = max;
do j = 1 to _n_ - 1;
set work.words(rename=(line=draw)) point=j; y + -inc; k + 1; output;
end;
draw = substr(line, 1, i);
y = max - _n_ * inc;
k + 1; output;
end;
call symputx('MAXORDER', order);
run;
data _null_;
set work.message(where=(order=&maxorder)) nobs=n1;
call symputx('MINO', k);
call symputx('MAXO', n1);
stop;
run;
data work.message(drop=j k); /* Pause */
set work.message end=eof;
output;
if eof then do j = 1 to 5;
do i = &MINO to &MAXO;
set work.message point=i;
order + j;
output;
end;
end;
run;
data work.annoImage;
function = 'image';
height = 100;
width = 100;
drawspace = 'GraphPercent';
image = '/folders/myfolders/heart.jpg';
layer = 'back';
run;
options papersize=('4 in', '3 in') printerpath=gif animation=start
animduration=.5 animloop=1 noanimoverlay nonumber nodate nobyline;
ods printer file='/folders/myfolders/demo1.gif';
ods graphics / width=4in height=3in imagefmt=gif;
proc sgplot data=message nowall noborder noautolegend sganno=annoimage;
by order;
text x=x y=y text=draw / textattrs=(size=38 weight=bold color=white style=italic);
xaxis values=(0 to 10) min=0 max=10 display=none;
yaxis values=(0 to 10) min=0 max=10 display=none;
run; quit;
options animation=stop byline;
ods printer close;
Ahh... this is quite sly. I like it! How can I change the first line of the message to read "Christina, my love,"?
Would I have to translate the hex in the code to regular text, remove the first part, and put what I'm wanting it to display in the code as hex?
@Vince_SASAlright, so I tried to change the hex numbers myself, and now the spacing of the last 3 lines of text is all funky. So, I guess I messed it up somehow? Hahaha... 😞
It does display what I want it to say, though.
Did you try @WarrenKuhfeld's code here to create the hex data?
The first DATA step writes the hex data to the log, and you can copy-and-paste it from there.
Vince DelGobbo
SAS R&D
No need to copy and paste! You write the message to a file. e.g. (just adding to Vince's code):
data _null_; input line $ 1-20; file '/folders/myfolders/hexlines.txt'; put line $hex40.; datalines; Christina, my love Will You Marry Me ; data words; infile '/folders/myfolders/hexlines.txt'; input line $hex40.; run; data work.message(drop=i line inc max); length draw $ 20; set words; x = 5; inc = 2.0; max = 11; do i = 1 to length(line); order + 1; y = max; do j = 1 to _n_ - 1; set work.words(rename=(line=draw)) point=j; y + -inc; k + 1; output; end; draw = substr(line, 1, i); y = max - _n_ * inc; k + 1; output; end; call symputx('MAXORDER', order); run; data _null_; set work.message(where=(order=&maxorder)) nobs=n1; call symputx('MINO', k); call symputx('MAXO', n1); stop; run; data work.message(drop=j k); /* Pause */ set work.message end=eof; output; if eof then do j = 1 to 5; do i = &MINO to &MAXO; set work.message point=i; order + j; output; end; end; run; data work.annoImage; function = 'image'; height = 100; width = 100; drawspace = 'GraphPercent'; image = '/folders/myfolders/heart.jpg'; layer = 'back'; run; options papersize=('4 in', '3 in') printerpath=gif animation=start animduration=.5 animloop=1 noanimoverlay nonumber nodate nobyline; ods printer file='/folders/myfolders/demo1.gif'; ods graphics / width=4in height=3in imagefmt=gif; proc sgplot data=message nowall noborder noautolegend sganno=annoimage; by order; text x=x y=y text=draw / textattrs=(size=38 weight=bold color=white style=italic); xaxis values=(0 to 10) min=0 max=10 display=none; yaxis values=(0 to 10) min=0 max=10 display=none; run; quit; options animation=stop byline; ods printer close;
Art, CEO, AnalystFinder.com
@art297 shows a nice technique, but I wouldn't use it in this case. We don't want the future Missus' eyes to see the message too soon. For this reason it's better to run the hex-generation code separately, and then use the encoded strings in the full code stream.
Now if she figures out the message from a quick scan of the hex strings while @grandpastyle13 proudly shows the code, then I would say that he found a real keeper
Vince DelGobbo
SAS R&D
@Vince_SASHahaha, she's a real keeper already. But I don't think she knows how to read hex. This is definitely going to be a complete surprise.
I have everything set now the way that I have wanted it to be, so I will make another reply and post the code and image that I'm going to use so anyone can see it, if they like.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.