Sure. I will put something together tomorrow.
Building on what @Reeza posted, you can display one letter at a time by doing something like this:
ods _all_ close;
title;
footnote;
data message;
length words $10 order x y 8;
input words $;
order = _n_;
x = 100;
y = 100;
cards;
W
Wi
Wil
Will
Y
Yo
You
M
Ma
Mar
Marr
Marry
M
Me
Me?
;
run;
options papersize=('5 in', '3 in') printerpath=gif animation=start
animduration=1 animloop=no noanimoverlay nonumber nodate nobyline;
ods printer file='/folders/myfolders/demo1.gif';
ods graphics / width=5in height=3in imagefmt=gif;
proc sgplot data=message;
by order;
text x=x y=y text=words;
xaxis values=(0 to 200 by 50) display=none;
yaxis values=(0 to 200 by 50) display=none;
run; quit;
options animation=stop byline;
ods printer close;
If it turns out that you want her to run the code, then you may be able to get away with obfuscating it a bit, as long as she doesn't think too hard about it 😉
ods _all_ close;
title;
footnote;
data m;
length w $10 order x y 8;
input w $hex.;
order = _n_;
x = 100;
y = 100;
cards;
57
5769
57696c
57696c6c
59
596f
596f75
4d
4d61
4d6172
4d617272
4d61727279
4d
4d65
4d653f
;
run;
options papersize=('5 in', '3 in') printerpath=gif animation=start
animduration=1 animloop=no noanimoverlay nonumber nodate nobyline;
ods printer file='/folders/myfolders/demo2.gif';
ods graphics / width=5in height=3in imagefmt=gif;
proc sgplot data=m;
by order;
text x=x y=y text=w;
xaxis values=(0 to 200 by 50) display=none;
yaxis values=(0 to 200 by 50) display=none;
run; quit;
options animation=stop byline;
ods printer close;
Vince DelGobbo
SAS R&D
I decided to take @Vince_SAS's code as a starting point. You could still do the unveil thing I had in mind, but see what you think of this first. I grabbed a heart image off the web. You can substitute other images. Maybe a picture of the two of you together at some particularly happy time? Now I have never tried to upload all of the stuff I need to upload for this. Someone let me know if things are not working. It looks like I was wrong to try to upload the animated gif as a video. I can't seem to delete it, so ignore it. If you want something like this, I can go back and add more comments etc. I did not want to spend a lot of time on that if I was not going in the right direction.
ods _all_ close;
title;
footnote;
data message(drop=i line inc max);
length line draw $20 order x y 8;
input line $ 1-20;
x = 5; inc = 2.0; max = 11;
do i = 1 to length(line);
order + 1;
if _n_ gt 1 then do; draw = 'My Darling,'; y = max - inc; output; end;
if _n_ gt 2 then do; draw = 'Will' ; y + -inc; output; end;
if _n_ gt 3 then do; draw = 'You ' ; y + -inc; output; end;
if _n_ gt 4 then do; draw = 'Marry'; y + -inc; output; end;
draw = substr(line, 1, i);
y = max - _n_ * inc;
output;
end;
datalines;
My Darling,
Will
You
Marry
Me?
;
data annoImage;
function='image'; height=100; width=100; drawspace='GraphPercent';
image="heartjpg.jpg"; layer='back';
run;
options papersize=('4 in', '3 in') printerpath=gif animation=start
animduration=.5 animloop=yes noanimoverlay nonumber nodate nobyline;
ods printer file='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;
@WarrenKuhfeld's code to combine an image with the animated text is what I had in mind.
Not only is he a great statistician and developer, he's a mind reader, too 😉
Vince DelGobbo
SAS R&D
Maybe someone well versed in SAS fonts can suggest a nicer font to use. Script font? I also need to build in a pause after the message is completed.
Again, following Vince's lead of specifying the literal text in hex, here is a slightly more general and more easily generalizable version of the code. It uses the same image as before. I also incorporates a pause at the end before looping again. Really, it just repeats the last frame a few times.
ods _all_ close;
data words;
input line $hex40.;
datalines;
4D79204461726C696E672C202020202020202020
57696C6C20202020202020202020202020202020
596F752020202020202020202020202020202020
4D61727279202020202020202020202020202020
4D653F2020202020202020202020202020202020
;
title;
footnote;
data 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 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 message(where=(order=&maxorder)) nobs=n1;
call symputx('mino', k);
call symputx('maxo', n1);
stop;
run;
data message(drop=j k); /* Pause */
set message end=eof;
output;
if eof then do j = 1 to 5;
do i = &mino to &maxo; set message point=i; order + j; output; end;
end;
run;
data annoImage;
function='image'; height=100; width=100; drawspace='GraphPercent';
image="heartjpg.jpg"; layer='back';
run;
options papersize=('4 in', '3 in') printerpath=gif animation=start
animduration=.5 animloop=yes noanimoverlay nonumber nodate nobyline;
ods printer file='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;
@WarrenKuhfeldthis is exactly the type of thing I had in mind! I love this one! It would be nice if we can get someone to show us some different fonts for it.
Yeah, I have 2 options with actually running of the program - I can run it here, on my laptop... Or, I can sneak the images needed onto her laptop into her directory, and get it to run on there. I know enough about programming that I would need to specify the file name in the code of the program (I already saw within your code where the file names are and where I would need to do that), and that file would have to be in the directory on the machine running the program. That part wouldn't be too much of an issue for me to do. It's the actual programming within SAS of what I'm wanting to happen that is the obstacle for me. But you are helping me hurdle over that! 🙂
Okay, turns out I had thought incorrectly about where to place the image.
I downloaded your "heartjpg.jpg" image, but I have apparently not placed it into the correct folder. I'm using SAS UE. Can someone tell me where I should place that image to have it work correctly in that program code?
Once I know where to place the image, I could use my own image and change the wording a little to get it just right! 😄
Put it in myfolders you made during setup/installation and make sure to change any path references to myfolders.
Hey @Reeza
So, I changed the path to use myfolders, and I placed the 'heartjpg' image in myfolders that were created when setting up SAS, but when I run the code, it still gives the warning that the system cannot find the file. When I open the .gif to look at the final product, there is just a white box with a red "X" through it.
I don't know why it's not working, if you would be able to figure it out, perhaps? Here is the code I'm using:
ods _all_ close;
title;
footnote;
data message(drop=i line inc max);
length line draw $20 order x y 8;
input line $ 1-20;
x = 5; inc = 2.0; max = 11;
do i = 1 to length(line);
order + 1;
if _n_ gt 1 then do; draw = 'Christina, my love,'; y = max - inc; output; end;
if _n_ gt 2 then do; draw = 'Will' ; y + -inc; output; end;
if _n_ gt 3 then do; draw = 'You ' ; y + -inc; output; end;
if _n_ gt 4 then do; draw = 'Marry'; y + -inc; output; end;
draw = substr(line, 1, i);
y = max - _n_ * inc;
output;
end;
datalines;
Christina, my love,
Will
You
Marry
Me?
;
data annoImage;
function='image'; height=100; width=100; drawspace='GraphPercent';
image="heartjpg.jpg"; layer='back';
run;
options papersize=('4 in', '3 in') printerpath=gif animation=start
animduration=.5 animloop=yes noanimoverlay nonumber nodate nobyline;
ods printer file='/folders/myfolders/proposal.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;
Also, here is the destination path for the 'heartjpg' image file:
C:\Users\Brandon\Desktop\SASUniversityEdition\myfolders\heartjpg
Try adding the full path to the image file in your annoImage data set:
image='/folders/myfolders/heartjpg.jpg';
Vince DelGobbo
SAS R&D
That did it! Awesome, thank you! 🙂
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.