SAS check if file on fileserver is opended by other PC - file

I have a sas-db file on a file server and want to check, if it is opened by another PC.
I tried several attempts using this sources http://www.wuss.org/proceedings11/Papers_Galligan_O_74889.pdf http://support.sas.com/documentation/cdl/en/lefunctionsref/63354/HTML/default/viewer.htm#p0a6vn2td7bjr2n1viy8y4lgvq61.htm with no success.
The numbers(fid) in the log never turn 0, irrespective if the file is open on the other PC or not.
%MACRO Try;
%let filrf=myfile;
%let rc=%sysfunc(filename(filrf,\\inti\[...]\p3001_overviewsampling.sas7bdat));
%let fid=%sysfunc(fopen(&filrf));
%PUT RC is: &RC // fid is &fid ;
%MEND;
%Try;
LOG: RC is: 20036 // fid is 30
Any ideas?
Thanks, Lubenja
------ EDIT after the answer of data null ----------------
Thanks for the repose. However, if I run your macro twice it is not working any more. Somehow the file gets locked even if running from the same PC. And now I cant delete the file any more from whichever PC.
17 %LET Path =\\hugo\Temp;
18 LIBNAME test "&Path";
NOTE: Libref TEST was successfully assigned as follows:
Engine: V9
Physical Name: \\hugo\Temp
19
20
21 data test.class2;
22 set sashelp.class;
23 run;
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
NOTE: The data set TEST.CLASS2 has 19 observations and 5 variables.
NOTE: DATA statement used (Total process time):
real time 0.06 seconds
cpu time 0.01 seconds
24
25 %MACRO Try(data=,library=);
26 %let filrf=myfile;
27 %let rc=%sysfunc(filename(filrf,%sysfunc(pathname(&library))/&data..sas7bdat));
28 %let fid=%sysfunc(fopen(&filrf,O));
29 %PUT RC is: &RC // fid is &fid ;
30 %if &fid %then %let rc=%sysfunc(fclose(&fid));
31 %MEND;
32 %Try(data=class2,library=test);
RC is: 0 // fid is 1
33 %Try(data=class2,library=test);
RC is: 0 // fid is 0
34 data test.class2;
35 set sashelp.class;
36 run;
ERROR: An I/O error has occurred on file TEST.CLASS2.DATA.
NOTE: The SAS System stopped processing this step because of errors.
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds

I had to add the O output option to FOPEN
25 data class;
26 set sashelp.class;
27 run;
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
NOTE: The data set WORK.CLASS has 19 observations and 5 variables.
NOTE: DATA statement used (Total process time):
real time 0.02 seconds
cpu time 0.01 seconds
28 %let did = %sysfunc(open(class));
29 %put &=did;
DID=1
30
31 %MACRO Try(data=);
32 %let filrf=myfile;
33 %let rc=%sysfunc(filename(filrf,%sysfunc(pathname(work))/&data..sas7bdat));
34 %let fid=%sysfunc(fopen(&filrf,O));
35 %PUT RC is: &RC // fid is &fid ;
36 %if &fid %then %let rc=%sysfunc(fclose(&fid));
37 %MEND;
38 %Try(data=class)
Resource is read-locked by another thread. File
=/opt/local/saswork/...redacted.../class.sas7bdat.
RC is: 0 // fid is 0
39
40 %let rc=%sysfunc(close(&did));
41 %put &=rc;
RC=0

The following is an approach to handling this case, although unfortunately it still writes an ERROR to the log:
%let lib=YOURLIB;
%let ds=YOURDS;
/* first - test for syscc>0 and handle */
/* next, attempt to gain update access and set var if successful */
%let locked=yes;
data &lib..&ds;
modify &lib..&ds;
call symputx('locked','no');
stop;
run;
/* if error, or explicity locked, handle the case */
%if &syscc>0 or &locked=yes %then %do;
%let syscc=0;
options obs=max replace nosyntaxcheck;
/* DO SOMETHING HERE */
%end;

Related

Do while loop in SAS

