@sasjs/utils 2.48.2 → 2.49.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/fs/generateCompileProgram.d.ts +1 -0
  2. package/fs/generateCompileProgram.js +154 -0
  3. package/fs/generateCompileProgram.js.map +1 -0
  4. package/fs/hash.d.ts +22 -0
  5. package/fs/hash.js +225 -0
  6. package/fs/hash.js.map +1 -0
  7. package/fs/index.d.ts +3 -0
  8. package/fs/index.js +13 -0
  9. package/fs/index.js.map +1 -0
  10. package/fs/internal/helper.d.ts +4 -0
  11. package/fs/internal/helper.js +125 -0
  12. package/fs/internal/helper.js.map +1 -0
  13. package/fs/sync.d.ts +6 -0
  14. package/fs/sync.js +208 -0
  15. package/fs/sync.js.map +1 -0
  16. package/index.d.ts +1 -0
  17. package/index.js +1 -0
  18. package/index.js.map +1 -1
  19. package/macros/mf_abort.sas +27 -0
  20. package/macros/mf_dedup.sas +53 -0
  21. package/macros/mf_deletefile.sas +31 -0
  22. package/macros/mf_existds.sas +30 -0
  23. package/macros/mf_existfeature.sas +59 -0
  24. package/macros/mf_existfileref.sas +33 -0
  25. package/macros/mf_existfunction.sas +37 -0
  26. package/macros/mf_existvar.sas +39 -0
  27. package/macros/mf_existvarlist.sas +56 -0
  28. package/macros/mf_fmtdttm.sas +42 -0
  29. package/macros/mf_getapploc.sas +78 -0
  30. package/macros/mf_getattrc.sas +34 -0
  31. package/macros/mf_getattrn.sas +34 -0
  32. package/macros/mf_getengine.sas +54 -0
  33. package/macros/mf_getfilesize.sas +64 -0
  34. package/macros/mf_getfmtlist.sas +61 -0
  35. package/macros/mf_getfmtname.sas +44 -0
  36. package/macros/mf_getkeyvalue.sas +32 -0
  37. package/macros/mf_getplatform.sas +75 -0
  38. package/macros/mf_getquotedstr.sas +57 -0
  39. package/macros/mf_getschema.sas +43 -0
  40. package/macros/mf_getuniquefileref.sas +60 -0
  41. package/macros/mf_getuniquelibref.sas +57 -0
  42. package/macros/mf_getuniquename.sas +22 -0
  43. package/macros/mf_getuser.sas +44 -0
  44. package/macros/mf_getvalue.sas +36 -0
  45. package/macros/mf_getvarcount.sas +49 -0
  46. package/macros/mf_getvarformat.sas +72 -0
  47. package/macros/mf_getvarlen.sas +56 -0
  48. package/macros/mf_getvarlist.sas +74 -0
  49. package/macros/mf_getvarnum.sas +58 -0
  50. package/macros/mf_getvartype.sas +52 -0
  51. package/macros/mf_getxengine.sas +43 -0
  52. package/macros/mf_increment.sas +29 -0
  53. package/macros/mf_isblank.sas +27 -0
  54. package/macros/mf_isdir.sas +34 -0
  55. package/macros/mf_isint.sas +36 -0
  56. package/macros/mf_islibds.sas +40 -0
  57. package/macros/mf_loc.sas +29 -0
  58. package/macros/mf_mkdir.sas +67 -0
  59. package/macros/mf_mval.sas +19 -0
  60. package/macros/mf_nobs.sas +26 -0
  61. package/macros/mf_trimstr.sas +50 -0
  62. package/macros/mf_uid.sas +21 -0
  63. package/macros/mf_verifymacvars.sas +72 -0
  64. package/macros/mf_wordsinstr1andstr2.sas +53 -0
  65. package/macros/mf_wordsinstr1butnotstr2.sas +54 -0
  66. package/macros/mf_writefile.sas +67 -0
  67. package/macros/mp_abort.sas +301 -0
  68. package/macros/mp_appendfile.sas +57 -0
  69. package/macros/mp_applyformats.sas +181 -0
  70. package/macros/mp_assert.sas +56 -0
  71. package/macros/mp_assertcols.sas +145 -0
  72. package/macros/mp_assertcolvals.sas +168 -0
  73. package/macros/mp_assertdsobs.sas +121 -0
  74. package/macros/mp_assertscope.sas +147 -0
  75. package/macros/mp_base64copy.sas +117 -0
  76. package/macros/mp_binarycopy.sas +79 -0
  77. package/macros/mp_chop.sas +194 -0
  78. package/macros/mp_cleancsv.sas +78 -0
  79. package/macros/mp_cntlout.sas +85 -0
  80. package/macros/mp_copyfolder.sas +84 -0
  81. package/macros/mp_coretable.sas +73 -0
  82. package/macros/mp_createconstraints.sas +70 -0
  83. package/macros/mp_createwebservice.sas +32 -0
  84. package/macros/mp_csv2ds.sas +140 -0
  85. package/macros/mp_deleteconstraints.sas +52 -0
  86. package/macros/mp_deletefolder.sas +70 -0
  87. package/macros/mp_dictionary.sas +52 -0
  88. package/macros/mp_dirlist.sas +263 -0
  89. package/macros/mp_distinctfmtvalues.sas +50 -0
  90. package/macros/mp_dropmembers.sas +46 -0
  91. package/macros/mp_ds2cards.sas +291 -0
  92. package/macros/mp_ds2csv.sas +212 -0
  93. package/macros/mp_ds2ddl.sas +30 -0
  94. package/macros/mp_ds2fmtds.sas +105 -0
  95. package/macros/mp_ds2inserts.sas +180 -0
  96. package/macros/mp_ds2md.sas +103 -0
  97. package/macros/mp_ds2squeeze.sas +120 -0
  98. package/macros/mp_dsmeta.sas +110 -0
  99. package/macros/mp_filtercheck.sas +251 -0
  100. package/macros/mp_filtergenerate.sas +105 -0
  101. package/macros/mp_filterstore.sas +254 -0
  102. package/macros/mp_filtervalidate.sas +105 -0
  103. package/macros/mp_getcols.sas +67 -0
  104. package/macros/mp_getconstraints.sas +115 -0
  105. package/macros/mp_getdbml.sas +335 -0
  106. package/macros/mp_getddl.sas +400 -0
  107. package/macros/mp_getformats.sas +124 -0
  108. package/macros/mp_getmaxvarlengths.sas +130 -0
  109. package/macros/mp_getpk.sas +281 -0
  110. package/macros/mp_gsubfile.sas +58 -0
  111. package/macros/mp_guesspk.sas +332 -0
  112. package/macros/mp_hashdataset.sas +91 -0
  113. package/macros/mp_hashdirectory.sas +162 -0
  114. package/macros/mp_include.sas +106 -0
  115. package/macros/mp_init.sas +76 -0
  116. package/macros/mp_jsonout.sas +406 -0
  117. package/macros/mp_lib2cards.sas +78 -0
  118. package/macros/mp_lib2inserts.sas +77 -0
  119. package/macros/mp_loadformat.sas +303 -0
  120. package/macros/mp_lockanytable.sas +243 -0
  121. package/macros/mp_lockfilecheck.sas +103 -0
  122. package/macros/mp_makedata.sas +107 -0
  123. package/macros/mp_md5.sas +58 -0
  124. package/macros/mp_perflog.sas +43 -0
  125. package/macros/mp_prevobs.sas +88 -0
  126. package/macros/mp_recursivejoin.sas +90 -0
  127. package/macros/mp_replace.sas +151 -0
  128. package/macros/mp_reseterror.sas +27 -0
  129. package/macros/mp_resetoption.sas +39 -0
  130. package/macros/mp_retainedkey.sas +247 -0
  131. package/macros/mp_runddl.sas +49 -0
  132. package/macros/mp_searchcols.sas +103 -0
  133. package/macros/mp_searchdata.sas +131 -0
  134. package/macros/mp_setkeyvalue.sas +55 -0
  135. package/macros/mp_sortinplace.sas +122 -0
  136. package/macros/mp_stackdiffs.sas +592 -0
  137. package/macros/mp_storediffs.sas +230 -0
  138. package/macros/mp_stprequests.sas +74 -0
  139. package/macros/mp_streamfile.sas +212 -0
  140. package/macros/mp_testjob.sas +92 -0
  141. package/macros/mp_testservice.sas +39 -0
  142. package/macros/mp_testwritespeedlibrary.sas +59 -0
  143. package/macros/mp_tree.sas +71 -0
  144. package/macros/mp_unzip.sas +90 -0
  145. package/macros/mp_updatevarlength.sas +93 -0
  146. package/macros/mp_validatecol.sas +97 -0
  147. package/macros/mp_wait4file.sas +35 -0
  148. package/macros/mp_webin.sas +59 -0
  149. package/macros/mp_zip.sas +85 -0
  150. package/package.json +5 -2
  151. package/scripts/copySASjsCore.ts +36 -0
  152. package/types/hash.d.ts +9 -0
  153. package/types/hash.js +3 -0
  154. package/types/hash.js.map +1 -0
  155. package/types/index.d.ts +1 -0
  156. package/types/index.js +1 -0
  157. package/types/index.js.map +1 -1
  158. package/utils/index.d.ts +1 -1
  159. package/utils/index.js +2 -1
  160. package/utils/index.js.map +1 -1
  161. package/utils/utils.d.ts +1 -0
  162. package/utils/utils.js +7 -1
  163. package/utils/utils.js.map +1 -1
