BookmarkSubscribeRSS Feed
Ronein
Meteorite | Level 14

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;
7 REPLIES 7
procphysics
SAS Employee

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!

Ronein
Meteorite | Level 14

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?

Ronein_0-1720586825291.png

 

 

procphysics
SAS Employee

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.

 

Ronein
Meteorite | Level 14

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         

 

 

 

procphysics
SAS Employee

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;

 

 

Ronein
Meteorite | Level 14

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 

Ronein_0-1720640091795.png

 

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;
Kurt_Bremser
Super User

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.

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 7 replies
  • 435 views
  • 0 likes
  • 3 in conversation