I am referring the SAS documentation page to understand the difference between DO while and DO until loops in SAS. While referring this document, I came to a conclusion that whenever I used DO while loop, the inequality of while statement should always less than (or less than or equal). The inequality cannot be greater than (or greater than or equal).
The reason is follows. When I ran this code:
data _null_;
n=0;
do while(n<5);
put n=;
n+1;
end;
run;
I got the output as 0,1,2,3,4.
But When I ran this code, I got nothing.
data _null_;
n=0;
do while(n>5);
put n=;
n+1;
end;
run;
Is my conclusion correct, or am I missing something?
Thank you
1:
It is not really whether you use > or <. But the logic of what to test is reversed. With DO WHILE() you execute the loop when the condition is TRUE. With DO UNTIL() you continue executing when the condition is FALSE.
11 data _null_;
12 do while(n<5);
13 put n #;
14 n+1;
15 end;
16 run;
0 1 2 3 4
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
17 data _null_;
18 do until(n>=5);
19 put n #;
20 n+1;
21 end;
22 run;
0 1 2 3 4
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
The other big difference is when the test is made. With DO WHILE() the test is before the loop starts. With DO UNTIL() it is after the loop finishes. So with DO UNTIL() the code always executes at least once.
Note your example is more easily done using an iterative DO loop instead.
6 data _null_;
7 do n=0 to 4;
8 put n #;
9 end;
10 run;
0 1 2 3 4

How to transfer long data to wide format data in sas

Suppose I have a data set as below
data have;
input subject$ day$ arm$ var1 var2;
datalines;
100-01 Day1 left 40 30
100-01 Day1 right 35 25
200-01 Day28 left 45 22
200-01 Day28 right 38 15
;
run;
In this data set each subject has two row. But I would like to make one row for each subject. The expected data set is
data want;
input subject$ day$ arm_left$ arm_right$ var1_left var1_right var2_left var2_right;
datalines;
100-01 Day1 left right 40 35 30 25
200-01 Day28 left right 45 38 22 15
;
run;
Any help is appreciated.
This gets you almost there, not the arm portion? Do you actually need that variable (arm_left/arm_right) seems redundant.
data have;
input subject$ day$ arm$ var1 var2;
datalines;
100-01 Day1 left 40 30
100-01 Day1 right 35 25
200-01 Day28 left 45 22
200-01 Day28 right 38 15
;
run;
proc transpose data=have out=long;
by subject day arm;
var var1 var2;
run;
proc transpose data=long out=wide delimiter=_;
by subject day;
id _name_ arm;
var col1;
run;
Another way but may not scale:
data have_left;
set have;
by subject day;
where arm='left';
rename arm = arm_left var1=var1_left var2=var2_left;
run;
data have_right;
set have;
where arm='right';
rename arm = arm_right var1=var1_right var2=var2_right;
run;
data want;
merge have_left have_right;
by subject day;
run;

Using macrovariables in calculus with arrays SAS

I would like some help with SAS Arrays and do loops
I have some code which nearly works and would like an explanation why it doesn't work as expected. I wish to calculate the max of the elements in an array taking a limited number values determined by a variable calculated.
DATA VALUES;
INPUT VAL;
DATALINES;
1
2
3
4
5
6
7
8
9
10
;
RUN;
%macro prueba(dataset);
DATA PRUEBA;
SET &dataset;
ARRAY DIAS(11) V1-V11 (4 5 6 7 8 9 10 88 75 46 71);
k = _n_ + 1;
IF k le dim(DIAS) THEN
%DO i = 1 %TO k;
Maxi = max(of V1 - V&i);
%END;
RUN;
%MEND;
%prueba(VALUES);
The error message:
A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was:
k
ERROR: The %TO value of the %DO I loop is invalid.
ERROR: The macro PRUEBA will stop executing.
Thanks
The error message is telling you that the upper bound for your %DO loop is a character string instead of a number. The macro processor sees k as constant text.
Just use a regular DO loop instead.
%macro prueba(dataset);
DATA PRUEBA;
SET &dataset;
ARRAY DIAS(11) V1-V11 (4 5 6 7 8 9 10 88 75 46 71);
k = _n_ + 1;
do i=1 to min(k,dim(DIAS));
Maxi = max(maxi,dias(i));
end;
RUN;
%MEND;

Connect SAS EG to SQL Server

