How can I protect my excel file with a password, because in sas EG not supported DDE.
I'm using this, but I dont have the convert.vbs, so where can i get it?
/***********************************************/
/* Create a test worksheet to password protect */
/***********************************************/
ods tagsets.excelxp file="c:\temp.xml";
proc print data=sashelp.class;
run;
ods tagsets.excelxp close;
/*****************************************************************/
/* Create and excecute a script file using the input XML file */
/* and the converted XLSX file. The value 51 is needed for XLSX. */
/* Use the value of 1 for XLS files in the SaveAs command. */
/*****************************************************************/
%let XMLfile = c:\temp.xml;
%let ExcelFile = c:\temp.xlsx;
%let VBscript = ***c:\convert.vbs***;
%let password=test;
data _null_;
file "&vbscript" lrecl=200;
put 'Dim xlApp, xlWkb, SourceFile, TargetFile';
put 'Set xlApp = CreateObject("excel.application")';
put 'SourceFile="' "&XMLfile" '"';
put 'Set xlWkb = xlApp.Workbooks.Open(SourceFile)';
put 'TargetFile="' "&ExcelFile" '"';
put 'xlApp.DisplayAlerts=false';
put "xlWkb.SaveAs TargetFile, 51,""&password""";
put 'xlApp.DisplayAlerts=true';
put 'xlWkb.close';
run;
options noxwait noxsync;
x "cscript ""&vbscript""";
It appears that your code creates the file c:\convert.vbs for you and then runs it. You just need to remove the asterisks so that it's a valid file path.
If you don't have DDE it's unlikely that code will work for you either.
The last line,
x "cscript ""&vbscript""";
Is a command to your operating system. Often if DDE is disabled, this type of functionality is also disabled. You can check this by examining the XCMD option.
proc options option=xcmd;
run;
If XCMD is enabled you'll see:
XCMD Enables the X command in SAS.
You can only change that setting at start up and sometimes need to be an administrator as well.
Related
Good Morning
So I have tried to download zip file from the website, and try to assign the location.
The location I want to put is
S:\Projects\
Method1,
First Attempt is below
DATA _null_ ;
x 'start https://yehonal.github.io/DownGit/#/home?url=https:%2F%2Fgithub.com%2FCSSEGISandData%2FCOVID-19%2Ftree%2Fmaster%2Fcsse_covid_19_data%2Fcsse_covid_19_daily_reports';
RUN ;
Method1, I can download the file, but this automatically downloaded to my Download folder.
Method 2,
so I found out this way.
filename out "S:\Projects\csse_covid_19_daily_reports.zip";
proc http
url='https://yehonal.github.io/DownGit/#/home?url=https:%2F%2Fgithub.com%2FCSSEGISandData%2FCOVID-19%2Ftree%2Fmaster%2Fcsse_covid_19_data%2Fcsse_covid_19_daily_reports'
method="get" out=out;
run;
But the code is not working, not downloading anything.
how can I download the file from the web and assign to the certain location?
I would probably recommend a macro in this case then (or CALL EXECUTE) but I prefer macros and then calling the macro via CALL EXECUTE. Took about a minute running on SAS Academics on Demand (free cloud service).
*set start date for files;
%let start_date = 01-22-2020;
*macro to import data;
%macro importFullData(date);
*file name reference;
filename out "/home/fkhurshed/WANT/&date..csv";
*file to download;
%let download_url = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports/&date..csv";
proc http url=&download_url
method="get" out=out;
run;
*You can add in data import/append steps here as well as necessary;
%mend;
%importFullData(&start_date.);
data importAll;
start_date=input("&start_date", mmddyy10.);
*runs up to previous day;
end_date=today() - 1;
do date=start_date to end_date;
formatted_date=put(date, mmddyyd10.);
str=catt('%importFullData(', formatted_date, ');');
call execute(str);
end;
run;
The url when viewed in a browser is using javascript in the browser to construct a zip file that is automatically downloaded. Proc HTTP does not run javascript, so will not be able to download the ultimate response which is the constructed zip file, thus you get the 404 message.
The list of the files in the repository can be obtain as json from url
https://api.github.com/repos/CSSEGISandData/COVID-19/contents/csse_covid_19_data/csse_covid_19_daily_reports
The listing data contains the download_url for each csv file.
A download_url will look like
https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports/01-22-2020.csv
You can download individual files with SAS per #Reeza, or
use git commands or SAS git* functions to download the repository
AFAIK git archive for downloading only a specific subfolder of a repository is not available surfaced by github server
use svn commands to download a specific folder from a git repository
requires svn be installed (https://subversion.apache.org/) I used SlikSvn
Example:
Make some series plots of a response by date from stacked imported downloaded data.
options noxwait xsync xmin source;
* use svn to download all files in a subfolder of a git repository;
* local folder for storing data from
* COVID-19 Data Repository by the Center for Systems Science and Engineering (CSSE) at Johns Hopkins University;
%let covid_data_root = c:\temp\csse;
%let rc = %sysfunc(dcreate(covid,&covid_data_root));
%let download_path = &covid_data_root\covid;
%let repo_subdir_url = https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_daily_reports;
%let svn_url = %sysfunc(tranwrd(&repo_subdir_url, tree/master, trunk));
%let os_command = svn checkout &svn_url "&download_path";
/*
* uncomment this block to download the (data) files from the repository subfolder;
%sysexec %superq(os_command);
*/
* codegen and execute the PROC IMPORT steps needed to read each csv file downloaded;
libname covid "&covid_data_root.\covid";
filename csvlist pipe "dir /b ""&download_path""";
data _null_;
infile csvlist length=l;
length filename $200;
input filename $varying. l;
if lowcase(scan(filename,-1,'.')) = 'csv';
out = 'covid.day_'||translate(scan(filename,1,'.'),'_','-');
/*
* NOTE: Starting 08/11/2020 FIPS data first starts appearing after a few hundred rows.
* Thus the high GuessingRows
*/
template =
'PROC IMPORT file="#path#\#filename#" replace out=#out# dbms=csv; ' ||
'GuessingRows = 5000;' ||
'run;';
source_code = tranwrd (template, "#path#", "&download_path");
source_code = tranwrd (source_code, "#filename#", trim(filename));
source_code = tranwrd (source_code, "#out#", trim(out));
/* uncomment this line to import each data file */
*call execute ('%nrstr(' || trim (source_code) || ')');
run;
* memname is always uppercase;
proc contents noprint data=covid._all_ out=meta(where=(memname like 'DAY_%'));
run;
* compute variable lengths for LENGTH statement;
proc sql noprint;
select
catx(' ', name, case when type=2 then '$' else '' end, maxlen)
into
:lengths separated by ' '
from
( select name, min(type) as type, max(length) as maxlen, min(varnum) as minvarnum, max(varnum) as maxvarnum
from meta
group by name
)
order by minvarnum, maxvarnum
;
quit;
* stack all the individual daily data;
data covid.all_days;
attrib date length=8 format=mmddyy10.;
length &lengths;
set covid.day_: indsname=dsname;
date = input(substr(dsname,11),mmddyy10.);
format _character_; * reset length based formats;
informat _character_; * reset length based informats;
run ;
proc sort data=covid.all_days out=us_days;
where country_region = 'US';
by province_state admin2 date;
run;
ods html gpath='.' path='.' file='covid.html';
options nobyline;
proc sgplot data=us_days;
where province_state =: 'Cali';
*where also admin2=: 'O';
by province_state admin2;
title "#byval2 County, #byval1";
series x=date y=confirmed;
xaxis valuesformat=monname3.;
label province_state='State' admin2='County';
label confirmed='Confirmed (cumulative?)';
run;
ods html close;
options byline;
Plots
I'm writing a SAS program to interact with an API. I'm trying to use SAS to capture a specific field from a text file generated by the API.
The generated text "resp" looks like this:
{"result":{"progressId":"ab12","percentComplete":0.0,"status":"inProgress"},"meta":{"requestId":"abcde123","httpStatus":"200 - OK"}}
The field I want to capture is "progressID". In this case, it would be "ab12". If the length of progressID will change, what's the easiest way to capture this field?
My current approach is as follows:
/* The following section will import the text into a SAS table,
seperated by colon. The third column would be "ab12","percentCompelte"
*/
proc import out = resp_table
datafile= resp
dbms = dlm REPLACE;
delimiter = ':';
GETNAMES = NO;
run;
/* The following section will trim off the string ,"percentCompete"*/
data resp_table;
set resp_table;
Progress_ID = SUBSTR(VAR3,2,LENGTH(VAR3)-20);
run;
Do you have an easier/ more concise solution?
Thanks!
Shawn
You can use the JSON library engine to read a json document, and copy the contents to SAS datasets. Work with the data items that the engine creates.
Example:
filename myjson "c:\temp\sandbox.json";
data _null_;
file myjson;
input;
put _infile_;
datalines;
{"result":{"progressId":"ab12","percentComplete":0.0,"status":"inProgress"},"meta":{"requestId":"abcde123","httpStatus":"200 - OK"}}
run;
libname jsondoc json "c:\temp\sandbox.json";
proc copy in=jsondoc out=work;
run;
proc print data=work.Alldata;
where P1='result' and P2='progressId';
run;
I wanna append string to a text file at beginning and end of proc sql statment, I tried like below
libname DXZ 'libpath';
%macro processlogger(msg);
filename logfile '../Processlog/processlog.txt';
data _null_;
file logfile;
put "%superq(message)";
run;
%mend;
%processlogger ('Begin');
proc sql;
select * from DZ.NoofDaysin_Reje /* Mispelled name */
run;
%processlogger('End');
I seems to messing up in macro variable, is there any other way I can do this, Thanks
If you want to use a data step to append to a text file then you need to add the MOD keyword to the FILE statement.
If you want to print the value of a macro variable that might have quotes and other strange characters in a data step then it is probably best to use symget() to retrieve the value into a datastep variable and print that.
Make sure to reference the macro variable that you created msg and not some other macro variable message.
If you don't want quotes to be included in the value of a macro variable then do not add them.
%macro processlogger(msg);
data _null_;
file '../Processlog/processlog.txt' mod;
length message $32767 ;
message=symget('msg');
put message ;
run;
%mend;
%processlogger(Starting at %sysfunc(datetime(),datetime24.3));
%processlogger(Ending at %sysfunc(datetime(),datetime24.3));
You can also use PRINTTO to redirect your log to a text file. And you have the option to either append to the original file or replace. Example here.
/*Redirect your log file*/
proc printto log='../Processlog/processlog.txt';
run;
/* Your Code Here */
/* Reset log path to default */
proc printto;
run;
I have just started learning SAS, and I'm using the following code to read xlsx files:
proc import out = data_lib.dataset_1
datafile = 'C:\data_folder\data_file_1.xlsx'
dbms = xlsx replace;
sheet = 'Sheet1';
getnames = yes;
run;
This has been working fine for me, but I'd like to supply the code with a list of filenames to read and a list of dataset names to create, so that the code need only appear once. I have looked at several instructional web pages about using macros, but I've been unable to translate that information into working code. Any help would be greatly appreciated. I'm using SAS 9.4, 64 bit.
I'd offer a modified version of kl78's suggestion, avoiding macros. Again, assuming you have the file names in a SAS data set, use a data step to read the list of file names and use call execute to run your proc import code for each file name.
data _null_;
set t_list;
call execute (
"proc import out = " || datasetname || "
datafile = '"|| filename ||"'
dbms = xlsx replace;
sheet = 'Sheet1';
getnames = yes;
run;");
run;
So, suppose you have your filenames and datanames in a table called t_list with variablename datasetname and filename, you could try something like this:
%macro readexcels;
data _null_;
set t_list (nobs=nobs);
call symputx(cat("libname_",_n_), datasetname);
call symputx(cat("filename_",_n_), filename);
if _n_=1 then
call symputx("nobs", nobs);
run;
%do i=1 %to &nobs;
proc import out = &&libname_&i;
datafile = "&&filename_&i"
dbms = xlsx replace;
sheet = 'Sheet1';
getnames = yes;
run;
%end;
%mend;
%readexcels;
In the datastep you read every entry of your table with datasetname and listname and create macrovariables with a numeric suffix. You only need to create a macrovariable for the number of entries once, so i did it when n = 1, you could also do this at eof.
Then you have a do loop, and with every loop you read the specific excel and write it in the specific dataset.
You need to write it like &&libname&i, because at first this resolves to &libname_1, and after this resolves to the variablevalue...
Is there a way to open a SAS dataset for viewing (i.e., in the "ViewTable" window) from within a .sas file?
I think this will do what you want:
dm log "vt sashelp.air";
Just change the "sashelp.air" part to your lib.table combo.
dw.mackie's answer is right on the money. That works great when submitted from the SAS editor window.
But I just want to caution you to be careful if you attempt it in batch mode (that is, having SAS run a .sas program directly from command-line using the -sysin option). It will indeed attempt to pop open the interactive SAS window environment upon execution.
But, if your batch code also attempts to build some graphs/charts, you'll be required to use the -noterminal option. And the -noterminal option isn't compatible with the dm command. You'd spot it right away in the log, but I just wanted to give you a heads-up.
Because of the size of some of my datasets I just do a simple proc print and limit the output to only 50 observations. I do this so often that I created the following macro that dumps the output to a html file.
%Macro DPrt(Dset, obs=50, vars=, w=, Path="C:\output\");
%LET BKPATH = &Path;
%PUT BKPATH= &BKPATH;
options obs = &obs.;
title;
ods listing close;
ods html
path = &BKPATH.
body = "Debug-&Dset..htm"
style = THEME;
proc print data = &Dset n u split=' ';
%if &vars NE %THEN %DO;
var &vars.;
%END;
%if &w NE %THEN %DO;
&w;
%END;
Run;
ods html close;
ods listing;
options obs = MAX;
%Mend Dprt;
Sample call for dataset test looks like
%dprt(test)