I refer here to the the issue addressed 6 years ago in "SAS GRAPH and multiple charts, more meaningful names?" To me this issue needs a solution. I need to generate one chart by indicator (2) and country (27). The index is 1,3,5,7,9,...,107. Please try to find the file/worksheet (png/xls) for country x and indicator y. Good luck! Can somebody help me? Maybe the person who addressed the issue at that time found a solution (I really hope it)? Many thanks!
Below you have an example using sashelp library. It creates Picture1.png, Picture3.png and Picture5.png. Instead of this, I would like to have PictureIBM.png, PictureIntel.png and PictureMicrosoft.png.
proc sort data=SASHELP.STOCKS out=testfile; by stock date; run;
data testfile; set testfile;
by stock ;
retain n;
if first.stock then n=0; else n=n+1;
if n le 5;
run;
ods listing gpath='write the path' ;
ods listing /*style = styles.new_font */
gpath='/ec/prod/1eusilc/flashestimates/FLIPI/3_Output/FE/PERFORMANCE/overall 2022/TIME SERIES' ;
ods graphics on /
width=14in height=10in
outputfmt=gif
imagemap=on
imagename="Picture"
border=off reset=index ;
proc sgplot data=testfile noborder noopaque nowall dattrmap=DATTRMAP
title "write the title";
by stock ;
highlow x=date low=low high=high / type=bar ;
scatter x=date y=close ;
xaxis type=discrete;
run;
Here are two ways to do this, one uses the #byval as indicated in the previous solution and which you used in title but not the file name for some reason.
First make fake data:
data prdsummary;
set sashelp.prdsale;
where year=1993 and (country="GERMANY" or country="CANADA") and region="EAST"
and division="CONSUMER" and
(product="SOFA" or product="TABLE" or product="BED");
run;
proc sort data=prdsummary;
by country;
run;
Then use #BYVAL. However, if you run this code multiple times, SAS does not overwrite the previous files, it adds a 1 to the filename instead. So you need to make sure that the files don't already exist. There may be an option to control this feature, I'm unsure at the moment.
ods listing gpath='/home/fkhurshed/Demo1/';
title 'Graph for #byval1';
ods graphics / imagename="Country #byval1";
proc sgplot data=prdsummary;
by country;
vbar prodtype / group=product response=actual groupdisplay=stack;
run;
A second workaround is to use a macro instead and control the name explicitly.
*explicitly control the names via macro looping;
ods listing gpath='/home/fkhurshed/Demo1/';
%macro generate_country_graph(country=);
ods graphics / imagename="Graphic for &Country.";
proc sgplot data=prdsummary;
where country="&country";
vbar prodtype / group=product response=actual groupdisplay=stack;
run;
%mend;
data _null_;
set prdsummary;
by country;
if first.country then
do;
str=catt('%generate_country_graph(country=', country, ');');
call execute(str);
end;
run;
Related
I got a problem with Hyperlink generated by SAS ODS EXCEl.
I'm using SAS9.4TM3 and EXCEL 2013.
I coded this
data lst_tie;
NUM_TIE = '2900004227803';
output;
NUM_TIE = '2900004233852';
output;
run;
data lst_tie(drop=HL);
set lst_tie;
format HL2 $500.;
HL = "http://tier-kh.cm-cic.fr/tie6_tiers/default.aspx?trt=tiesyn&banque=02297&caisse=38848&tiers="||NUM_TIE;
HL2 = '=LIEN_HYPERTEXTE("'||HL||'";"'||NUM_TIE||'")';
run;
ods excel file = "$GRPFPU/test_tiesyn.xlsx"
options (absolute_column_width="3cm,20cm,20cm");
proc report data=lst_tie
;
column NUM_TIE
HL2;
define num_tie / "Numero" style(column)={ width=100%};
define HL2 / "Tiers" style(column)={tagattr='wraptext:no' width=100%};
quit;
ods excel close;
The URL seems well encoded :
=LIEN_HYPERTEXTE("http://tier-kh.cm-cic.fr/tie6_tiers/default.aspx?trt=tiesyn&banque=02297&caisse=38848&tiers=2900004227803";"2900004227803")
without carriage return (CR).
But, on opening the XLSX file there is a CR characters just after LIEN_HYPERTEXTE (HYPERLINK in English)
XLSX Preview 1
But if I delete the CR so the hyperlink is OK.
XLSX OK
I tried several option as WIDTH_COLUMS, Wrap Option , but no way.
Thanks
ODS EXCEL is trying to make your printout pretty by inserting physical line breaks into long lines. Apparently it doesn't notice that your value is a formula instead of plain text.
Starting with SAS 9.4M4 you can add flow="tables" to the ODS statement. See this SAS Blog post
ods excel file = "$GRPFPU/test_tiesyn.xlsx"
options (absolute_column_width="3cm,20cm,20cm"
flow="tables"
)
;
For older versions of SAS, like yours, try making the column wider so it doesn't try to wrap it. Try adding width=1000% instead of width=100% to the column with the links.
define HL2 / "Tiers" style(column)={tagattr='wraptext:no' width=1000%};
To have a clickable hyperlink I add a format
``
data lst_tie;
NUM_TIE = '2900004227803';
output;
NUM_TIE = '2900004233852';
output;
run;
data lst_tie;
set lst_tie;
format HL2 $500.;
HL = "http://tier-kh.cm-cic.fr/tie6_tiers/default.aspx?trt=tiesyn&banque=02297&caisse=38848&tiers="||NUM_TIE;
run;
data one;
set lst_tie;
retain fmtname '$urltie';
rename NUM_TIE=start;
label = HL;
run;
proc format cntlin=one;
run;
ods excel file = "$GRPFPU/test_tiesyn.xlsx"
options (absolute_column_width="3cm,20cm,20cm" flow="tables");
proc report data=lst_tie
;
column NUM_TIE
;
define num_tie / "Numero" style(column)={TAGATTR='format:0' width=1.5in url=$urltie. color=cx0000FF textdecoration=underline /*tagattr='wraptext:no' width=100%*/
};
quit;
ods excel close;
``
ODS EXCEL FILE="/mypoath/myfile.xlsx" options(
frozen_headers="3"
sheet_name="#byval1");
PROC TABULATE data=out;
BY byVariable;
CLASS varA varB;
TABLES varA, varB;
RUN;
ODS EXCEL CLOSE;
The code above creates an excel-file with different sheets. There is one sheet for each value of the variable byVariable. Is there a way to create an additional sheet "ALL" which contains the results for all values of the byVariable together? I mean something like "ALL" (used in the TABLES-section). I tried BY ALL byVar already (which doesn't work).
Thanks for help!
The simple answer is NO. If you want all of the data then don't use the BY statement.
ODS EXCEL FILE="/mypoath/myfile.xlsx" options(frozen_headers="3");
ODS EXCEL options(sheet_name="ALL");
PROC TABULATE data=out;
CLASS varA varB;
TABLES varA, varB;
RUN;
ODS EXCEL options(sheet_name="#byval1");
PROC TABULATE data=out;
BY byVariable;
CLASS varA varB;
TABLES varA, varB;
RUN;
ODS EXCEL CLOSE;
There is no such option.
You can:
rerun the report without BY, or
stack the data on itself modifying the by variable to be ALL -- such that it is higher than all existant by values.
data stacked / view=stacked;
set
have
have (in=stackflag)
;
if stackflag then do;
byvar = 'A0'x || 'ALL'; * A0 forces value to be 'after' other original byVar values;
end
run;
proc tabulate data=stacked;
by byvar;
…
Note: 'A0'x is a hard space ASCII character
so I have a code like this, when this executes
data t4;
put new_EMPLID $2000.;
do until(last.CRSE_ID);
set t3;
by CRSE_ID notsorted;
new_EMPLID = catx(',',new_EMPLID,compress(EMPLID));
END;
drop EMPLID;
run;
output on SAS is
THEN "View in Excel"
I want to show LIKE THIS "2234944,2330002" exactly like output on SAS
Why excel is changing like pic? Does anybody know how to fix this issue???
I know , is cauing issue, when I changed to 'x', it worked on excel.
What operating system, SAS version and Excel version and bittiness of each ?
What code did you submit ?
This sample code with Proc EXPORT exhibits no issues in Windows 10, SAS 9.4M4 and Excel 2016 64-bit.
If a courseId has only one attendee, or the if commas could be misinterpreted by Excel they will be :). Your language settings can also have influence the Excel rendering.
data have; input
courseId employeeId; datalines;
1 2234944
1 2330002
1 1975365
1 2244221
2 1122334
2 2233445
2 3344551
run;
data want;
do until (last.courseId);
set have;
by courseId;
length attendeeList $2000;
attendeeList = catx(',',attendeeList,employeeId);
end;
drop employeeId;
run;
proc export data=want dbms=excel replace file='c:\temp\course_attendence.xlsx';
run;
I am quite new to SAS. I have got a file with file extension .sas7bdat which contains daily stocks prices and percentage changes. It has almost 2 million line items. I know that I can simply double click the file and open it with SAS 9.4. But, I am looking for codes which I can type in Editor and open this file. Please help me.
After I open this file, I need to export it to excel. Since it has 2 million data, I can not export everything in a single excel tab. So, What I want to do it randomly pick (say 10,000 or 20,000) data and export only this randomly picked data to excel.
My .sas7bdat file is on desktop.
Please help.
You can use surveyselect and specify the number of records you want in your subset the use proc export.
In my Example below I create a table of 10 rows and only wanted 5 row in the subset. just change the value in my macro variable from 5 to 100000
Code:
data have;
input value;
datalines;
1
2
3
4
5
6
7
8
9
10
;
run;
%let subset=5;
proc surveyselect data=have
method=srs n=&subset. out=want;
run;
Output:
value=1
value=2
value=5
value=6
value=10
Exporting:
proc export data=sashelp.class
outfile='c:\myfiles\want.csv'
dbms=csv
replace;
run;
You can also filter on the data you are exporting, dummy example below:
proc export data=want (where=(value > 100 or location='X'))
outfile='c:\myfiles\want.csv'
dbms=csv
replace;
run;
You can use ODS. This will be simpler, but generate a file which will give warning in opening first time
libname rd_data "<Your Path to dataset>"
data temp;
set rd_data.<dataset name>;
rnd = ranuni(123456);
run;
proc sort data = temp out = temp(drop=rnd);
by rnd;
run;
**** Remember this is .xls file, not .xlsx
ods html file = <xls file path - full path>;
proc print data = temp(obs=1000);
run;
ods html close;
Alternatively, you can use DDE (Dynamic Data Exchange)
First, create a library to point to the location on the file system where the data set resides. This is a pointer (in C terms) to the directory.
libname myData "<path to folder>";
From there you can use a random number and a data step to get N random values. Alternatively, PROC SURVEYSELECT can be used, but you might not have it licensed.
data temp;
set myData.<Data Set Name>;
__rnd = ranuni(1);
run;
proc sort data=temp ;
by __rnd;
run;
data toOutput;
set temp(obs=10000 drop=__rnd);
run;
The last Data Step reads in just the first 10,000 records which you randomized above.
Then you can use PROC EXPORT to export the values.
proc export data=toOutput outfile="c:\temp\output.xlsx" dbms=xlsx replace;
sheet="MyData";
run;
The great thing here is that you can create other sheets in the file with additional exports.
proc export data=toOutput outfile="c:\temp\output.xlsx" dbms=xlsx replace;
sheet="MyData2";
run;
This would allow you to create multiple samples or even export all the data across multiple sheets.
I am wondering if there is a way of defining when and where page breaks occur when using a macro to output data. I know within the various ODS tagests the "Startpage=NOW" can be used but that does not seem to work if a macro is used inside that tagset. So basically I want the two tables, and graph for each personal ID code to be on a single and the next page contains the same summary graphs, charts for that individual, and etc. Currently I can only get every table and chart to its own individual page which makes for a lengthy report! Any help/suggestions would be appreciated!
/*************************************************************************/
/* Create a macro variable of all the ID codes */
/* */
/*************************************************************************/
proc sql noprint;
select personal_id
into :varlist separated by ' ' /*Each identifier code in the list is sep. by a single space*/
from provider;
quit;
%let cntlist = &sqlobs; /*Store a count of the number of id codes*/
%put &varlist; /*Print the codes to the log to be sure our list is accurate*/
ods tagsets.rtf file="C:\USER\test.doc" style=sasdocprinter;
/* macro for generating the output table*/
%macro output(x);
proc print data=prov_&x;
run;
proc print data=prov_revCD_&x;
run;
/*Print graph to template defined earlier*/
ods graphics on / height=500px width=500px;
proc sgrender data=summary_&x template=corf_graphs;
run;
ods graphics on / reset=all;
%mend;
%macro loopit(mylist);
%let else=;
%let n = %sysfunc(countw(&mylist)); /*let n=number of codes in the list*/
data
%do I=0 %to &n;
%let val = %scan(&mylist,&I); /*Let val= the ith code in the list*/
%end;
/*Run a loop for each oscar code. Each code will enter the
%do j=0 %to &n;
%let val = %scan(&mylist,&j); /*Let val= the jth code in the list*/
/*Run the macro loop to generate the required tables*/
%runtab(&val);
%output(&val);
%end;
run;
%mend;
%loopit(&varlist)
/*Run the macro loop over the list of significant procedure code values*/
ods tagsets.rtf close;
Macros are nothing but source code generation devices. They have no impact on the effectiveness of any particular technique, except insomuch as their (mis)use may make it more difficult to see how to do it properly.
In this case, if you want the entirety of each single iteration of %output() to be on one page, then you simply need to add a startpage now before the %output(&val) call.
%runtab(&val);
ods tagsets.rtf startpage=now;
%output(&val);
%end;
That will produce a startpage instruction immediately before the output. You could just as easily include it in the %output macro, if you will always want a new page before a call of it.
I inserted the startpage=NOW where suggested and it inserted a blank page, after playing around with the placement and looking at what the code is doing this following snip it ended up working:
ods tagsets.rtf startpage=NOW;
%runtab(&val);
%output(&val);
ods tagsets.rtf startpage=no;
%end;
Beyond the use of macro, you can also consider the use of pagebywith proc print to split page for you.
See this link for PageBY