I have never tried to connect to SQL Server before (and not that great at coding).
I tried to read some stuff on the internet - this is how far I am:
I have made a connection in the ODBC Data Source Administration and the test was successfull and i called the database: fpt
Snapshot :
Afterwards I started a program in SAS EG and coded (I use windows SQL authentication, so cahnged username and password to X) :
LIBNAME test ODBC DSN=fpt user=X pw=X
in the log i get the following error and cannot figure out why?
1 ;*';*";*/;quit;run;
2 OPTIONS PAGENO=MIN;
3 %LET _CLIENTTASKLABEL='Program (6)';
4 %LET _CLIENTPROJECTPATH='C:\Users\g46973\Desktop\test.egp';
5 %LET _CLIENTPROJECTNAME='test.egp';
6 %LET _SASPROGRAMFILE=;
7
8 ODS _ALL_ CLOSE;
9 OPTIONS DEV=ACTIVEX;
10 GOPTIONS XPIXELS=0 YPIXELS=0;
11 FILENAME EGSR TEMP;
12 ODS tagsets.sasreport13(ID=EGSR) FILE=EGSR
13 STYLE=HtmlBlue
14 STYLESHEET=(URL="file:///C:/Program%20Files/SASHOME/SASEnterpriseGuide/7.1/Styles/HtmlBlue.css")
15 NOGTITLE
16 NOGFOOTNOTE
17 GPATH=&sasworklocation
18 ENCODING=UTF8
19 options(rolap="on")
20 ;
NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR
21
22 GOPTIONS ACCESSIBLE;
23 LIBNAME test ODBC DSN=fpt user=fptreader pw=XXXXXXXX
24
25 GOPTIONS NOACCESSIBLE;
________
22
ERROR: Libref TEST is not assigned.
ERROR: Error in the LIBNAME statement.
ERROR 22-7: Invalid option name GOPTIONS.
26 %LET _CLIENTTASKLABEL=;
27 %LET _CLIENTPROJECTPATH=;
28 %LET _CLIENTPROJECTNAME=;
29 %LET _SASPROGRAMFILE=;
30
31 ;*';*";*/;quit;run;
32 ODS _ALL_ CLOSE;
33
34
35 QUIT; RUN;
36
Any awesome programmer who can help?
You are missing a semicolon at the end of the libname statement. This causes SAS to think the goptions statement (which is added by EG) is part of the libname statement.
I don't see a DSN switch for the LIBNAME statement.
I think you need DATASRC instead.
Source

Loop each variable into SAS macro

I have several variables in data set survey. I want to write a loop to load each variable into a SAS macro.
the code is below.
%let var= r1 r2 r3 ;
DATA survey;
INPUT id sex $ age inc r1 r2 r3 ;
DATALINES;
1 F 35 17 7 2 2
17 M 50 14 5 5 3
33 F 45 6 7 2 7
49 M 24 14 7 5 7
65 F 52 9 4 7 7
81 M 44 11 7 7 7
2 F 34 17 6 5 3
18 M 40 14 7 5 2
34 F 47 6 6 5 6
50 M 35 17 5 7 5
;
%MACRO bvars(input);
proc univariate data = "D:\hsb2" plots;
var &input.;
run;
%MEND bvars;
I just want &var can load into macro bvars each time for only one variable instead of writing the following.
%bvars(r1)
%bvars(r2)
%bvars(r3)
.....
This is time consuming while the number of variables are bigger than 100.
This will run proc univariate for all the variables in survay which start with "r" (so r1, r2, etc.). Procedures with a var statement usually accept multiple variables.
proc univariate data = survey;
var r:;
run;
If you wish to run for all numeric variables replace r: with _NUM_.
If you want to loop through the variables and call a function seperately each time there are several approaches. Usually they involve a macro do loop (which must be inside a macro) like so:
%macro looper(inData);
/* List all the variable names */
proc contents data = &inData. out = _colNames noprint;
run;
proc sql noprint;
select name
/* Put the variable names in a macro variable list */
into :colNames separated by " "
from _colNames
/* Get only numeric variables */
where type = 1
order by varnum;
quit;
/* Loop through the variable names */
%do i = 1 %to %sysfunc(countw(&colNames.));
%let colName = %scan(&colNAmes., &i.);
%put &colName.;
/* Your macro call or code here */
/* %bvars(&inData., &colName.) */
%end;
%mend looper;
%looper(sashelp.cars);
It might prove useful for you to become familiar with macro %do loops, proc contents (or better yet proc datasets), the %scan() function and the different ways to assign macro variables. The sas documentation online is a great place to start.
Updated answer.
You can utilise the VCOLUMN table that is automatically created for every SAS dataset in each library including the Work library. This table contains a row for each variable for each dataset in SAS.
So you would do the following. I am assuming your survery dataset is in the Work library.
So the code does the following;
1. Looks ups your dataset in the Vcolumn table and only keep the name of the variable (thats all we need) and store it into dataset temp.
2. For every variable run the bvars Marcro via the call execute statement.
data temp(keep=name);
set Sashelp.Vcolumn;
where libname = 'WORK' and memname = 'SURVEY';
run;
*Call macro using call execute;
data _null_;
set temp;
call execute ("%bvars("||name||");");
run;

Resources