Hello
I want to send an email via sas with following elements:
1-Attach report (based on sashelp.class data)
2-Report on email body (based on sashelp.cars)
3-Few sentences in email body. (It was written in code as footnotes to proc report)
My question-
The sentences are written in Hebrew language .
Hebrew is written from right to left but the sentences appears in the email body from left to right.
What is the way that the Hebrew sentences appears from right to left?
ods excel file="/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.xlsx" ;
ods excel options (sheet_name='F');
proc report data=sashelp.class;
where sex='F';
column name age height weight;
define name / group;
run;
ods excel options (sheet_name='M');
proc report data=sashelp.class;
where sex='M';
column name age height weight;
define name / group;
run;
ods excel close;
title;
footnote;
filename temp email
from = "Ron.Einstein@BankLeumi.co.il"
TO=("Ron.Einstein@BankLeumi.co.il")
subject="דוח רכבי הונדה"
type="text/html"
encoding='utf-8'
attach=("/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.xlsx"
content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
ODS html body=temp ;
FOOTNOTE1 justify=right 'שלום רב,';
FOOTNOTE2 justify=right 'להלן דוח רכבי הונדה';
proc report data=sashelp.cars contents="Honda Cars";
where Make="Honda";
column ("Car" make model) ("Cost" msrp invoice) ("Fuel Efficiency" mpg_city mpg_highway);
run;
Hello, if I understand correctly you are asking to read the footnotes in SAS from right to left since they are in Hebrew.
This is possible by combining a few different functions in a data step.
First, we will define our footnote1 and footnote 2 as variables inside a data step.
data _null_; foot1 = 'שלום רב,' ; foot2 = 'להלן דוח רכבי הונדה' ; run;
The 'data _null_' step is a data step that does not create an output data set, and does not require an existing data set to read in. Think of it as a data step that just executes code and processes data without actually outputting a new data set.
The next step is to use the scan function to extract each word from foot1 and foot2.
Here I create new variables, for each word of foot1 and foot2.
Remember foot1 has 2 words (separated by 1 space) and foot2 has 4 words (separated by three spaces) so we need to scan foot1 twice and scan foot2 four times.
data _null_;
foot1 = 'שלום רב,' ;
foot2 = 'להלן דוח רכבי הונדה' ;
foot1_1 = scan(foot1,1,' ');
foot1_2 = scan(foot1,2,' ');
foot2_1 = scan(foot2,1,' ');
foot2_2 = scan(foot2,2,' ');
foot2_3 = scan(foot2,3,' ');
foot2_4 = scan(foot2,4,' ');
run;
Now to put this all together but in backwards order (right to left), use the 'catx' function to concatenate, or combine, each word starting from the last to the first.
data _null_;
foot1 = 'שלום רב,' ;
foot2 = 'להלן דוח רכבי הונדה' ;
foot1_1 = scan(foot1,1,' ');
foot1_2 = scan(foot1,2,' ');
foot2_1 = scan(foot2,1,' ');
foot2_2 = scan(foot2,2,' ');
foot2_3 = scan(foot2,3,' ');
foot2_4 = scan(foot2,4,' ');
foot1_reverse = catx(' ',foot1_2,foot1_1);
foot2_reverse = catx(' ',foot2_4,foot2_3,foot2_2,foot2_1);
run;
I used the catx function here instead of the cat function so we could add a space (' ') between each word when they are combined.
The last part of the data step is to put the values of foot1_reverse and foot2_reverse into 'macro variables' that can be passed to the footnote statement in ODS HTML.
This is done by using the 'call symputx' function, and needs to be done to pass the result of foot1_reverse and foot2_reverse to the HTML footnotes.
data _null_;
foot1 = 'שלום רב,' ;
foot2 = 'להלן דוח רכבי הונדה' ;
foot1_1 = scan(foot1,1,' ');
foot1_2 = scan(foot1,2,' ');
foot2_1 = scan(foot2,1,' ');
foot2_2 = scan(foot2,2,' ');
foot2_3 = scan(foot2,3,' ');
foot2_4 = scan(foot2,4,' ');
foot1_reverse = catx(' ',foot1_2,foot1_1);
foot2_reverse = catx(' ',foot2_4,foot2_3,foot2_2,foot2_1);
call symputx('foot1_reverse', foot1_reverse);
call symputx('foot2_reverse', foot2_reverse);
run;
Finally, you can apply the reversed strings (foot1_reverse and foot2_reverse) in the ODS HTML footnotes. Because we used the 'call symputx' function to store foot1_reverse and foot2_reverse as macro variables (so they can be used outside of the _null_ data step), we need to reference them in the footnote statements with '&'.
ods html body=temp ;
FOOTNOTE1 justify=right "&foot1_reverse";
FOOTNOTE2 justify=right "&foot2_reverse";
proc report data=sashelp.cars contents="Honda Cars";
where Make="Honda";
column ("Car" make model) ("Cost" msrp invoice) ("Fuel Efficiency" mpg_city
mpg_highway);
run;
Hope this helps!
Thank you so much,
However I think there was misunderstanding.
What you did is that you changed the order of the words in each footnote.
I only asked to move the footnote from left side to right side.
In Hebrew we read from right to left so it is better to locate the text in right side.
Please look at this email , can you see that the text is located in left side and not right side?
Ah I see. You want to place the footnotes on the right side of the page instead of the left.
This is not directly supported by default SAS functionality. However you can manually adjust the position of the footnotes.
1.
ODS HTML sends the output to an HTML file called 'Class_Report.html'.
ODS escapechar allows you to apply style changes in the footnotes.
ods html file='/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.html' style=styles.printer;
ods escapechar='^';
2.
PROC TEMPLATE lets you define a custom style template called 'styles.mystyle' that is inherited from 'style.printer'. I've linked more info on that here.
Here we set the table to be left-justified (just=l), and the footnotes to be right-justified (just=r).
proc template;
define style styles.mystyle;
parent=styles.printer;
style table / just=l ;
style footer / just=r ;
end;
run;
3.
ODS HTML applies the custom style 'styles.mystyle' to the output in HTML.
We set a right-aligned footnote1 and footnote2 using 'justify=right'.
Then insert your code and data table for the PROC REPORT part.
Finally close the ODS HTML destination.
ods html file='/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.html' style=styles.mystyle;
filename temp email
from = "Ron.Einstein@BankLeumi.co.il"
to=("Ron.Einstein@BankLeumi.co.il")
subject="דוח רכבי הונדה"
type="text/html"
encoding='utf-8' ;
footnote1 justify=right 'שלום רב,';
footnote2 justify=right 'להלן דוח רכבי הונדה';
proc report data=sashelp.cars contents="Honda Cars";
where Make="Honda";
column ("Car" make model) ("Cost" msrp invoice) ("Fuel Efficiency"
mpg_city mpg_highway);
run;
ods html close;
The code all together:
ods html file='/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.html' style=styles.printer;
ods escapechar='^';
proc template;
define style styles.mystyle;
parent=styles.printer;
style table / just=l ;
style footer / just=r ;
end;
run;
ods html file='/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.html' style=styles.mystyle;
filename temp email
from = "Ron.Einstein@BankLeumi.co.il"
to=("Ron.Einstein@BankLeumi.co.il")
subject="דוח רכבי הונדה"
type="text/html"
encoding='utf-8' ;
footnote1 justify=right 'שלום רב,';
footnote2 justify=right 'להלן דוח רכבי הונדה';
proc report data=sashelp.cars contents="Honda Cars";
where Make="Honda";
column ("Car" make model) ("Cost" msrp invoice) ("Fuel Efficiency"
mpg_city mpg_highway);
run;
ods html close;
The HTML file will now have footnote on the bottom right of the page.
Thank you
I have some questions related to your reply please:
Question1
I run your code and receive an error-ERROR: Template 'Styles.Mystyle' was unable to write to template store!
Question2
I want to add report to email body (Honda cars report) and also attach XLSX file with report related to class data.
In my code I export the class reports into XLSX file and this is the file that I want to attach.
This file is located in "/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.xlsx"
In your code I don't see that you used attachment statement.
Here is the full Log to see the error
1 The SAS System 18:42 Wednesday, July 10, 2024
1 ;*';*";*/;quit;run;
2 OPTIONS PAGENO=MIN;
3 %LET _CLIENTTASKLABEL='Program';
4 %LET _CLIENTPROCESSFLOWNAME='Process Flow';
5 %LET _CLIENTPROJECTPATH='';
6 %LET _CLIENTPROJECTPATHHOST='';
7 %LET _CLIENTPROJECTNAME='';
8 %LET _SASPROGRAMFILE='';
9 %LET _SASPROGRAMFILEHOST='';
10
11 ODS _ALL_ CLOSE;
12 OPTIONS DEV=PNG;
13 GOPTIONS XPIXELS=0 YPIXELS=0;
14 FILENAME EGSR TEMP;
15 ODS tagsets.sasreport13(ID=EGSR) FILE=EGSR
16 STYLE=HTMLBlue
17 STYLESHEET=(URL="file:///C:/Program%20Files/SASHome/SASEnterpriseGuide/7.1/Styles/HTMLBlue.css")
18 NOGTITLE
19 NOGFOOTNOTE
20 GPATH=&sasworklocation
21 ENCODING=UTF8
22 options(rolap="on")
23 ;
NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR
24
25 GOPTIONS ACCESSIBLE;
26
27 ods html file='/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.html' style=styles.printer;
NOTE: Writing HTML Body file: /usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.html
28 ods escapechar='^';
29
30 proc template;
31 define style styles.mystyle;
32 parent=styles.printer;
33 style table / just=l ;
34 style footer / just=r ;
35 end;
ERROR: Template 'Styles.Mystyle' was unable to write to template store!
36 run;
NOTE: PROCEDURE TEMPLATE used (Total process time):
real time 0.02 seconds
user cpu time 0.00 seconds
system cpu time 0.00 seconds
memory 107.34k
OS Memory 25248.00k
Timestamp 07/10/2024 06:42:23 PM
Step Count 2 Switch Count 2
Page Faults 0
Page Reclaims 101
Page Swaps 0
Voluntary Context Switches 10
Involuntary Context Switches 0
Block Input Operations 0
Block Output Operations 0
WARNING: Errors were produced.
NOTE: The SAS System stopped processing this step because of errors.
37
2 The SAS System 18:42 Wednesday, July 10, 2024
38 ods html file='/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.html' style=styles.mystyle;
NOTE: Writing HTML Body file: /usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.html
39 filename temp email
40 from = "Ron.Einstein@BankLeumi.co.il"
41 to=("Ron.Einstein@BankLeumi.co.il")
42 subject="דוח רכבי הונדה"
43 type="text/html"
44 encoding='utf-8' ;
45 /****Report in Body email+Footnotes in Body email***/
46 footnote1 justify=right 'שלום רב,';
47 footnote2 justify=right 'להלן דוח רכבי הונדה';
48 proc report data=sashelp.cars contents="Honda Cars";
49 where Make="Honda";
50 column ("Car" make model) ("Cost" msrp invoice) ("Fuel Efficiency"
51 mpg_city mpg_highway);
52 run;
NOTE: Multiple concurrent threads will be used to summarize data.
NOTE: There were 17 observations read from the data set SASHELP.CARS.
WHERE Make='Honda';
NOTE: PROCEDURE REPORT used (Total process time):
real time 0.14 seconds
user cpu time 0.02 seconds
system cpu time 0.01 seconds
memory 8507.09k
OS Memory 33972.00k
Timestamp 07/10/2024 06:42:23 PM
Step Count 3 Switch Count 1
Page Faults 0
Page Reclaims 2635
Page Swaps 0
Voluntary Context Switches 42
Involuntary Context Switches 0
Block Input Operations 0
Block Output Operations 0
53 ods html close
54
55 GOPTIONS NOACCESSIBLE;
________ ____________
1 79
76
WARNING 1-322: Assuming the symbol OPTIONS was misspelled as GOPTIONS.
ERROR 79-322: Expecting a (.
ERROR 76-322: Syntax error, statement will be ignored.
56 %LET _CLIENTTASKLABEL=;
57 %LET _CLIENTPROCESSFLOWNAME=;
58 %LET _CLIENTPROJECTPATH=;
59 %LET _CLIENTPROJECTPATHHOST=;
60 %LET _CLIENTPROJECTNAME=;
61 %LET _SASPROGRAMFILE=;
62 %LET _SASPROGRAMFILEHOST=;
63
64 ;*';*";*/;quit;run;
65 ODS _ALL_ CLOSE;
3 The SAS System 18:42 Wednesday, July 10, 2024
66
67
68 QUIT; RUN;
69
Great questions. The first question can be addressed here and here. Just add ods path (prepend) work.templat(update);
before proc template.
As for the second question, you will reference it within your ODS HTML statement.
All together your code should now be:
ods excel file = "/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.xlsx" ;
ods excel options (sheet_name='F');
proc report data=sashelp.class;
where sex='F';
column name age height weight;
define name / group;
run;
ods excel options (sheet_name='M');
proc report data=sashelp.class;
where sex='M';
column name age height weight;
define name / group;
run;
ods excel close;
ods path (prepend) work.templat(update);
ods escapechar='^';
proc template;
define style styles.mystyle;
parent=styles.printer;
style table / just=l ;
style footer / just=r ;
end;
run;
filename temp email
from = "Ron.Einstein@BankLeumi.co.il"
to=("Ron.Einstein@BankLeumi.co.il")
subject="דוח רכבי הונדה"
type="text/html"
encoding='utf-8'
attach =
("/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.xlsx"
content_type="application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet");
ods html body=temp style=styles.mystyle;
FOOTNOTE1 justify=right "שלום רב,";
FOOTNOTE2 justify=right "להלן דוח רכבי הונדה";
proc report data=sashelp.cars contents="Honda Cars";
where Make="Honda";
column ("Car" make model) ("Cost" msrp invoice) ("Fuel Efficiency" mpg_city
mpg_highway);
run;
ods html close;
Thanks a lot,
I run your code but still footnotes are written in left side and not in right side as requested for my language.
By the way, it was also better that the table also located in right side and order of columns is as you see
Here is the code I run (It is exactly your code)
/*******Export Reports to XLSX file****/
/*******Export Reports to XLSX file****/
/*******Export Reports to XLSX file****/
ods excel file = "/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.xlsx" ;
ods excel options (sheet_name='F');
proc report data=sashelp.class;
where sex='F';
column name age height weight;
define name / group;
run;
ods excel options (sheet_name='M');
proc report data=sashelp.class;
where sex='M';
column name age height weight;
define name / group;
run;
ods excel close;
ods path (prepend) work.templat(update);
ods escapechar='^';
proc template;
define style styles.mystyle;
parent=styles.printer;
style table / just=l ;
style footer / just=r ;
end;
run;
filename temp email
from = "Ron.Einstein@BankLeumi.co.il"
to=("Ron.Einstein@BankLeumi.co.il")
subject="דוח רכבי הונדה"
type="text/html"
encoding='utf-8'
/**Attach |Report XLSX FILE that we created before****/
attach = ("/usr/local/SAS/SASUsers/LabRet/UserDir/udclk79/Class_Report.xlsx"
content_type="application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet");
ods html body=temp style=styles.mystyle;
/****Report in Body email+Footnotes in Body email***/
FOOTNOTE1 justify=right "שלום רב,";
FOOTNOTE2 justify=right "להלן דוח רכבי הונדה";
proc report data=sashelp.cars contents="Honda Cars";
where Make="Honda";
column ("Car" make model) ("Cost" msrp invoice) ("Fuel Efficiency" mpg_city mpg_highway);
run;
ods html close;
I ran your code on SAS On Demand and sent the email to myself.
I opened the email on my Mac, using the MacOS standard mail client.
The footnotes are right-justified, as they should be.
On my Android table, Gmail showed them left-justified.
So I think your email client is the culprit, as is Android Gmail.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
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.