@sasjs/utils 2.49.0 → 2.49.2
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.
- package/fs/internal/helper.js +19 -24
- package/fs/internal/helper.js.map +1 -1
- package/macros/mf_abort.sas +27 -0
- package/macros/mf_dedup.sas +53 -0
- package/macros/mf_deletefile.sas +31 -0
- package/macros/mf_existds.sas +30 -0
- package/macros/mf_existfeature.sas +59 -0
- package/macros/mf_existfileref.sas +33 -0
- package/macros/mf_existfunction.sas +37 -0
- package/macros/mf_existvar.sas +39 -0
- package/macros/mf_existvarlist.sas +56 -0
- package/macros/mf_fmtdttm.sas +42 -0
- package/macros/mf_getapploc.sas +78 -0
- package/macros/mf_getattrc.sas +34 -0
- package/macros/mf_getattrn.sas +34 -0
- package/macros/mf_getengine.sas +54 -0
- package/macros/mf_getfilesize.sas +64 -0
- package/macros/mf_getfmtlist.sas +61 -0
- package/macros/mf_getfmtname.sas +44 -0
- package/macros/mf_getkeyvalue.sas +32 -0
- package/macros/mf_getplatform.sas +75 -0
- package/macros/mf_getquotedstr.sas +57 -0
- package/macros/mf_getschema.sas +43 -0
- package/macros/mf_getuniquefileref.sas +60 -0
- package/macros/mf_getuniquelibref.sas +57 -0
- package/macros/mf_getuniquename.sas +22 -0
- package/macros/mf_getuser.sas +44 -0
- package/macros/mf_getvalue.sas +36 -0
- package/macros/mf_getvarcount.sas +49 -0
- package/macros/mf_getvarformat.sas +72 -0
- package/macros/mf_getvarlen.sas +56 -0
- package/macros/mf_getvarlist.sas +74 -0
- package/macros/mf_getvarnum.sas +58 -0
- package/macros/mf_getvartype.sas +52 -0
- package/macros/mf_getxengine.sas +43 -0
- package/macros/mf_increment.sas +29 -0
- package/macros/mf_isblank.sas +27 -0
- package/macros/mf_isdir.sas +34 -0
- package/macros/mf_isint.sas +36 -0
- package/macros/mf_islibds.sas +40 -0
- package/macros/mf_loc.sas +29 -0
- package/macros/mf_mkdir.sas +67 -0
- package/macros/mf_mval.sas +19 -0
- package/macros/mf_nobs.sas +26 -0
- package/macros/mf_trimstr.sas +50 -0
- package/macros/mf_uid.sas +21 -0
- package/macros/mf_verifymacvars.sas +72 -0
- package/macros/mf_wordsinstr1andstr2.sas +53 -0
- package/macros/mf_wordsinstr1butnotstr2.sas +54 -0
- package/macros/mf_writefile.sas +67 -0
- package/macros/mp_abort.sas +301 -0
- package/macros/mp_appendfile.sas +57 -0
- package/macros/mp_applyformats.sas +181 -0
- package/macros/mp_assert.sas +56 -0
- package/macros/mp_assertcols.sas +145 -0
- package/macros/mp_assertcolvals.sas +168 -0
- package/macros/mp_assertdsobs.sas +121 -0
- package/macros/mp_assertscope.sas +147 -0
- package/macros/mp_base64copy.sas +117 -0
- package/macros/mp_binarycopy.sas +79 -0
- package/macros/mp_chop.sas +194 -0
- package/macros/mp_cleancsv.sas +78 -0
- package/macros/mp_cntlout.sas +85 -0
- package/macros/mp_copyfolder.sas +84 -0
- package/macros/mp_coretable.sas +73 -0
- package/macros/mp_createconstraints.sas +70 -0
- package/macros/mp_createwebservice.sas +32 -0
- package/macros/mp_csv2ds.sas +140 -0
- package/macros/mp_deleteconstraints.sas +52 -0
- package/macros/mp_deletefolder.sas +70 -0
- package/macros/mp_dictionary.sas +52 -0
- package/macros/mp_dirlist.sas +262 -0
- package/macros/mp_distinctfmtvalues.sas +50 -0
- package/macros/mp_dropmembers.sas +46 -0
- package/macros/mp_ds2cards.sas +291 -0
- package/macros/mp_ds2csv.sas +212 -0
- package/macros/mp_ds2ddl.sas +30 -0
- package/macros/mp_ds2fmtds.sas +105 -0
- package/macros/mp_ds2inserts.sas +180 -0
- package/macros/mp_ds2md.sas +103 -0
- package/macros/mp_ds2squeeze.sas +120 -0
- package/macros/mp_dsmeta.sas +110 -0
- package/macros/mp_filtercheck.sas +251 -0
- package/macros/mp_filtergenerate.sas +105 -0
- package/macros/mp_filterstore.sas +254 -0
- package/macros/mp_filtervalidate.sas +105 -0
- package/macros/mp_getcols.sas +67 -0
- package/macros/mp_getconstraints.sas +115 -0
- package/macros/mp_getdbml.sas +335 -0
- package/macros/mp_getddl.sas +400 -0
- package/macros/mp_getformats.sas +124 -0
- package/macros/mp_getmaxvarlengths.sas +130 -0
- package/macros/mp_getpk.sas +281 -0
- package/macros/mp_gitadd.sas +45 -0
- package/macros/mp_gitreleaseinfo.sas +74 -0
- package/macros/mp_gitstatus.sas +67 -0
- package/macros/mp_gsubfile.sas +58 -0
- package/macros/mp_guesspk.sas +332 -0
- package/macros/mp_hashdataset.sas +91 -0
- package/macros/mp_hashdirectory.sas +164 -0
- package/macros/mp_include.sas +106 -0
- package/macros/mp_init.sas +76 -0
- package/macros/mp_jsonout.sas +406 -0
- package/macros/mp_lib2cards.sas +78 -0
- package/macros/mp_lib2inserts.sas +77 -0
- package/macros/mp_loadformat.sas +303 -0
- package/macros/mp_lockanytable.sas +243 -0
- package/macros/mp_lockfilecheck.sas +103 -0
- package/macros/mp_makedata.sas +107 -0
- package/macros/mp_md5.sas +58 -0
- package/macros/mp_perflog.sas +43 -0
- package/macros/mp_prevobs.sas +88 -0
- package/macros/mp_recursivejoin.sas +90 -0
- package/macros/mp_replace.sas +151 -0
- package/macros/mp_reseterror.sas +27 -0
- package/macros/mp_resetoption.sas +39 -0
- package/macros/mp_retainedkey.sas +247 -0
- package/macros/mp_runddl.sas +49 -0
- package/macros/mp_searchcols.sas +103 -0
- package/macros/mp_searchdata.sas +131 -0
- package/macros/mp_setkeyvalue.sas +55 -0
- package/macros/mp_sortinplace.sas +122 -0
- package/macros/mp_stackdiffs.sas +592 -0
- package/macros/mp_storediffs.sas +230 -0
- package/macros/mp_stprequests.sas +74 -0
- package/macros/mp_streamfile.sas +212 -0
- package/macros/mp_testjob.sas +92 -0
- package/macros/mp_testservice.sas +39 -0
- package/macros/mp_testwritespeedlibrary.sas +59 -0
- package/macros/mp_tree.sas +71 -0
- package/macros/mp_unzip.sas +90 -0
- package/macros/mp_updatevarlength.sas +93 -0
- package/macros/mp_validatecol.sas +97 -0
- package/macros/mp_wait4file.sas +35 -0
- package/macros/mp_webin.sas +59 -0
- package/macros/mp_zip.sas +85 -0
- package/package.json +5 -2
- package/scripts/copySASjsCore.ts +36 -0
- package/utils/index.d.ts +1 -2
- package/utils/index.js +2 -3
- package/utils/index.js.map +1 -1
- package/utils/utils.d.ts +1 -0
- package/utils/utils.js +7 -1
- package/utils/utils.js.map +1 -1
- package/utils/getNodeModulePath.d.ts +0 -2
- package/utils/getNodeModulePath.js +0 -83
- package/utils/getNodeModulePath.js.map +0 -1
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Export a dataset to a CSV file WITH leading blanks
|
|
4
|
+
@details Export a dataset to a file or fileref, retaining leading blanks.
|
|
5
|
+
|
|
6
|
+
When using SASJS headerformat, the input statement is provided in the first
|
|
7
|
+
row of the CSV.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
|
|
11
|
+
%mp_ds2csv(sashelp.class,outref="%sysfunc(pathname(work))/file.csv")
|
|
12
|
+
|
|
13
|
+
filename example temp;
|
|
14
|
+
%mp_ds2csv(sashelp.air,outref=example,headerformat=SASJS)
|
|
15
|
+
data; infile example; input;put _infile_; if _n_>5 then stop;run;
|
|
16
|
+
|
|
17
|
+
data _null_;
|
|
18
|
+
infile example;
|
|
19
|
+
input;
|
|
20
|
+
call symputx('stmnt',_infile_);
|
|
21
|
+
stop;
|
|
22
|
+
run;
|
|
23
|
+
data work.want;
|
|
24
|
+
infile example dsd firstobs=2;
|
|
25
|
+
input &stmnt;
|
|
26
|
+
run;
|
|
27
|
+
|
|
28
|
+
Why use mp_ds2csv over, say, proc export?
|
|
29
|
+
|
|
30
|
+
1. Ability to retain leading blanks (this is a major one)
|
|
31
|
+
2. Control the header format
|
|
32
|
+
3. Simple one-liner
|
|
33
|
+
|
|
34
|
+
@param [in] ds The dataset to be exported
|
|
35
|
+
@param [in] dlm= (COMMA) The delimeter to apply. For SASJS, will always be
|
|
36
|
+
COMMA. Supported values:
|
|
37
|
+
@li COMMA
|
|
38
|
+
@li SEMICOLON
|
|
39
|
+
@param [in] headerformat= (LABEL) The format to use for the header section.
|
|
40
|
+
Valid values:
|
|
41
|
+
@li LABEL - Use the variable label (or name, if blank)
|
|
42
|
+
@li NAME - Use the variable name
|
|
43
|
+
@li SASJS - Used to create sasjs-formatted input CSVs, eg for use in
|
|
44
|
+
mp_testservice.sas. This format will supply an input statement in the
|
|
45
|
+
first row, making ingestion by datastep a breeze. Special misisng values
|
|
46
|
+
will be prefixed with a period (eg `.A`) to enable ingestion on both SAS 9
|
|
47
|
+
and Viya. Dates / Datetimes etc are identified by the format type (lookup
|
|
48
|
+
with mcf_getfmttype.sas) and converted to human readable formats (not
|
|
49
|
+
numbers).
|
|
50
|
+
@param [out] outfile= The output filename - should be quoted.
|
|
51
|
+
@param [out] outref= (0) The output fileref (takes precedence if provided)
|
|
52
|
+
@param [in] outencoding= (0) The (quoted) output encoding to use, eg `"UTF-8"`
|
|
53
|
+
@param [in] termstr= (CRLF) The line seperator to use. For SASJS, will
|
|
54
|
+
always be CRLF. Valid values:
|
|
55
|
+
@li CRLF
|
|
56
|
+
@li LF
|
|
57
|
+
|
|
58
|
+
<h4> SAS Macros </h4>
|
|
59
|
+
@li mcf_getfmttype.sas
|
|
60
|
+
@li mf_getuniquename.sas
|
|
61
|
+
@li mf_getvarformat.sas
|
|
62
|
+
@li mf_getvarlist.sas
|
|
63
|
+
@li mf_getvartype.sas
|
|
64
|
+
|
|
65
|
+
@version 9.2
|
|
66
|
+
@author Allan Bowe (credit mjsq)
|
|
67
|
+
**/
|
|
68
|
+
|
|
69
|
+
%macro mp_ds2csv(ds
|
|
70
|
+
,dlm=COMMA
|
|
71
|
+
,outref=0
|
|
72
|
+
,outfile=
|
|
73
|
+
,outencoding=0
|
|
74
|
+
,headerformat=LABEL
|
|
75
|
+
,termstr=CRLF
|
|
76
|
+
)/*/STORE SOURCE*/;
|
|
77
|
+
|
|
78
|
+
%local outloc delim i varlist var vcnt vat dsv vcom vmiss fmttype vfmt;
|
|
79
|
+
|
|
80
|
+
%if not %sysfunc(exist(&ds)) %then %do;
|
|
81
|
+
%put %str(WARN)ING: &ds does not exist;
|
|
82
|
+
%return;
|
|
83
|
+
%end;
|
|
84
|
+
|
|
85
|
+
%if %index(&ds,.)=0 %then %let ds=WORK.&ds;
|
|
86
|
+
|
|
87
|
+
%if &outencoding=0 %then %let outencoding=;
|
|
88
|
+
%else %let outencoding=encoding=&outencoding;
|
|
89
|
+
|
|
90
|
+
%if &outref=0 %then %let outloc=&outfile;
|
|
91
|
+
%else %let outloc=&outref;
|
|
92
|
+
|
|
93
|
+
%if &headerformat=SASJS %then %do;
|
|
94
|
+
%let delim=",";
|
|
95
|
+
%let termstr=CRLF;
|
|
96
|
+
%mcf_getfmttype(wrap=YES)
|
|
97
|
+
%end;
|
|
98
|
+
%else %if &dlm=COMMA %then %let delim=",";
|
|
99
|
+
%else %let delim=";";
|
|
100
|
+
|
|
101
|
+
/* credit to mjsq - https://stackoverflow.com/a/55642267 */
|
|
102
|
+
|
|
103
|
+
/* first get headers */
|
|
104
|
+
data _null_;
|
|
105
|
+
file &outloc &outencoding lrecl=32767 termstr=&termstr;
|
|
106
|
+
length header $ 2000 varnm vfmt $32 dlm $1 fmttype $8;
|
|
107
|
+
call missing(of _all_);
|
|
108
|
+
dsid=open("&ds.","i");
|
|
109
|
+
num=attrn(dsid,"nvars");
|
|
110
|
+
dlm=&delim;
|
|
111
|
+
do i=1 to num;
|
|
112
|
+
varnm=upcase(varname(dsid,i));
|
|
113
|
+
if i=num then dlm='';
|
|
114
|
+
%if &headerformat=NAME %then %do;
|
|
115
|
+
header=cats(varnm,dlm);
|
|
116
|
+
%end;
|
|
117
|
+
%else %if &headerformat=LABEL %then %do;
|
|
118
|
+
header = cats(coalescec(varlabel(dsid,i),varnm),dlm);
|
|
119
|
+
%end;
|
|
120
|
+
%else %if &headerformat=SASJS %then %do;
|
|
121
|
+
if vartype(dsid,i)='C' then header=cats(varnm,':$char',varlen(dsid,i),'.');
|
|
122
|
+
else do;
|
|
123
|
+
vfmt=coalescec(varfmt(dsid,i),'0');
|
|
124
|
+
fmttype=mcf_getfmttype(vfmt);
|
|
125
|
+
if fmttype='DATE' then header=cats(varnm,':date9.');
|
|
126
|
+
else if fmttype='DATETIME' then header=cats(varnm,':E8601DT26.6');
|
|
127
|
+
else if fmttype='TIME' then header=cats(varnm,':TIME12.');
|
|
128
|
+
else header=cats(varnm,':best.');
|
|
129
|
+
end;
|
|
130
|
+
%end;
|
|
131
|
+
%else %do;
|
|
132
|
+
%put &sysmacroname: Invalid headerformat value (&headerformat);
|
|
133
|
+
%return;
|
|
134
|
+
%end;
|
|
135
|
+
put header @;
|
|
136
|
+
end;
|
|
137
|
+
rc=close(dsid);
|
|
138
|
+
run;
|
|
139
|
+
|
|
140
|
+
%let varlist=%mf_getvarlist(&ds);
|
|
141
|
+
%let vcnt=%sysfunc(countw(&varlist));
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The $quote modifier (without a width) will take the length from the variable
|
|
145
|
+
* and increase by two. However this will lead to truncation where the value
|
|
146
|
+
* contains double quotes (which are doubled up). To get around this, scan the
|
|
147
|
+
* data to see the max number of double quotes, so that the appropriate width
|
|
148
|
+
* can be applied in the subsequent step.
|
|
149
|
+
*/
|
|
150
|
+
data _null_;
|
|
151
|
+
set &ds end=last;
|
|
152
|
+
%do i=1 %to &vcnt;
|
|
153
|
+
%let var=%scan(&varlist,&i);
|
|
154
|
+
%if %mf_getvartype(&ds,&var)=C %then %do;
|
|
155
|
+
%let dsv1=%mf_getuniquename(prefix=csvcol1_);
|
|
156
|
+
%let dsv2=%mf_getuniquename(prefix=csvcol2_);
|
|
157
|
+
retain &dsv1 0;
|
|
158
|
+
&dsv2=length(&var)+countc(&var,'"');
|
|
159
|
+
if &dsv2>&dsv1 then &dsv1=&dsv2;
|
|
160
|
+
if last then call symputx(
|
|
161
|
+
"vlen&i"
|
|
162
|
+
/* should be no shorter than varlen, and no longer than 32767 */
|
|
163
|
+
,cats('$quote',min(&dsv1+2,32767),'.')
|
|
164
|
+
,'l'
|
|
165
|
+
);
|
|
166
|
+
%end;
|
|
167
|
+
%end;
|
|
168
|
+
|
|
169
|
+
%let vat=@;
|
|
170
|
+
%let vcom=&delim;
|
|
171
|
+
%let vmiss=%mf_getuniquename(prefix=csvcol3_);
|
|
172
|
+
/* next, export data */
|
|
173
|
+
data _null_;
|
|
174
|
+
set &ds.;
|
|
175
|
+
file &outloc mod dlm=&delim dsd &outencoding lrecl=32767 termstr=&termstr;
|
|
176
|
+
if _n_=1 then &vmiss=' ';
|
|
177
|
+
%do i=1 %to &vcnt;
|
|
178
|
+
%let var=%scan(&varlist,&i);
|
|
179
|
+
%if &i=&vcnt %then %do;
|
|
180
|
+
%let vat=;
|
|
181
|
+
%let vcom=;
|
|
182
|
+
%end;
|
|
183
|
+
%if %mf_getvartype(&ds,&var)=N %then %do;
|
|
184
|
+
%if &headerformat = SASJS %then %do;
|
|
185
|
+
%let vcom=&delim;
|
|
186
|
+
%let fmttype=%sysfunc(mcf_getfmttype(%mf_getvarformat(&ds,&var)0));
|
|
187
|
+
%if &fmttype=DATE %then %let vfmt=DATE9.;
|
|
188
|
+
%else %if &fmttype=DATETIME %then %let vfmt=E8601DT26.6;
|
|
189
|
+
%else %if &fmttype=TIME %then %let vfmt=TIME12.;
|
|
190
|
+
%else %do;
|
|
191
|
+
%let vfmt=;
|
|
192
|
+
%let vcom=;
|
|
193
|
+
%end;
|
|
194
|
+
%end;
|
|
195
|
+
%else %let vcom=;
|
|
196
|
+
|
|
197
|
+
/* must use period - in order to work in both 9.4 and Viya 3.5 */
|
|
198
|
+
if missing(&var) and &var ne %sysfunc(getoption(MISSING)) then do;
|
|
199
|
+
&vmiss=cats('.',&var);
|
|
200
|
+
put &vmiss &vat;
|
|
201
|
+
end;
|
|
202
|
+
else put &var &vfmt &vcom &vat;
|
|
203
|
+
|
|
204
|
+
%end;
|
|
205
|
+
%else %do;
|
|
206
|
+
%if &i ne &vcnt %then %let vcom=&delim;
|
|
207
|
+
put &var &&vlen&i &vcom &vat;
|
|
208
|
+
%end;
|
|
209
|
+
%end;
|
|
210
|
+
run;
|
|
211
|
+
|
|
212
|
+
%mend mp_ds2csv;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief A wrapper for mp_getddl.sas
|
|
4
|
+
@details In the next release, this will be the main version.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
<h4> SAS Macros </h4>
|
|
8
|
+
@li mp_getddl.sas
|
|
9
|
+
|
|
10
|
+
**/
|
|
11
|
+
|
|
12
|
+
%macro mp_ds2ddl(libds,fref=getddl,flavour=SAS,showlog=YES,schema=
|
|
13
|
+
,applydttm=NO
|
|
14
|
+
)/*/STORE SOURCE*/;
|
|
15
|
+
|
|
16
|
+
%local libref;
|
|
17
|
+
%let libds=%upcase(&libds);
|
|
18
|
+
%let libref=%scan(&libds,1,.);
|
|
19
|
+
%if &libref=&libds %then %let libds=WORK.&libds;
|
|
20
|
+
|
|
21
|
+
%mp_getddl(%scan(&libds,1,.)
|
|
22
|
+
,%scan(&libds,2,.)
|
|
23
|
+
,fref=&fref
|
|
24
|
+
,flavour=SAS
|
|
25
|
+
,showlog=&showlog
|
|
26
|
+
,schema=&schema
|
|
27
|
+
,applydttm=&applydttm
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
%mend mp_ds2ddl;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Converts every value in a dataset to formatted value
|
|
4
|
+
@details Converts every value to it's formatted value. All variables will
|
|
5
|
+
become character, and will be in the same order as the original dataset.
|
|
6
|
+
|
|
7
|
+
Lengths will be adjusted according to the format lengths, where applicable.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
|
|
11
|
+
%mp_ds2fmtds(sashelp.cars,work.cars)
|
|
12
|
+
%mp_ds2fmtds(sashelp.vallopt,vw_vallopt)
|
|
13
|
+
|
|
14
|
+
@param [in] libds The library.dataset to be converted
|
|
15
|
+
@param [out] outds The dataset to create.
|
|
16
|
+
|
|
17
|
+
<h4> SAS Macros </h4>
|
|
18
|
+
@li mf_existds.sas
|
|
19
|
+
|
|
20
|
+
<h4> Related Macros </h4>
|
|
21
|
+
@li mp_jsonout.sas
|
|
22
|
+
|
|
23
|
+
@version 9.2
|
|
24
|
+
@author Allan Bowe
|
|
25
|
+
**/
|
|
26
|
+
|
|
27
|
+
%macro mp_ds2fmtds(libds, outds
|
|
28
|
+
)/*/STORE SOURCE*/;
|
|
29
|
+
|
|
30
|
+
/* validations */
|
|
31
|
+
|
|
32
|
+
%if not %mf_existds(libds=&libds) %then %do;
|
|
33
|
+
%put %str(WARN)ING: &libds does not exist as either a VIEW or DATASET;
|
|
34
|
+
%return;
|
|
35
|
+
%end;
|
|
36
|
+
%if %index(&libds,.)=0 %then %let libds=WORK.&libds;
|
|
37
|
+
|
|
38
|
+
/* grab metadata */
|
|
39
|
+
proc contents noprint data=&libds
|
|
40
|
+
out=_data_(keep=name type length format formatl formatd varnum);
|
|
41
|
+
run;
|
|
42
|
+
proc sort;
|
|
43
|
+
by varnum;
|
|
44
|
+
run;
|
|
45
|
+
|
|
46
|
+
/* prepare formats and varnames */
|
|
47
|
+
data _null_;
|
|
48
|
+
set &syslast end=last;
|
|
49
|
+
name=upcase(name);
|
|
50
|
+
/* fix formats */
|
|
51
|
+
if type=2 or type=6 then do;
|
|
52
|
+
length fmt $49.;
|
|
53
|
+
if format='' then fmt=cats('$',length,'.');
|
|
54
|
+
else if formatl=0 then fmt=cats(format,'.');
|
|
55
|
+
else fmt=cats(format,formatl,'.');
|
|
56
|
+
newlen=max(formatl,length);
|
|
57
|
+
end;
|
|
58
|
+
else do;
|
|
59
|
+
if format='' then fmt='best.';
|
|
60
|
+
else if formatl=0 then fmt=cats(format,'.');
|
|
61
|
+
else if formatd=0 then fmt=cats(format,formatl,'.');
|
|
62
|
+
else fmt=cats(format,formatl,'.',formatd);
|
|
63
|
+
/* needs to be wide, for datetimes etc */
|
|
64
|
+
newlen=max(length,formatl,24);
|
|
65
|
+
end;
|
|
66
|
+
/* 32 char unique name */
|
|
67
|
+
newname='sasjs'!!substr(cats(put(md5(name),$hex32.)),1,27);
|
|
68
|
+
|
|
69
|
+
call symputx(cats('name',_n_),name,'l');
|
|
70
|
+
call symputx(cats('newname',_n_),newname,'l');
|
|
71
|
+
call symputx(cats('len',_n_),newlen,'l');
|
|
72
|
+
call symputx(cats('fmt',_n_),fmt,'l');
|
|
73
|
+
call symputx(cats('type',_n_),type,'l');
|
|
74
|
+
if last then call symputx('nobs',_n_,'l');
|
|
75
|
+
run;
|
|
76
|
+
|
|
77
|
+
/* clean up */
|
|
78
|
+
proc sql;
|
|
79
|
+
drop table &syslast;
|
|
80
|
+
|
|
81
|
+
%if &nobs=0 %then %do;
|
|
82
|
+
%put Dataset &libds has no columns!
|
|
83
|
+
data &outds;
|
|
84
|
+
set &libds;
|
|
85
|
+
run;
|
|
86
|
+
%return;
|
|
87
|
+
%end;
|
|
88
|
+
|
|
89
|
+
data &outds;
|
|
90
|
+
/* rename on entry */
|
|
91
|
+
set &libds(rename=(
|
|
92
|
+
%local i;
|
|
93
|
+
%do i=1 %to &nobs;
|
|
94
|
+
&&name&i=&&newname&i
|
|
95
|
+
%end;
|
|
96
|
+
));
|
|
97
|
+
%do i=1 %to &nobs;
|
|
98
|
+
length &&name&i $&&len&i;
|
|
99
|
+
&&name&i=left(put(&&newname&i,&&fmt&i));
|
|
100
|
+
drop &&newname&i;
|
|
101
|
+
%end;
|
|
102
|
+
if _error_ then call symputx('syscc',1012);
|
|
103
|
+
run;
|
|
104
|
+
|
|
105
|
+
%mend mp_ds2fmtds;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Export a dataset to SQL insert statements
|
|
4
|
+
@details Converts dataset values to SQL insert statements for use across
|
|
5
|
+
multiple database types.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
|
|
9
|
+
%mp_ds2inserts(sashelp.class,outref=myref,outds=class)
|
|
10
|
+
data class;
|
|
11
|
+
set sashelp.class;
|
|
12
|
+
stop;
|
|
13
|
+
proc sql;
|
|
14
|
+
%inc myref;
|
|
15
|
+
|
|
16
|
+
@param [in] ds The dataset to be exported
|
|
17
|
+
@param [in] maxobs= (max) The max number of inserts to create
|
|
18
|
+
@param [out] outref= (0) The output fileref. If it does not exist, it is
|
|
19
|
+
created. If it does exist, new records are APPENDED.
|
|
20
|
+
@param [out] schema= (0) The library (or schema) in which the target table is
|
|
21
|
+
located. If not provided, is ignored.
|
|
22
|
+
@param [out] outds= (0) The output table to load. If not provided, will
|
|
23
|
+
default to the table in the &ds parameter.
|
|
24
|
+
@param [in] flavour= (SAS) The SQL flavour to be applied to the output. Valid
|
|
25
|
+
options:
|
|
26
|
+
@li SAS (default) - suitable for regular proc sql
|
|
27
|
+
@li PGSQL - Used for Postgres databases
|
|
28
|
+
@param [in] applydttm= (YES) If YES, any columns using datetime formats will
|
|
29
|
+
be converted to native DB datetime literals
|
|
30
|
+
|
|
31
|
+
<h4> SAS Macros </h4>
|
|
32
|
+
@li mf_existfileref.sas
|
|
33
|
+
@li mf_getvarcount.sas
|
|
34
|
+
@li mf_getvarformat.sas
|
|
35
|
+
@li mf_getvarlist.sas
|
|
36
|
+
@li mf_getvartype.sas
|
|
37
|
+
|
|
38
|
+
@version 9.2
|
|
39
|
+
@author Allan Bowe (credit mjsq)
|
|
40
|
+
**/
|
|
41
|
+
|
|
42
|
+
%macro mp_ds2inserts(ds, outref=0,schema=0,outds=0,flavour=SAS,maxobs=max
|
|
43
|
+
,applydttm=YES
|
|
44
|
+
)/*/STORE SOURCE*/;
|
|
45
|
+
|
|
46
|
+
%if not %sysfunc(exist(&ds)) %then %do;
|
|
47
|
+
%put %str(WAR)NING: &ds does not exist;
|
|
48
|
+
%return;
|
|
49
|
+
%end;
|
|
50
|
+
|
|
51
|
+
%if not %sysfunc(exist(&ds)) %then %do;
|
|
52
|
+
%put %str(WAR)NING: &ds does not exist;
|
|
53
|
+
%return;
|
|
54
|
+
%end;
|
|
55
|
+
|
|
56
|
+
%if %index(&ds,.)=0 %then %let ds=WORK.&ds;
|
|
57
|
+
|
|
58
|
+
%let flavour=%upcase(&flavour);
|
|
59
|
+
%if &flavour ne SAS and &flavour ne PGSQL %then %do;
|
|
60
|
+
%put %str(WAR)NING: &flavour is not supported;
|
|
61
|
+
%return;
|
|
62
|
+
%end;
|
|
63
|
+
|
|
64
|
+
%if &outref=0 %then %do;
|
|
65
|
+
%put %str(WAR)NING: Please provide a fileref;
|
|
66
|
+
%return;
|
|
67
|
+
%end;
|
|
68
|
+
%if %mf_existfileref(&outref)=0 %then %do;
|
|
69
|
+
filename &outref temp lrecl=66000;
|
|
70
|
+
%end;
|
|
71
|
+
|
|
72
|
+
%if &schema=0 %then %let schema=;
|
|
73
|
+
%else %let schema=&schema..;
|
|
74
|
+
|
|
75
|
+
%if &outds=0 %then %let outds=%scan(&ds,2,.);
|
|
76
|
+
|
|
77
|
+
%local nobs;
|
|
78
|
+
proc sql noprint;
|
|
79
|
+
select count(*) into: nobs TRIMMED from &ds;
|
|
80
|
+
%if &nobs=0 %then %do;
|
|
81
|
+
data _null_;
|
|
82
|
+
file &outref mod;
|
|
83
|
+
put "/* No rows found in &ds */";
|
|
84
|
+
run;
|
|
85
|
+
%end;
|
|
86
|
+
|
|
87
|
+
%local vars;
|
|
88
|
+
%let vars=%mf_getvarcount(&ds);
|
|
89
|
+
%if &vars=0 %then %do;
|
|
90
|
+
data _null_;
|
|
91
|
+
file &outref mod;
|
|
92
|
+
put "/* No columns found in &schema.&ds */";
|
|
93
|
+
run;
|
|
94
|
+
%return;
|
|
95
|
+
%end;
|
|
96
|
+
%else %if &vars>1600 and &flavour=PGSQL %then %do;
|
|
97
|
+
data _null_;
|
|
98
|
+
file &fref mod;
|
|
99
|
+
put "/* &schema.&ds contains &vars vars */";
|
|
100
|
+
put "/* Postgres cannot handle tables with over 1600 vars */";
|
|
101
|
+
put "/* No inserts will be generated for this table */";
|
|
102
|
+
run;
|
|
103
|
+
%return;
|
|
104
|
+
%end;
|
|
105
|
+
|
|
106
|
+
%local varlist varlistcomma;
|
|
107
|
+
%let varlist=%mf_getvarlist(&ds);
|
|
108
|
+
%let varlistcomma=%mf_getvarlist(&ds,dlm=%str(,),quote=double);
|
|
109
|
+
|
|
110
|
+
/* next, export data */
|
|
111
|
+
data _null_;
|
|
112
|
+
file &outref mod ;
|
|
113
|
+
if _n_=1 then put "/* &schema.&outds (&nobs rows, &vars columns) */";
|
|
114
|
+
set &ds;
|
|
115
|
+
%if &maxobs ne max %then %do;
|
|
116
|
+
if _n_>&maxobs then stop;
|
|
117
|
+
%end;
|
|
118
|
+
length _____str $32767;
|
|
119
|
+
call missing(_____str);
|
|
120
|
+
format _numeric_ best.;
|
|
121
|
+
format _character_ ;
|
|
122
|
+
%local i comma var vtype vfmt;
|
|
123
|
+
%do i=1 %to %sysfunc(countw(&varlist));
|
|
124
|
+
%let var=%scan(&varlist,&i);
|
|
125
|
+
%let vtype=%mf_getvartype(&ds,&var);
|
|
126
|
+
%let vfmt=%upcase(%mf_getvarformat(&ds,&var,force=1));
|
|
127
|
+
%if &i=1 %then %do;
|
|
128
|
+
%if &flavour=SAS %then %do;
|
|
129
|
+
put "insert into &schema.&outds set ";
|
|
130
|
+
put " &var="@;
|
|
131
|
+
%end;
|
|
132
|
+
%else %if &flavour=PGSQL %then %do;
|
|
133
|
+
_____str=cats(
|
|
134
|
+
"INSERT INTO &schema.&outds ("
|
|
135
|
+
,symget('varlistcomma')
|
|
136
|
+
,") VALUES ("
|
|
137
|
+
);
|
|
138
|
+
put _____str;
|
|
139
|
+
put " "@;
|
|
140
|
+
%end;
|
|
141
|
+
%end;
|
|
142
|
+
%else %do;
|
|
143
|
+
%if &flavour=SAS %then %do;
|
|
144
|
+
put " ,&var="@;
|
|
145
|
+
%end;
|
|
146
|
+
%else %if &flavour=PGSQL %then %do;
|
|
147
|
+
put " ,"@;
|
|
148
|
+
%end;
|
|
149
|
+
%end;
|
|
150
|
+
%if &vtype=N %then %do;
|
|
151
|
+
%if &flavour=SAS %then %do;
|
|
152
|
+
put &var;
|
|
153
|
+
%end;
|
|
154
|
+
%else %if &flavour=PGSQL %then %do;
|
|
155
|
+
if missing(&var) then put 'NULL';
|
|
156
|
+
%if &applydttm=YES and "%substr(&vfmt.xxxxxxxx,1,8)"="DATETIME"
|
|
157
|
+
%then %do;
|
|
158
|
+
else put "TIMESTAMP '" &var E8601DT25.6 "'";
|
|
159
|
+
%end;
|
|
160
|
+
%else %do;
|
|
161
|
+
else put &var;
|
|
162
|
+
%end;
|
|
163
|
+
%end;
|
|
164
|
+
%end;
|
|
165
|
+
%else %do;
|
|
166
|
+
_____str="'"!!trim(tranwrd(&var,"'","''"))!!"'";
|
|
167
|
+
put _____str;
|
|
168
|
+
%end;
|
|
169
|
+
%end;
|
|
170
|
+
%if &flavour=SAS %then %do;
|
|
171
|
+
put ';';
|
|
172
|
+
%end;
|
|
173
|
+
%else %if &flavour=PGSQL %then %do;
|
|
174
|
+
put ');';
|
|
175
|
+
%end;
|
|
176
|
+
|
|
177
|
+
if _n_=&nobs then put /;
|
|
178
|
+
run;
|
|
179
|
+
|
|
180
|
+
%mend mp_ds2inserts;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Create a Markdown Table from a dataset
|
|
4
|
+
@details A markdown table is a simple table representation for use in
|
|
5
|
+
documents written in markdown format.
|
|
6
|
+
|
|
7
|
+
An online generator is available here:
|
|
8
|
+
https://www.tablesgenerator.com/markdown_tables
|
|
9
|
+
|
|
10
|
+
This structure is also used by the Macro Core library for documenting input/
|
|
11
|
+
output datasets, as well as the sasjs/cli tool for documenting inputs/outputs
|
|
12
|
+
for web services.
|
|
13
|
+
|
|
14
|
+
We take the standard definition one step further by embedding the informat
|
|
15
|
+
in the table header row, like so:
|
|
16
|
+
|
|
17
|
+
|var1:$32|var2:best.|var3:date9.|
|
|
18
|
+
|---|---|---|
|
|
19
|
+
|some text|42|01JAN1960|
|
|
20
|
+
|blah|1|31DEC1999|
|
|
21
|
+
|
|
22
|
+
Which resolves to:
|
|
23
|
+
|
|
24
|
+
|var1:$32|var2:best.|var3:date9.|
|
|
25
|
+
|---|---|---|
|
|
26
|
+
|some text|42|01JAN1960|
|
|
27
|
+
|blah|1|31DEC1999|
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
Usage:
|
|
31
|
+
|
|
32
|
+
%mp_ds2md(sashelp.class)
|
|
33
|
+
|
|
34
|
+
@param [in] libds the library / dataset to create or read from.
|
|
35
|
+
@param [out] outref= (mdtable) Fileref to contain the markdown
|
|
36
|
+
@param [out] showlog= (YES) Set to NO to avoid printing markdown to the log
|
|
37
|
+
|
|
38
|
+
<h4> SAS Macros </h4>
|
|
39
|
+
@li mf_getvarlist.sas
|
|
40
|
+
@li mf_getvarformat.sas
|
|
41
|
+
|
|
42
|
+
@version 9.3
|
|
43
|
+
@author Allan Bowe
|
|
44
|
+
**/
|
|
45
|
+
|
|
46
|
+
%macro mp_ds2md(
|
|
47
|
+
libds,
|
|
48
|
+
outref=mdtable,
|
|
49
|
+
showlog=YES
|
|
50
|
+
)/*/STORE SOURCE*/;
|
|
51
|
+
|
|
52
|
+
/* check fileref is assigned */
|
|
53
|
+
%if %sysfunc(fileref(&outref)) > 0 %then %do;
|
|
54
|
+
filename &outref temp;
|
|
55
|
+
%end;
|
|
56
|
+
|
|
57
|
+
%local vars;
|
|
58
|
+
%let vars=%upcase(%mf_getvarlist(&libds));
|
|
59
|
+
|
|
60
|
+
%if %trim(X&vars)=X %then %do;
|
|
61
|
+
%put &sysmacroname: Table &libds has no columns!!;
|
|
62
|
+
%return;
|
|
63
|
+
%end;
|
|
64
|
+
|
|
65
|
+
/* create the header row */
|
|
66
|
+
data _null_;
|
|
67
|
+
file &outref;
|
|
68
|
+
length line $32767;
|
|
69
|
+
call missing(line);
|
|
70
|
+
put '|'
|
|
71
|
+
%local i var fmt;
|
|
72
|
+
%do i=1 %to %sysfunc(countw(&vars));
|
|
73
|
+
%let var=%scan(&vars,&i);
|
|
74
|
+
%let fmt=%lowcase(%mf_getvarformat(&libds,&var,force=1));
|
|
75
|
+
"&var:&fmt|"
|
|
76
|
+
%end;
|
|
77
|
+
;
|
|
78
|
+
put '|'
|
|
79
|
+
%do i=1 %to %sysfunc(countw(&vars));
|
|
80
|
+
"---|"
|
|
81
|
+
%end;
|
|
82
|
+
;
|
|
83
|
+
run;
|
|
84
|
+
|
|
85
|
+
/* write out the data */
|
|
86
|
+
data _null_;
|
|
87
|
+
file &outref mod dlm='|' lrecl=32767;
|
|
88
|
+
set &libds ;
|
|
89
|
+
length line $32767;
|
|
90
|
+
line='|`'!!cats(%mf_getvarlist(&libds,dlm=%str(%)!!' `|`'!!cats%()))!!' `|';
|
|
91
|
+
put line;
|
|
92
|
+
run;
|
|
93
|
+
|
|
94
|
+
%if %upcase(&showlog)=YES %then %do;
|
|
95
|
+
options ps=max lrecl=max;
|
|
96
|
+
data _null_;
|
|
97
|
+
infile &outref;
|
|
98
|
+
input;
|
|
99
|
+
putlog _infile_;
|
|
100
|
+
run;
|
|
101
|
+
%end;
|
|
102
|
+
|
|
103
|
+
%mend mp_ds2md;
|