@@ -0,0 +1,140 @@
1
+ /**
2
+ @file mp_csv2ds.sas
3
+ @brief Efficient import of arbitrary CSV using a dataset as template
4
+ @details Used to import relevant columns from a large CSV using
5
+ a dataset to provide the types and lengths. Assumes that a header
6
+ row is provided, and datarows start on line 2. Extra columns in
7
+ both the CSV and base dataset are ignored.
8
+
9
+ Usage:
10
+
11
+ filename mycsv temp;
12
+ data _null_;
13
+ file mycsv;
14
+ put 'name,age,nickname';
15
+ put 'John,48,Jonny';
16
+ put 'Jennifer,23,Jen';
17
+ run;
18
+
19
+ %mp_csv2ds(inref=mycsv,outds=myds,baseds=sashelp.class)
20
+
21
+
22
+ @param inref= fileref to the CSV
23
+ @param outds= output ds (lib.ds format)
24
+ @param view= Set to YES or NO to determine whether the output should be
25
+ a view or not. Default is NO (not a view).
26
+ @param baseds= Template dataset on which to create the input statement.
27
+ Is used to determine types, lengths, and any informats.
28
+
29
+ @version 9.2
30
+ @author Allan Bowe
31
+
32
+ <h4> SAS Macros </h4>
33
+ @li mp_abort.sas
34
+ @li mf_existds.sas
35
+
36
+ **/
37
+
38
+ %macro mp_csv2ds(inref=0,outds=0,baseds=0,view=NO);
39
+
40
+ %mp_abort(iftrue=( &inref=0 )
41
+ ,mac=&sysmacroname
42
+ ,msg=%str(the INREF variable must be provided)
43
+ )
44
+ %mp_abort(iftrue=( %superq(outds)=0 )
45
+ ,mac=&sysmacroname
46
+ ,msg=%str(the OUTDS variable must be provided)
47
+ )
48
+ %mp_abort(iftrue=( &baseds=0 )
49
+ ,mac=&sysmacroname
50
+ ,msg=%str(the BASEDS variable must be provided)
51
+ )
52
+ %mp_abort(iftrue=( %mf_existds(&baseds)=0 )
53
+ ,mac=&sysmacroname
54
+ ,msg=%str(the BASEDS dataset (&baseds) needs to be assigned, and to exist)
55
+ )
56
+
57
+ /* count rows */
58
+ %local hasheader; %let hasheader=0;
59
+ data _null_;
60
+ if _N_ > 1 then do;
61
+ call symputx('hasheader',1,'l');
62
+ stop;
63
+ end;
64
+ infile &inref;
65
+ input;
66
+ run;
67
+ %mp_abort(iftrue=( &hasheader=0 )
68
+ ,mac=&sysmacroname
69
+ ,msg=%str(No header row in &inref)
70
+ )
71
+
72
+ /* get the variables in the CSV */
73
+ data _data_;
74
+ infile &inref;
75
+ input;
76
+ length name $32;
77
+ do i=1 to countc(_infile_,',')+1;
78
+ name=upcase(scan(_infile_,i,','));
79
+ output;
80
+ end;
81
+ stop;
82
+ run;
83
+ %local csv_vars;%let csv_vars=&syslast;
84
+
85
+ /* get the variables in the dataset */
86
+ proc contents noprint data=&baseds
87
+ out=_data_ (keep=name type length format: informat);
88
+ run;
89
+ %local base_vars; %let base_vars=&syslast;
90
+
91
+ proc sql undo_policy=none;
92
+ create table &csv_vars as
93
+ select a.*
94
+ ,b.type
95
+ ,b.length
96
+ ,b.format
97
+ ,b.formatd
98
+ ,b.formatl
99
+ ,b.informat
100
+ from &csv_vars a
101
+ left join &base_vars b
102
+ on a.name=upcase(b.name)
103
+ order by i;
104
+
105
+ /* prepare the input statement */
106
+ %local instat dropvars;
107
+ data _null_;
108
+ set &syslast end=last;
109
+ length in dropvars $32767;
110
+ retain in dropvars;
111
+ if missing(type) then do;
112
+ informat='$1.';
113
+ dropvars=catx(' ',dropvars,name);
114
+ end;
115
+ else if missing(informat) then do;
116
+ if type=1 then informat='best.';
117
+ else informat=cats('$',length,'.');
118
+ end;
119
+ else informat=cats(informat,'.');
120
+ in=catx(' ',in,name,':',informat);
121
+ if last then do;
122
+ call symputx('instat',in,'l');
123
+ call symputx('dropvars',dropvars,'l');
124
+ end;
125
+ run;
126
+
127
+ /* import the CSV */
128
+ data &outds
129
+ %if %upcase(&view)=YES %then %do;
130
+ /view=&outds
131
+ %end;
132
+ ;
133
+ infile &inref dsd firstobs=2;
134
+ input &instat;
135
+ %if %length(&dropvars)>0 %then %do;
136
+ drop &dropvars;
137
+ %end;
138
+ run;
139
+
140
+ %mend mp_csv2ds;
@@ -0,0 +1,52 @@
1
+ /**
2
+ @file mp_deleteconstraints.sas
3
+ @brief Delete constraionts
4
+ @details Takes the output from mp_getconstraints.sas as input
5
+
6
+ proc sql;
7
+ create table work.example(
8
+ TX_FROM float format=datetime19.,
9
+ DD_TYPE char(16),
10
+ DD_SOURCE char(2048),
11
+ DD_SHORTDESC char(256),
12
+ constraint pk primary key(tx_from, dd_type,dd_source),
13
+ constraint unq unique(tx_from, dd_type),
14
+ constraint nnn not null(DD_SHORTDESC)
15
+ );
16
+
17
+ %mp_getconstraints(lib=work,ds=example,outds=work.constraints)
18
+ %mp_deleteconstraints(inds=work.constraints,outds=dropped,execute=YES)
19
+
20
+ @param inds= The input table containing the constraint info
21
+ @param outds= a table containing the drop statements (drop_statement column)
22
+ @param execute= `YES|NO` - default is NO. To actually drop, use YES.
23
+
24
+
25
+ @version 9.2
26
+ @author Allan Bowe
27
+
28
+ **/
29
+
30
+ %macro mp_deleteconstraints(inds=mp_getconstraints
31
+ ,outds=mp_deleteconstraints
32
+ ,execute=NO
33
+ )/*/STORE SOURCE*/;
34
+
35
+ proc sort data=&inds out=&outds;
36
+ by libref table_name constraint_name;
37
+ run;
38
+
39
+ data &outds;
40
+ set &outds;
41
+ by libref table_name constraint_name;
42
+ length drop_statement $500;
43
+ if _n_=1 and "&execute"="YES" then call execute('proc sql;');
44
+ if first.constraint_name then do;
45
+ drop_statement=catx(" ","alter table",libref,".",table_name
46
+ ,"drop constraint",constraint_name,";");
47
+ output;
48
+ if "&execute"="YES" then call execute(drop_statement);
49
+ end;
50
+ run;
51
+
52
+ %mend mp_deleteconstraints;
@@ -0,0 +1,70 @@
1
+ /**
2
+ @file
3
+ @brief A macro to delete a directory
4
+ @details Will delete all folder content (including subfolder content) and
5
+ finally, the folder itself.
6
+
7
+ Usage:
8
+
9
+ %let rootdir=%sysfunc(pathname(work))/demo;
10
+ %mf_mkdir(&rootdir)
11
+ %mf_mkdir(&rootdir/subdir)
12
+ %mf_mkdir(&rootdir/subdir/subsubdir)
13
+ data "&rootdir/subdir/example.sas7bdat";
14
+ run;
15
+
16
+ %mp_deletefolder(&rootdir)
17
+
18
+ @param path Unquoted path to the folder to delete.
19
+
20
+ <h4> SAS Macros </h4>
21
+ @li mf_getuniquename.sas
22
+ @li mf_isdir.sas
23
+ @li mp_dirlist.sas
24
+
25
+ <h4> Related Macros </h4>
26
+ @li mp_deletefolder.test.sas
27
+
28
+ **/
29
+
30
+ %macro mp_deletefolder(folder);
31
+ /* proceed if valid directory */
32
+ %if %mf_isdir(&folder)=1 %then %do;
33
+
34
+ /* prep temp table */
35
+ %local tempds;
36
+ %let tempds=%mf_getuniquename();
37
+
38
+ /* recursive directory listing */
39
+ %mp_dirlist(path=&folder,outds=work.&tempds, maxdepth=MAX)
40
+
41
+ /* sort descending level so can delete folder contents before folders */
42
+ proc sort data=work.&tempds;
43
+ by descending level;
44
+ run;
45
+
46
+ /* ensure top level folder is removed at the end */
47
+ proc sql;
48
+ insert into work.&tempds set filepath="&folder";
49
+
50
+ /* delete everything */
51
+ data _null_;
52
+ set work.&tempds end=last;
53
+ length fref $8;
54
+ fref='';
55
+ rc=filename(fref,filepath);
56
+ rc=fdelete(fref);
57
+ if rc then do;
58
+ msg=sysmsg();
59
+ put "&sysmacroname:" / rc= / msg= / filepath=;
60
+ end;
61
+ rc=filename(fref);
62
+ run;
63
+
64
+ /* tidy up */
65
+ proc sql;
66
+ drop table work.&tempds;
67
+
68
+ %end;
69
+ %else %put &sysmacroname: &folder: is not a valid / accessible folder. ;
70
+ %mend mp_deletefolder;
@@ -0,0 +1,52 @@
1
+ /**
2
+ @file mp_dictionary.sas
3
+ @brief Creates a portal (libref) into the SQL Dictionary Views
4
+ @details Provide a libref and the macro will create a series of views against
5
+ each view in the special PROC SQL dictionary libref.
6
+
7
+ This is useful if you would like to visualise (navigate) the views in a SAS
8
+ client such as Base SAS, Enterprise Guide, or Studio (or [Data Controller](
9
+ https://datacontroller.io)).
10
+
11
+ It works by extracting the dictionary.dictionaries view into
12
+ YOURLIB.dictionaries, then uses that to create a YOURLIB.{viewName} for every
13
+ other dictionary.view, eg:
14
+
15
+ proc sql;
16
+ create view YOURLIB.columns as select * from dictionary.columns;
17
+
18
+ Usage:
19
+
20
+ libname demo "/lib/directory";
21
+ %mp_dictionary(lib=demo)
22
+
23
+ Or, to just create them in WORK:
24
+
25
+ %mp_dictionary()
26
+
27
+ If you'd just like to browse the dictionary data model, you can also check
28
+ out [this article](https://rawsas.com/dictionary-of-dictionaries/).
29
+
30
+ ![](https://user-images.githubusercontent.com/4420615/188278365-2987db97-0594-4a39-ac81-dbacdef5cdc8.png)
31
+
32
+ @param lib= (WORK) The libref in which to create the views
33
+
34
+ <h4> Related Files </h4>
35
+ @li mp_dictionary.test.sas
36
+
37
+ @version 9.2
38
+ @author Allan Bowe
39
+
40
+ **/
41
+
42
+ %macro mp_dictionary(lib=WORK)/*/STORE SOURCE*/;
43
+ %local list i mem;
44
+ proc sql noprint;
45
+ create view &lib..dictionaries as select * from dictionary.dictionaries;
46
+ select distinct memname into: list separated by ' ' from &lib..dictionaries;
47
+ %do i=1 %to %sysfunc(countw(&list,%str( )));
48
+ %let mem=%scan(&list,&i,%str( ));
49
+ create view &lib..&mem as select * from dictionary.&mem;
50
+ %end;
51
+ quit;
52
+ %mend mp_dictionary;
@@ -0,0 +1,263 @@
1
+ /**
2
+ @file
3
+ @brief Returns all files and subdirectories within a specified parent
4
+ @details When used with getattrs=NO, is not OS specific (uses dopen / dread).
5
+
6
+ Credit for the rename approach:
7
+ https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
8
+
9
+ Usage:
10
+
11
+ %mp_dirlist(path=/some/location, outds=myTable, maxdepth=MAX)
12
+
13
+ %mp_dirlist(outds=cwdfileprops, getattrs=YES)
14
+
15
+ %mp_dirlist(fref=MYFREF)
16
+
17
+ @warning In a Unix environment, the existence of a named pipe will cause this
18
+ macro to hang. Therefore this tool should be used with caution in a SAS 9 web
19
+ application, as it can use up all available multibridge sessions if requests
20
+ are resubmitted.
21
+ If anyone finds a way to positively identify a named pipe using SAS (without
22
+ X CMD) do please raise an issue!
23
+
24
+
25
+ @param [in] path= (%sysfunc(pathname(work))) Path for which to return contents
26
+ @param [in] fref= (0) Provide a DISK engine fileref as an alternative to PATH
27
+ @param [in] maxdepth= (0) Set to a positive integer to indicate the level of
28
+ subdirectory scan recursion - eg 3, to go `./3/levels/deep`. For unlimited
29
+ recursion, set to MAX.
30
+ @param [in] showparent= (NO) By default, the initial parent directory is not
31
+ part of the results. Set to YES to include it. For this record only,
32
+ directory=filepath.
33
+ @param [out] outds= (work.mp_dirlist) The output dataset to create
34
+ @param [out] getattrs= (NO) If getattrs=YES then the doptname / foptname
35
+ functions are used to scan all properties - any characters that are not
36
+ valid in a SAS name (v7) are simply stripped, and the table is transposed
37
+ so theat each property is a column and there is one file per row. An
38
+ attempt is made to get all properties whether a file or folder, but some
39
+ files/folders cannot be accessed, and so not all properties can / will be
40
+ populated.
41
+
42
+
43
+ @returns outds contains the following variables:
44
+ - directory (containing folder)
45
+ - file_or_folder (file / folder)
46
+ - filepath (path/to/file.name)
47
+ - filename (just the file name)
48
+ - ext (.extension)
49
+ - msg (system message if any issues)
50
+ - level (depth of folder)
51
+ - OS SPECIFIC variables, if <code>getattrs=</code> is used.
52
+
53
+ <h4> SAS Macros </h4>
54
+ @li mf_existds.sas
55
+ @li mf_getvarlist.sas
56
+ @li mf_wordsinstr1butnotstr2.sas
57
+ @li mp_dropmembers.sas
58
+
59
+ <h4> Related Macros </h4>
60
+ @li mp_dirlist.test.sas
61
+
62
+ @version 9.2
63
+ **/
64
+
65
+ %macro mp_dirlist(path=%sysfunc(pathname(work))
66
+ , fref=0
67
+ , outds=work.mp_dirlist
68
+ , getattrs=NO
69
+ , showparent=NO
70
+ , maxdepth=0
71
+ , level=0 /* The level of recursion to perform. For internal use only. */
72
+ )/*/STORE SOURCE*/;
73
+ %let getattrs=%upcase(&getattrs)XX;
74
+
75
+ /* temp table */
76
+ %local out_ds;
77
+ data;run;
78
+ %let out_ds=%str(&syslast);
79
+
80
+ /* drop main (top) table if it exists */
81
+ %if &level=0 %then %do;
82
+ %mp_dropmembers(%scan(&outds,-1,.), libref=WORK)
83
+ %end;
84
+
85
+ data &out_ds(compress=no
86
+ keep=file_or_folder filepath filename ext msg directory level
87
+ );
88
+ length directory filepath $500 fref fref2 $8 file_or_folder $6 filename $80
89
+ ext $20 msg $200 foption $16;
90
+ if _n_=1 then call missing(of _all_);
91
+ retain level &level;
92
+ %if &fref=0 %then %do;
93
+ rc = filename(fref, "&path");
94
+ %end;
95
+ %else %do;
96
+ fref="&fref";
97
+ rc=0;
98
+ %end;
99
+ if rc = 0 then do;
100
+ did = dopen(fref);
101
+ if did=0 then do;
102
+ putlog "NOTE: This directory is empty, or does not exist - &path";
103
+ msg=sysmsg();
104
+ put msg;
105
+ put _all_;
106
+ stop;
107
+ end;
108
+ /* attribute is OS-dependent - could be "Directory" or "Directory Name" */
109
+ numopts=doptnum(did);
110
+ do i=1 to numopts;
111
+ foption=doptname(did,i);
112
+ if foption=:'Directory' then i=numopts;
113
+ end;
114
+ directory=dinfo(did,foption);
115
+ rc = filename(fref);
116
+ end;
117
+ else do;
118
+ msg=sysmsg();
119
+ put _all_;
120
+ stop;
121
+ end;
122
+ dnum = dnum(did);
123
+ do i = 1 to dnum;
124
+ filename = dread(did, i);
125
+ filepath=cats(directory,'/',filename);
126
+ rc = filename(fref2,filepath);
127
+ midd=dopen(fref2);
128
+ dmsg=sysmsg();
129
+ if did > 0 then file_or_folder='folder';
130
+ rc=dclose(midd);
131
+ midf=fopen(fref2);
132
+ fmsg=sysmsg();
133
+ if midf > 0 then file_or_folder='file';
134
+ rc=fclose(midf);
135
+
136
+ if index(fmsg,'File is in use') or index(dmsg,'is not a directory')
137
+ then file_or_folder='file';
138
+ else if index(fmsg,'Insufficient authorization') then file_or_folder='file';
139
+ else if file_or_folder='' then file_or_folder='locked';
140
+
141
+ if file_or_folder='file' then do;
142
+ ext = prxchange('s/.*\.{1,1}(.*)/$1/', 1, filename);
143
+ if filename = ext then ext = ' ';
144
+ end;
145
+ else do;
146
+ ext='';
147
+ file_or_folder='folder';
148
+ end;
149
+ output;
150
+ end;
151
+ rc = dclose(did);
152
+ %if &showparent=YES and &level=0 %then %do;
153
+ filepath=directory;
154
+ file_or_folder='folder';
155
+ ext='';
156
+ filename=scan(directory,-1,'/\');
157
+ msg='';
158
+ level=&level;
159
+ output;
160
+ %end;
161
+ stop;
162
+ run;
163
+
164
+ %if %substr(&getattrs,1,1)=Y %then %do;
165
+ data &out_ds;
166
+ set &out_ds;
167
+ length infoname infoval $60 fref $8;
168
+ if _n_=1 then call missing(fref);
169
+ rc=filename(fref,filepath);
170
+ drop rc infoname fid i close fref;
171
+ if file_or_folder='file' then do;
172
+ fid=fopen(fref);
173
+ if fid le 0 then do;
174
+ msg=sysmsg();
175
+ putlog "Could not open file:" filepath fid= ;
176
+ sasname='_MCNOTVALID_';
177
+ output;
178
+ end;
179
+ else do i=1 to foptnum(fid);
180
+ infoname=foptname(fid,i);
181
+ infoval=finfo(fid,infoname);
182
+ sasname=compress(infoname, '_', 'adik');
183
+ if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
184
+ if upcase(sasname) ne 'FILENAME' then output;
185
+ end;
186
+ close=fclose(fid);
187
+ end;
188
+ else do;
189
+ fid=dopen(fref);
190
+ if fid le 0 then do;
191
+ msg=sysmsg();
192
+ putlog "Could not open folder:" filepath fid= ;
193
+ sasname='_MCNOTVALID_';
194
+ output;
195
+ end;
196
+ else do i=1 to doptnum(fid);
197
+ infoname=doptname(fid,i);
198
+ infoval=dinfo(fid,infoname);
199
+ sasname=compress(infoname, '_', 'adik');
200
+ if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
201
+ if upcase(sasname) ne 'FILENAME' then output;
202
+ end;
203
+ close=dclose(fid);
204
+ end;
205
+ run;
206
+ proc sort;
207
+ by filepath sasname;
208
+ proc transpose data=&out_ds out=&out_ds(drop=_:);
209
+ id sasname;
210
+ var infoval;
211
+ by filepath file_or_folder filename ext ;
212
+ run;
213
+ %end;
214
+
215
+ data &out_ds;
216
+ set &out_ds(where=(filepath ne ''));
217
+ run;
218
+
219
+ /**
220
+ * The above transpose can mean that some updates create additional columns.
221
+ * This necessitates the occasional use of datastep over proc append.
222
+ */
223
+ %if %mf_existds(&outds) %then %do;
224
+ %local basevars appvars newvars;
225
+ %let basevars=%mf_getvarlist(&outds);
226
+ %let appvars=%mf_getvarlist(&out_ds);
227
+ %let newvars=%length(%mf_wordsinstr1butnotstr2(Str1=&appvars,Str2=&basevars));
228
+ %if &newvars>0 %then %do;
229
+ data &outds;
230
+ set &outds &out_ds;
231
+ run;
232
+ %end;
233
+ %else %do;
234
+ proc append base=&outds data=&out_ds force nowarn;
235
+ run;
236
+ %end;
237
+ %end;
238
+ %else %do;
239
+ proc append base=&outds data=&out_ds;
240
+ run;
241
+ %end;
242
+
243
+ /* recursive call */
244
+ %if &maxdepth>&level or &maxdepth=MAX %then %do;
245
+ data _null_;
246
+ set &out_ds;
247
+ where file_or_folder='folder';
248
+ %if &showparent=YES and &level=0 %then %do;
249
+ if filepath ne directory;
250
+ %end;
251
+ length code $10000;
252
+ code=cats('%nrstr(%mp_dirlist(path=',filepath,",outds=&outds"
253
+ ,",getattrs=&getattrs,level=%eval(&level+1),maxdepth=&maxdepth))");
254
+ put code=;
255
+ call execute(code);
256
+ run;
257
+ %end;
258
+
259
+ /* tidy up */
260
+ proc sql;
261
+ drop table &out_ds;
262
+
263
+ %mend mp_dirlist;
@@ -0,0 +1,50 @@
1
+ /**
2
+ @file
3
+ @brief Creates a dataset containing distinct _formatted_ values
4
+ @details If no format is supplied, then the original value is used instead.
5
+ There is also a dependency on other macros within the Macro Core library.
6
+ Usage:
7
+
8
+ %mp_distinctfmtvalues(libds=sashelp.class,var=age,outvar=age,outds=test)
9
+
10
+ @param libds input dataset
11
+ @param var variable to get distinct values for
12
+ @param outvar variable to create. Default: `formatted_value`
13
+ @param outds dataset to create. Default: work.mp_distinctfmtvalues
14
+ @param varlen length of variable to create (default 200)
15
+
16
+ @version 9.2
17
+ @author Allan Bowe
18
+
19
+ **/
20
+
21
+ %macro mp_distinctfmtvalues(
22
+ libds=
23
+ ,var=
24
+ ,outvar=formatted_value
25
+ ,outds=work.mp_distinctfmtvalues
26
+ ,varlen=2000
27
+ )/*/STORE SOURCE*/;
28
+
29
+ %local fmt vtype;
30
+ %let fmt=%mf_getvarformat(&libds,&var);
31
+ %let vtype=%mf_getvartype(&libds,&var);
32
+
33
+ proc sql;
34
+ create table &outds as
35
+ select distinct
36
+ %if &vtype=C & %trim(&fmt)=%str() %then %do;
37
+ &var
38
+ %end;
39
+ %else %if &vtype=C %then %do;
40
+ put(&var,&fmt)
41
+ %end;
42
+ %else %if %trim(&fmt)=%str() %then %do;
43
+ put(&var,32.)
44
+ %end;
45
+ %else %do;
46
+ put(&var,&fmt)
47
+ %end;
48
+ as &outvar length=&varlen
49
+ from &libds;
50
+ %mend mp_distinctfmtvalues;
@@ -0,0 +1,46 @@
1
+ /**
2
+ @file
3
+ @brief Drops tables / views (if they exist) without warnings in the log
4
+ @details Useful for dropping tables when you're not sure they exist, or if
5
+ you are not sure whether they are a dataset or view. Also efficient for
6
+ dropping multiple tables / views.
7
+
8
+ Example usage:
9
+
10
+ proc sql;
11
+ create table data1 as select * from sashelp.class;
12
+ create view view2 as select * from sashelp.class;
13
+ %mp_dropmembers(data1 view2, libref=WORK)
14
+
15
+
16
+ <h4> SAS Macros </h4>
17
+ @li mf_isblank.sas
18
+
19
+
20
+ @param [in] list space separated list of datasets / views, WITHOUT libref
21
+ @param [in] libref= (WORK) Note - you can only drop from one library at a time
22
+ @param [in] iftrue= (1=1) Conditionally drop tables, eg if &debug=N
23
+
24
+ @version 9.2
25
+ @author Allan Bowe
26
+
27
+ **/
28
+
29
+ %macro mp_dropmembers(
30
+ list /* space separated list of datasets / views */
31
+ ,libref=WORK /* can only drop from a single library at a time */
32
+ ,iftrue=%str(1=1)
33
+ )/*/STORE SOURCE*/;
34
+
35
+ %if not(%eval(%unquote(&iftrue))) %then %return;
36
+
37
+ %if %mf_isblank(&list) %then %do;
38
+ %put NOTE: nothing to drop!;
39
+ %return;
40
+ %end;
41
+
42
+ proc datasets lib=&libref nolist;
43
+ delete &list;
44
+ delete &list /mtype=view;
45
+ run;
46
+ %mend mp_dropmembers;