mirror of
https://github.com/sasjs/core.git
synced 2025-12-16 00:24:35 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1613ab2c9e | ||
|
|
a2df4e35be | ||
|
|
aabbcfdf6b | ||
|
|
7b7759e1ce | ||
|
|
e5a3053600 | ||
|
|
9856d0ef58 | ||
|
|
77b37e5503 | ||
|
|
793319fe38 | ||
|
|
594a895ddd | ||
|
|
0d59266b8d | ||
|
|
4863aafaa8 | ||
|
|
6015320145 | ||
|
|
8c09c0bce0 | ||
|
|
437943b779 | ||
|
|
6a090e45b6 | ||
|
|
a7dc314204 |
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
@file mp_cleancsv.sas
|
||||
@file
|
||||
@brief Fixes embedded cr / lf / crlf in CSV
|
||||
@details CSVs will sometimes contain lf or crlf within quotes (eg when
|
||||
saved by excel). When the termstr is ALSO lf or crlf that can be tricky
|
||||
@@ -7,14 +7,16 @@
|
||||
This macro converts any csv to follow the convention of a windows excel file,
|
||||
applying CRLF line endings and converting embedded cr and crlf to lf.
|
||||
|
||||
usage:
|
||||
Usage:
|
||||
|
||||
fileref mycsv "/path/your/csv";
|
||||
%mp_cleancsv(in=mycsv,out=/path/new.csv)
|
||||
|
||||
@param in= provide path or fileref to input csv
|
||||
@param out= output path or fileref to output csv
|
||||
@param qchar= quote char - hex code 22 is the double quote.
|
||||
@param in= (NOTPROVIDED) Provide path or fileref to input csv. If a period is
|
||||
found, it is assumed to be a file.
|
||||
@param out= (NOTPROVIDED) Output path or fileref to output csv. If a period
|
||||
is found, it is assumed to be a file.
|
||||
@param qchar= ('22'x) Quote char - hex code 22 is the double quote.
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe
|
||||
@@ -56,9 +58,14 @@
|
||||
else do;
|
||||
/* outside a quote, change cr and lf to crlf */
|
||||
if inchar='0D'x then do;
|
||||
crblank:
|
||||
put '0D0A'x;
|
||||
input inchar $char1.;
|
||||
if inchar ne '0A'x then do;
|
||||
if inchar='0D'x then do;
|
||||
/* multiple CR indicates CR formatted file with blank lines */
|
||||
goto crblank;
|
||||
end;
|
||||
else if inchar ne '0A'x then do;
|
||||
put inchar $char1.;
|
||||
if inchar=qchar then isq = mod(isq+1,2);
|
||||
end;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_existds.sas
|
||||
|
||||
<h4> Related Macros <h4>
|
||||
<h4> Related Macros </h4>
|
||||
@li mp_jsonout.sas
|
||||
|
||||
@version 9.2
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
@param [in] maxobs= (MAX) Provide an integer to limit the number of input rows
|
||||
that should be converted to JSON
|
||||
|
||||
<h4> Related Macros <h4>
|
||||
<h4> Related Files </h4>
|
||||
@li mp_ds2fmtds.sas
|
||||
|
||||
@version 9.2
|
||||
@@ -70,14 +70,14 @@
|
||||
@source https://github.com/sasjs/core
|
||||
|
||||
**/
|
||||
|
||||
%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y
|
||||
,engine=DATASTEP
|
||||
,missing=NULL
|
||||
,showmeta=N
|
||||
,maxobs=MAX
|
||||
)/*/STORE SOURCE*/;
|
||||
%local tempds colinfo fmtds i numcols stmt_obs;
|
||||
%local tempds colinfo fmtds i numcols numobs stmt_obs lastobs optval
|
||||
tmpds1 tmpds2 tmpds3 tmpds4;
|
||||
%let numcols=0;
|
||||
%if &maxobs ne MAX %then %let stmt_obs=%str(if _n_>&maxobs then stop;);
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
by varnum;
|
||||
run;
|
||||
/* move meta to mac vars */
|
||||
data _null_;
|
||||
data &colinfo;
|
||||
if _n_=1 then call symputx('numcols',nobs,'l');
|
||||
set &colinfo end=last nobs=nobs;
|
||||
name=upcase(name);
|
||||
@@ -144,9 +144,15 @@
|
||||
call symputx(cats('type',_n_),type,'l');
|
||||
call symputx(cats('typelong',_n_),typelong,'l');
|
||||
call symputx(cats('label',_n_),coalescec(label,name),'l');
|
||||
/* overwritten when fmt=Y and a custom format exists in catalog */
|
||||
if typelong='num' then call symputx(cats('fmtlen',_n_),200,'l');
|
||||
else call symputx(cats('fmtlen',_n_),min(32767,ceil((length+3)*1.5)),'l');
|
||||
run;
|
||||
|
||||
%let tempds=%substr(_%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32);
|
||||
proc sql;
|
||||
select count(*) into: lastobs from &ds;
|
||||
%if &maxobs ne MAX %then %let lastobs=%sysfunc(min(&lastobs,&maxobs));
|
||||
|
||||
%if &engine=PROCJSON %then %do;
|
||||
%if &missing=STRING %then %do;
|
||||
@@ -183,27 +189,99 @@
|
||||
%end;
|
||||
|
||||
%if &fmt=Y %then %do;
|
||||
data _data_;
|
||||
/**
|
||||
* Extract format definitions
|
||||
* First, by getting library locations from dictionary.formats
|
||||
* Then, by exporting the width using proc format
|
||||
* Cannot use maxw from sashelp.vformat as not always populated
|
||||
* Cannot use fmtinfo() as not supported in all flavours
|
||||
*/
|
||||
%let tmpds1=%substr(fmtsum%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32);
|
||||
%let tmpds2=%substr(cntl%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32);
|
||||
%let tmpds3=%substr(cntl%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32);
|
||||
%let tmpds4=%substr(col%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32);
|
||||
proc sql noprint;
|
||||
create table &tmpds1 as
|
||||
select cats(libname,'.',memname) as fmtcat,
|
||||
fmtname
|
||||
from dictionary.formats
|
||||
where fmttype='F' and libname is not null
|
||||
and fmtname in (select format from &colinfo where format is not null)
|
||||
order by 1;
|
||||
create table &tmpds2(
|
||||
FMTNAME char(32),
|
||||
LENGTH num
|
||||
);
|
||||
%local catlist cat fmtlist i;
|
||||
select distinct fmtcat into: catlist separated by ' ' from &tmpds1;
|
||||
%do i=1 %to %sysfunc(countw(&catlist,%str( )));
|
||||
%let cat=%scan(&catlist,&i,%str( ));
|
||||
proc sql;
|
||||
select distinct fmtname into: fmtlist separated by ' '
|
||||
from &tmpds1 where fmtcat="&cat";
|
||||
proc format lib=&cat cntlout=&tmpds3(keep=fmtname length);
|
||||
select &fmtlist;
|
||||
run;
|
||||
proc sql;
|
||||
insert into &tmpds2 select distinct fmtname,length from &tmpds3;
|
||||
%end;
|
||||
|
||||
proc sql;
|
||||
create table &tmpds4 as
|
||||
select a.*, b.length as maxw
|
||||
from &colinfo a
|
||||
left join &tmpds2 b
|
||||
on cats(a.format)=cats(upcase(b.fmtname))
|
||||
order by a.varnum;
|
||||
data _null_;
|
||||
set &tmpds4;
|
||||
if not missing(maxw);
|
||||
call symputx(
|
||||
cats('fmtlen',_n_),
|
||||
/* vars need extra padding due to JSON escaping of special chars */
|
||||
min(32767,ceil((max(length,maxw)+3)*1.5))
|
||||
,'l'
|
||||
);
|
||||
run;
|
||||
|
||||
/* configure varlenchk - as we are explicitly shortening the variables */
|
||||
%let optval=%sysfunc(getoption(varlenchk));
|
||||
options varlenchk=NOWARN;
|
||||
data _data_(compress=char);
|
||||
/* shorten the new vars */
|
||||
length
|
||||
%do i=1 %to &numcols;
|
||||
&&name&i $&&fmtlen&i
|
||||
%end;
|
||||
;
|
||||
/* rename on entry */
|
||||
set &ds(rename=(
|
||||
%do i=1 %to &numcols;
|
||||
&&name&i=&&newname&i
|
||||
&&name&i=&&newname&i
|
||||
%end;
|
||||
));
|
||||
&stmt_obs;
|
||||
|
||||
drop
|
||||
%do i=1 %to &numcols;
|
||||
&&newname&i
|
||||
%end;
|
||||
;
|
||||
%do i=1 %to &numcols;
|
||||
/* formatted values can be up to length 32767 */
|
||||
length &&name&i $32767;
|
||||
%if &&typelong&i=num %then %do;
|
||||
&&name&i=left(put(&&newname&i,&&fmt&i));
|
||||
&&name&i=cats(put(&&newname&i,&&fmt&i));
|
||||
%end;
|
||||
%else %do;
|
||||
&&name&i=put(&&newname&i,&&fmt&i);
|
||||
%end;
|
||||
drop &&newname&i;
|
||||
%end;
|
||||
if _error_ then call symputx('syscc',1012);
|
||||
if _error_ then do;
|
||||
call symputx('syscc',1012);
|
||||
stop;
|
||||
end;
|
||||
run;
|
||||
%let fmtds=&syslast;
|
||||
options varlenchk=&optval;
|
||||
%end;
|
||||
|
||||
proc format; /* credit yabwon for special null removal */
|
||||
@@ -222,8 +300,8 @@
|
||||
attrib _all_ label='';
|
||||
%do i=1 %to &numcols;
|
||||
%if &&typelong&i=char or &fmt=Y %then %do;
|
||||
length &&name&i $32767;
|
||||
format &&name&i $32767.;
|
||||
length &&name&i $&&fmtlen&i...;
|
||||
format &&name&i $&&fmtlen&i...;
|
||||
%end;
|
||||
%end;
|
||||
%if &fmt=Y %then %do;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
/**
|
||||
@file
|
||||
@brief Logs the time the macro was executed in a control dataset.
|
||||
@details If the dataset does not exist, it is created. Usage:
|
||||
@brief Logs a message in a dataset every time it is invoked
|
||||
@details If the dataset does not exist, it is created.
|
||||
Usage:
|
||||
|
||||
%mp_perflog(started)
|
||||
%mp_perflog()
|
||||
%mp_perflog(startanew,libds=work.newdataset)
|
||||
%mp_perflog(finished,libds=work.newdataset)
|
||||
%mp_perflog(finished)
|
||||
%mp_perflog(started)
|
||||
%mp_perflog()
|
||||
%mp_perflog(startanew,libds=work.newdataset)
|
||||
%mp_perflog(finished,libds=work.newdataset)
|
||||
%mp_perflog(finished)
|
||||
|
||||
|
||||
@param label Provide label to go into the control dataset
|
||||
|
||||
@@ -93,14 +93,14 @@ data _null_;
|
||||
file sasjs lrecl=3000 ;
|
||||
put "/* Created on %sysfunc(datetime(),datetime19.) by %mf_getuser() */";
|
||||
/* WEBOUT BEGIN */
|
||||
put ' ';
|
||||
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
||||
put ' ,engine=DATASTEP ';
|
||||
put ' ,missing=NULL ';
|
||||
put ' ,showmeta=N ';
|
||||
put ' ,maxobs=MAX ';
|
||||
put ')/*/STORE SOURCE*/; ';
|
||||
put '%local tempds colinfo fmtds i numcols stmt_obs; ';
|
||||
put '%local tempds colinfo fmtds i numcols numobs stmt_obs lastobs optval ';
|
||||
put ' tmpds1 tmpds2 tmpds3 tmpds4; ';
|
||||
put '%let numcols=0; ';
|
||||
put '%if &maxobs ne MAX %then %let stmt_obs=%str(if _n_>&maxobs then stop;); ';
|
||||
put ' ';
|
||||
@@ -138,7 +138,7 @@ data _null_;
|
||||
put ' by varnum; ';
|
||||
put ' run; ';
|
||||
put ' /* move meta to mac vars */ ';
|
||||
put ' data _null_; ';
|
||||
put ' data &colinfo; ';
|
||||
put ' if _n_=1 then call symputx(''numcols'',nobs,''l''); ';
|
||||
put ' set &colinfo end=last nobs=nobs; ';
|
||||
put ' name=upcase(name); ';
|
||||
@@ -167,9 +167,15 @@ data _null_;
|
||||
put ' call symputx(cats(''type'',_n_),type,''l''); ';
|
||||
put ' call symputx(cats(''typelong'',_n_),typelong,''l''); ';
|
||||
put ' call symputx(cats(''label'',_n_),coalescec(label,name),''l''); ';
|
||||
put ' /* overwritten when fmt=Y and a custom format exists in catalog */ ';
|
||||
put ' if typelong=''num'' then call symputx(cats(''fmtlen'',_n_),200,''l''); ';
|
||||
put ' else call symputx(cats(''fmtlen'',_n_),min(32767,ceil((length+3)*1.5)),''l''); ';
|
||||
put ' run; ';
|
||||
put ' ';
|
||||
put ' %let tempds=%substr(_%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' proc sql; ';
|
||||
put ' select count(*) into: lastobs from &ds; ';
|
||||
put ' %if &maxobs ne MAX %then %let lastobs=%sysfunc(min(&lastobs,&maxobs)); ';
|
||||
put ' ';
|
||||
put ' %if &engine=PROCJSON %then %do; ';
|
||||
put ' %if &missing=STRING %then %do; ';
|
||||
@@ -206,27 +212,99 @@ data _null_;
|
||||
put ' %end; ';
|
||||
put ' ';
|
||||
put ' %if &fmt=Y %then %do; ';
|
||||
put ' data _data_; ';
|
||||
put ' /** ';
|
||||
put ' * Extract format definitions ';
|
||||
put ' * First, by getting library locations from dictionary.formats ';
|
||||
put ' * Then, by exporting the width using proc format ';
|
||||
put ' * Cannot use maxw from sashelp.vformat as not always populated ';
|
||||
put ' * Cannot use fmtinfo() as not supported in all flavours ';
|
||||
put ' */ ';
|
||||
put ' %let tmpds1=%substr(fmtsum%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' %let tmpds2=%substr(cntl%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' %let tmpds3=%substr(cntl%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' %let tmpds4=%substr(col%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' proc sql noprint; ';
|
||||
put ' create table &tmpds1 as ';
|
||||
put ' select cats(libname,''.'',memname) as fmtcat, ';
|
||||
put ' fmtname ';
|
||||
put ' from dictionary.formats ';
|
||||
put ' where fmttype=''F'' and libname is not null ';
|
||||
put ' and fmtname in (select format from &colinfo where format is not null) ';
|
||||
put ' order by 1; ';
|
||||
put ' create table &tmpds2( ';
|
||||
put ' FMTNAME char(32), ';
|
||||
put ' LENGTH num ';
|
||||
put ' ); ';
|
||||
put ' %local catlist cat fmtlist i; ';
|
||||
put ' select distinct fmtcat into: catlist separated by '' '' from &tmpds1; ';
|
||||
put ' %do i=1 %to %sysfunc(countw(&catlist,%str( ))); ';
|
||||
put ' %let cat=%scan(&catlist,&i,%str( )); ';
|
||||
put ' proc sql; ';
|
||||
put ' select distinct fmtname into: fmtlist separated by '' '' ';
|
||||
put ' from &tmpds1 where fmtcat="&cat"; ';
|
||||
put ' proc format lib=&cat cntlout=&tmpds3(keep=fmtname length); ';
|
||||
put ' select &fmtlist; ';
|
||||
put ' run; ';
|
||||
put ' proc sql; ';
|
||||
put ' insert into &tmpds2 select distinct fmtname,length from &tmpds3; ';
|
||||
put ' %end; ';
|
||||
put ' ';
|
||||
put ' proc sql; ';
|
||||
put ' create table &tmpds4 as ';
|
||||
put ' select a.*, b.length as maxw ';
|
||||
put ' from &colinfo a ';
|
||||
put ' left join &tmpds2 b ';
|
||||
put ' on cats(a.format)=cats(upcase(b.fmtname)) ';
|
||||
put ' order by a.varnum; ';
|
||||
put ' data _null_; ';
|
||||
put ' set &tmpds4; ';
|
||||
put ' if not missing(maxw); ';
|
||||
put ' call symputx( ';
|
||||
put ' cats(''fmtlen'',_n_), ';
|
||||
put ' /* vars need extra padding due to JSON escaping of special chars */ ';
|
||||
put ' min(32767,ceil((max(length,maxw)+3)*1.5)) ';
|
||||
put ' ,''l'' ';
|
||||
put ' ); ';
|
||||
put ' run; ';
|
||||
put ' ';
|
||||
put ' /* configure varlenchk - as we are explicitly shortening the variables */ ';
|
||||
put ' %let optval=%sysfunc(getoption(varlenchk)); ';
|
||||
put ' options varlenchk=NOWARN; ';
|
||||
put ' data _data_(compress=char); ';
|
||||
put ' /* shorten the new vars */ ';
|
||||
put ' length ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' &&name&i $&&fmtlen&i ';
|
||||
put ' %end; ';
|
||||
put ' ; ';
|
||||
put ' /* rename on entry */ ';
|
||||
put ' set &ds(rename=( ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' &&name&i=&&newname&i ';
|
||||
put ' &&name&i=&&newname&i ';
|
||||
put ' %end; ';
|
||||
put ' )); ';
|
||||
put ' &stmt_obs; ';
|
||||
put ' ';
|
||||
put ' drop ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' &&newname&i ';
|
||||
put ' %end; ';
|
||||
put ' ; ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' /* formatted values can be up to length 32767 */ ';
|
||||
put ' length &&name&i $32767; ';
|
||||
put ' %if &&typelong&i=num %then %do; ';
|
||||
put ' &&name&i=left(put(&&newname&i,&&fmt&i)); ';
|
||||
put ' &&name&i=cats(put(&&newname&i,&&fmt&i)); ';
|
||||
put ' %end; ';
|
||||
put ' %else %do; ';
|
||||
put ' &&name&i=put(&&newname&i,&&fmt&i); ';
|
||||
put ' %end; ';
|
||||
put ' drop &&newname&i; ';
|
||||
put ' %end; ';
|
||||
put ' if _error_ then call symputx(''syscc'',1012); ';
|
||||
put ' if _error_ then do; ';
|
||||
put ' call symputx(''syscc'',1012); ';
|
||||
put ' stop; ';
|
||||
put ' end; ';
|
||||
put ' run; ';
|
||||
put ' %let fmtds=&syslast; ';
|
||||
put ' options varlenchk=&optval; ';
|
||||
put ' %end; ';
|
||||
put ' ';
|
||||
put ' proc format; /* credit yabwon for special null removal */ ';
|
||||
@@ -245,8 +323,8 @@ data _null_;
|
||||
put ' attrib _all_ label=''''; ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' %if &&typelong&i=char or &fmt=Y %then %do; ';
|
||||
put ' length &&name&i $32767; ';
|
||||
put ' format &&name&i $32767.; ';
|
||||
put ' length &&name&i $&&fmtlen&i...; ';
|
||||
put ' format &&name&i $&&fmtlen&i...; ';
|
||||
put ' %end; ';
|
||||
put ' %end; ';
|
||||
put ' %if &fmt=Y %then %do; ';
|
||||
@@ -368,8 +446,8 @@ data _null_;
|
||||
put ' %quote(&user) ';
|
||||
put ' ';
|
||||
put '%mend mf_getuser; ';
|
||||
put '%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL ';
|
||||
put ' ,showmeta=N ';
|
||||
put '%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=N,missing=NULL ';
|
||||
put ' ,showmeta=N,maxobs=MAX,workobs=0 ';
|
||||
put '); ';
|
||||
put '%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug ';
|
||||
put ' sasjs_tables; ';
|
||||
@@ -436,14 +514,14 @@ data _null_;
|
||||
put ' ';
|
||||
put '%else %if &action=ARR or &action=OBJ %then %do; ';
|
||||
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref ';
|
||||
put ' ,engine=&jsonengine,missing=&missing,showmeta=&showmeta ';
|
||||
put ' ,engine=&jsonengine,missing=&missing,showmeta=&showmeta,maxobs=&maxobs ';
|
||||
put ' ) ';
|
||||
put '%end; ';
|
||||
put '%else %if &action=CLOSE %then %do; ';
|
||||
put ' /* To avoid issues with _webout on EBI we use a temporary file */ ';
|
||||
put ' filename _sjsref temp lrecl=131068; ';
|
||||
put ' %if %str(&_debug) ge 131 %then %do; ';
|
||||
put ' /* if debug mode, send back first 10 records of each work table also */ ';
|
||||
put ' %if %str(&workobs) > 0 %then %do; ';
|
||||
put ' /* if debug mode, send back first XX records of each work table also */ ';
|
||||
put ' data;run;%let tempds=%scan(&syslast,2,.); ';
|
||||
put ' ods output Members=&tempds; ';
|
||||
put ' proc datasets library=WORK memtype=data; ';
|
||||
@@ -467,7 +545,9 @@ data _null_;
|
||||
put ' put " ""&wt"" : {"; ';
|
||||
put ' put ''"nlobs":'' nlobs; ';
|
||||
put ' put '',"nvars":'' nvars; ';
|
||||
put ' %mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y,maxobs=10) ';
|
||||
put ' %mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y,maxobs=10 ';
|
||||
put ' ,maxobs=&workobs ';
|
||||
put ' ) ';
|
||||
put ' data _null_; file _sjsref mod encoding=''utf-8''; ';
|
||||
put ' put "}"; ';
|
||||
put ' %end; ';
|
||||
@@ -477,23 +557,30 @@ data _null_;
|
||||
put ' %end; ';
|
||||
put ' /* close off json */ ';
|
||||
put ' data _null_;file _sjsref mod encoding=''utf-8''; ';
|
||||
put ' _PROGRAM=quote(trim(resolve(symget(''_PROGRAM'')))); ';
|
||||
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
|
||||
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
|
||||
put ' length SYSPROCESSNAME syserrortext syswarningtext autoexec $512; ';
|
||||
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
|
||||
put ' _METAUSER=quote(trim(symget(''_METAUSER''))); ';
|
||||
put ' put ",""_METAUSER"": " _METAUSER; ';
|
||||
put ' _METAPERSON=quote(trim(symget(''_METAPERSON''))); ';
|
||||
put ' put '',"_METAPERSON": '' _METAPERSON; ';
|
||||
put ' _PROGRAM=quote(trim(resolve(symget(''_PROGRAM'')))); ';
|
||||
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
||||
put ' autoexec=quote(urlencode(trim(getoption(''autoexec'')))); ';
|
||||
put ' put '',"AUTOEXEC" : '' autoexec; ';
|
||||
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
|
||||
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
||||
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
|
||||
put ' syserrortext=cats(''"'',tranwrd(symget(''syserrortext''),''"'',''\"''),''"''); ';
|
||||
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
|
||||
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
||||
put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; ';
|
||||
put ' put ",""SYSPROCESSMODE"" : ""&SYSPROCESSMODE"" "; ';
|
||||
put ' SYSPROCESSNAME=quote(urlencode(cats(SYSPROCESSNAME))); ';
|
||||
put ' put ",""SYSPROCESSNAME"" : " SYSPROCESSNAME; ';
|
||||
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
|
||||
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
|
||||
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
||||
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
|
||||
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
||||
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
||||
put ' syswarningtext=cats(''"'',tranwrd(symget(''syswarningtext''),''"'',''\"''),''"''); ';
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
@param [in] action Either FETCH, OPEN, ARR, OBJ or CLOSE
|
||||
@param [in] ds The dataset to send back to the frontend
|
||||
@param [out] dslabel= Value to use instead of table name for sending to JSON
|
||||
@param [in] fmt=(Y) Set to N to send back unformatted values
|
||||
@param [in] fmt= (N) Setting Y converts all vars to their formatted values
|
||||
@param [out] fref= (_webout) The fileref to which to write the JSON
|
||||
@param [in] missing= (NULL) Special numeric missing values can be sent as NULL
|
||||
(eg `null`) or as STRING values (eg `".a"` or `".b"`)
|
||||
@@ -34,17 +34,25 @@
|
||||
such as the column formats and types. The metadata is contained inside an
|
||||
object with the same name as the table but prefixed with a dollar sign - ie,
|
||||
`,"$tablename":{"formats":{"col1":"$CHAR1"},"types":{"COL1":"C"}}`
|
||||
|
||||
@param [in] workobs= (0) When set to a positive integer, will create a new
|
||||
output object (WORK) which contains this number of observations from all
|
||||
tables in the WORK library.
|
||||
@param [in] maxobs= (MAX) Provide an integer to limit the number of input rows
|
||||
that should be converted to output JSON
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mp_jsonout.sas
|
||||
|
||||
<h4> Related Macros </h4>
|
||||
@li ms_webout.sas
|
||||
@li mv_webout.sas
|
||||
|
||||
@version 9.3
|
||||
@author Allan Bowe
|
||||
|
||||
**/
|
||||
%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL
|
||||
,showmeta=N
|
||||
%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=N,missing=NULL
|
||||
,showmeta=N,maxobs=MAX,workobs=0
|
||||
);
|
||||
%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug
|
||||
sasjs_tables;
|
||||
@@ -111,14 +119,14 @@
|
||||
|
||||
%else %if &action=ARR or &action=OBJ %then %do;
|
||||
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
|
||||
,engine=&jsonengine,missing=&missing,showmeta=&showmeta
|
||||
,engine=&jsonengine,missing=&missing,showmeta=&showmeta,maxobs=&maxobs
|
||||
)
|
||||
%end;
|
||||
%else %if &action=CLOSE %then %do;
|
||||
/* To avoid issues with _webout on EBI we use a temporary file */
|
||||
filename _sjsref temp lrecl=131068;
|
||||
%if %str(&_debug) ge 131 %then %do;
|
||||
/* if debug mode, send back first 10 records of each work table also */
|
||||
%if %str(&workobs) > 0 %then %do;
|
||||
/* if debug mode, send back first XX records of each work table also */
|
||||
data;run;%let tempds=%scan(&syslast,2,.);
|
||||
ods output Members=&tempds;
|
||||
proc datasets library=WORK memtype=data;
|
||||
@@ -142,7 +150,9 @@
|
||||
put " ""&wt"" : {";
|
||||
put '"nlobs":' nlobs;
|
||||
put ',"nvars":' nvars;
|
||||
%mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y,maxobs=10)
|
||||
%mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y,maxobs=10
|
||||
,maxobs=&workobs
|
||||
)
|
||||
data _null_; file _sjsref mod encoding='utf-8';
|
||||
put "}";
|
||||
%end;
|
||||
@@ -152,23 +162,30 @@
|
||||
%end;
|
||||
/* close off json */
|
||||
data _null_;file _sjsref mod encoding='utf-8';
|
||||
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
||||
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
||||
put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
|
||||
length SYSPROCESSNAME syserrortext syswarningtext autoexec $512;
|
||||
put ",""_DEBUG"" : ""&_debug"" ";
|
||||
_METAUSER=quote(trim(symget('_METAUSER')));
|
||||
put ",""_METAUSER"": " _METAUSER;
|
||||
_METAPERSON=quote(trim(symget('_METAPERSON')));
|
||||
put ',"_METAPERSON": ' _METAPERSON;
|
||||
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||
autoexec=quote(urlencode(trim(getoption('autoexec'))));
|
||||
put ',"AUTOEXEC" : ' autoexec;
|
||||
put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
|
||||
put ",""SYSCC"" : ""&syscc"" ";
|
||||
put ",""SYSENCODING"" : ""&sysencoding"" ";
|
||||
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"');
|
||||
put ',"SYSERRORTEXT" : ' syserrortext;
|
||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||
put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" ";
|
||||
put ",""SYSPROCESSMODE"" : ""&SYSPROCESSMODE"" ";
|
||||
SYSPROCESSNAME=quote(urlencode(cats(SYSPROCESSNAME)));
|
||||
put ",""SYSPROCESSNAME"" : " SYSPROCESSNAME;
|
||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||
put ",""SYSSCPL"" : ""&sysscpl"" ";
|
||||
put ",""SYSSITE"" : ""&syssite"" ";
|
||||
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
||||
sysvlong=quote(trim(symget('sysvlong')));
|
||||
put ',"SYSVLONG" : ' sysvlong;
|
||||
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"');
|
||||
|
||||
@@ -94,14 +94,14 @@ data _null_;
|
||||
file &sasjsref termstr=crlf lrecl=512;
|
||||
put "/* Created on %sysfunc(datetime(),datetime19.) by %mf_getuser() */";
|
||||
/* WEBOUT BEGIN */
|
||||
put ' ';
|
||||
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
||||
put ' ,engine=DATASTEP ';
|
||||
put ' ,missing=NULL ';
|
||||
put ' ,showmeta=N ';
|
||||
put ' ,maxobs=MAX ';
|
||||
put ')/*/STORE SOURCE*/; ';
|
||||
put '%local tempds colinfo fmtds i numcols stmt_obs; ';
|
||||
put '%local tempds colinfo fmtds i numcols numobs stmt_obs lastobs optval ';
|
||||
put ' tmpds1 tmpds2 tmpds3 tmpds4; ';
|
||||
put '%let numcols=0; ';
|
||||
put '%if &maxobs ne MAX %then %let stmt_obs=%str(if _n_>&maxobs then stop;); ';
|
||||
put ' ';
|
||||
@@ -139,7 +139,7 @@ data _null_;
|
||||
put ' by varnum; ';
|
||||
put ' run; ';
|
||||
put ' /* move meta to mac vars */ ';
|
||||
put ' data _null_; ';
|
||||
put ' data &colinfo; ';
|
||||
put ' if _n_=1 then call symputx(''numcols'',nobs,''l''); ';
|
||||
put ' set &colinfo end=last nobs=nobs; ';
|
||||
put ' name=upcase(name); ';
|
||||
@@ -168,9 +168,15 @@ data _null_;
|
||||
put ' call symputx(cats(''type'',_n_),type,''l''); ';
|
||||
put ' call symputx(cats(''typelong'',_n_),typelong,''l''); ';
|
||||
put ' call symputx(cats(''label'',_n_),coalescec(label,name),''l''); ';
|
||||
put ' /* overwritten when fmt=Y and a custom format exists in catalog */ ';
|
||||
put ' if typelong=''num'' then call symputx(cats(''fmtlen'',_n_),200,''l''); ';
|
||||
put ' else call symputx(cats(''fmtlen'',_n_),min(32767,ceil((length+3)*1.5)),''l''); ';
|
||||
put ' run; ';
|
||||
put ' ';
|
||||
put ' %let tempds=%substr(_%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' proc sql; ';
|
||||
put ' select count(*) into: lastobs from &ds; ';
|
||||
put ' %if &maxobs ne MAX %then %let lastobs=%sysfunc(min(&lastobs,&maxobs)); ';
|
||||
put ' ';
|
||||
put ' %if &engine=PROCJSON %then %do; ';
|
||||
put ' %if &missing=STRING %then %do; ';
|
||||
@@ -207,27 +213,99 @@ data _null_;
|
||||
put ' %end; ';
|
||||
put ' ';
|
||||
put ' %if &fmt=Y %then %do; ';
|
||||
put ' data _data_; ';
|
||||
put ' /** ';
|
||||
put ' * Extract format definitions ';
|
||||
put ' * First, by getting library locations from dictionary.formats ';
|
||||
put ' * Then, by exporting the width using proc format ';
|
||||
put ' * Cannot use maxw from sashelp.vformat as not always populated ';
|
||||
put ' * Cannot use fmtinfo() as not supported in all flavours ';
|
||||
put ' */ ';
|
||||
put ' %let tmpds1=%substr(fmtsum%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' %let tmpds2=%substr(cntl%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' %let tmpds3=%substr(cntl%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' %let tmpds4=%substr(col%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' proc sql noprint; ';
|
||||
put ' create table &tmpds1 as ';
|
||||
put ' select cats(libname,''.'',memname) as fmtcat, ';
|
||||
put ' fmtname ';
|
||||
put ' from dictionary.formats ';
|
||||
put ' where fmttype=''F'' and libname is not null ';
|
||||
put ' and fmtname in (select format from &colinfo where format is not null) ';
|
||||
put ' order by 1; ';
|
||||
put ' create table &tmpds2( ';
|
||||
put ' FMTNAME char(32), ';
|
||||
put ' LENGTH num ';
|
||||
put ' ); ';
|
||||
put ' %local catlist cat fmtlist i; ';
|
||||
put ' select distinct fmtcat into: catlist separated by '' '' from &tmpds1; ';
|
||||
put ' %do i=1 %to %sysfunc(countw(&catlist,%str( ))); ';
|
||||
put ' %let cat=%scan(&catlist,&i,%str( )); ';
|
||||
put ' proc sql; ';
|
||||
put ' select distinct fmtname into: fmtlist separated by '' '' ';
|
||||
put ' from &tmpds1 where fmtcat="&cat"; ';
|
||||
put ' proc format lib=&cat cntlout=&tmpds3(keep=fmtname length); ';
|
||||
put ' select &fmtlist; ';
|
||||
put ' run; ';
|
||||
put ' proc sql; ';
|
||||
put ' insert into &tmpds2 select distinct fmtname,length from &tmpds3; ';
|
||||
put ' %end; ';
|
||||
put ' ';
|
||||
put ' proc sql; ';
|
||||
put ' create table &tmpds4 as ';
|
||||
put ' select a.*, b.length as maxw ';
|
||||
put ' from &colinfo a ';
|
||||
put ' left join &tmpds2 b ';
|
||||
put ' on cats(a.format)=cats(upcase(b.fmtname)) ';
|
||||
put ' order by a.varnum; ';
|
||||
put ' data _null_; ';
|
||||
put ' set &tmpds4; ';
|
||||
put ' if not missing(maxw); ';
|
||||
put ' call symputx( ';
|
||||
put ' cats(''fmtlen'',_n_), ';
|
||||
put ' /* vars need extra padding due to JSON escaping of special chars */ ';
|
||||
put ' min(32767,ceil((max(length,maxw)+3)*1.5)) ';
|
||||
put ' ,''l'' ';
|
||||
put ' ); ';
|
||||
put ' run; ';
|
||||
put ' ';
|
||||
put ' /* configure varlenchk - as we are explicitly shortening the variables */ ';
|
||||
put ' %let optval=%sysfunc(getoption(varlenchk)); ';
|
||||
put ' options varlenchk=NOWARN; ';
|
||||
put ' data _data_(compress=char); ';
|
||||
put ' /* shorten the new vars */ ';
|
||||
put ' length ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' &&name&i $&&fmtlen&i ';
|
||||
put ' %end; ';
|
||||
put ' ; ';
|
||||
put ' /* rename on entry */ ';
|
||||
put ' set &ds(rename=( ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' &&name&i=&&newname&i ';
|
||||
put ' &&name&i=&&newname&i ';
|
||||
put ' %end; ';
|
||||
put ' )); ';
|
||||
put ' &stmt_obs; ';
|
||||
put ' ';
|
||||
put ' drop ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' &&newname&i ';
|
||||
put ' %end; ';
|
||||
put ' ; ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' /* formatted values can be up to length 32767 */ ';
|
||||
put ' length &&name&i $32767; ';
|
||||
put ' %if &&typelong&i=num %then %do; ';
|
||||
put ' &&name&i=left(put(&&newname&i,&&fmt&i)); ';
|
||||
put ' &&name&i=cats(put(&&newname&i,&&fmt&i)); ';
|
||||
put ' %end; ';
|
||||
put ' %else %do; ';
|
||||
put ' &&name&i=put(&&newname&i,&&fmt&i); ';
|
||||
put ' %end; ';
|
||||
put ' drop &&newname&i; ';
|
||||
put ' %end; ';
|
||||
put ' if _error_ then call symputx(''syscc'',1012); ';
|
||||
put ' if _error_ then do; ';
|
||||
put ' call symputx(''syscc'',1012); ';
|
||||
put ' stop; ';
|
||||
put ' end; ';
|
||||
put ' run; ';
|
||||
put ' %let fmtds=&syslast; ';
|
||||
put ' options varlenchk=&optval; ';
|
||||
put ' %end; ';
|
||||
put ' ';
|
||||
put ' proc format; /* credit yabwon for special null removal */ ';
|
||||
@@ -246,8 +324,8 @@ data _null_;
|
||||
put ' attrib _all_ label=''''; ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' %if &&typelong&i=char or &fmt=Y %then %do; ';
|
||||
put ' length &&name&i $32767; ';
|
||||
put ' format &&name&i $32767.; ';
|
||||
put ' length &&name&i $&&fmtlen&i...; ';
|
||||
put ' format &&name&i $&&fmtlen&i...; ';
|
||||
put ' %end; ';
|
||||
put ' %end; ';
|
||||
put ' %if &fmt=Y %then %do; ';
|
||||
@@ -370,8 +448,8 @@ data _null_;
|
||||
put ' ';
|
||||
put '%mend mf_getuser; ';
|
||||
put ' ';
|
||||
put '%macro ms_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL ';
|
||||
put ' ,showmeta=N ';
|
||||
put '%macro ms_webout(action,ds,dslabel=,fref=_webout,fmt=N,missing=NULL ';
|
||||
put ' ,showmeta=N,maxobs=MAX,workobs=0 ';
|
||||
put '); ';
|
||||
put '%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug ';
|
||||
put ' sasjs_tables; ';
|
||||
@@ -430,12 +508,12 @@ data _null_;
|
||||
put ' %let missing=NULL; ';
|
||||
put ' %end; ';
|
||||
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref ';
|
||||
put ' ,engine=DATASTEP,missing=&missing,showmeta=&showmeta ';
|
||||
put ' ,engine=DATASTEP,missing=&missing,showmeta=&showmeta,maxobs=&maxobs ';
|
||||
put ' ) ';
|
||||
put '%end; ';
|
||||
put '%else %if &action=CLOSE %then %do; ';
|
||||
put ' %if %str(&_debug) ge 131 %then %do; ';
|
||||
put ' /* if debug mode, send back first 10 records of each work table also */ ';
|
||||
put ' %if %str(&workobs) > 0 %then %do; ';
|
||||
put ' /* if debug mode, send back first XX records of each work table also */ ';
|
||||
put ' data;run;%let tempds=%scan(&syslast,2,.); ';
|
||||
put ' ods output Members=&tempds; ';
|
||||
put ' proc datasets library=WORK memtype=data; ';
|
||||
@@ -460,7 +538,9 @@ data _null_;
|
||||
put ' put " ""&wt"" : {"; ';
|
||||
put ' put ''"nlobs":'' nlobs; ';
|
||||
put ' put '',"nvars":'' nvars; ';
|
||||
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y,maxobs=10) ';
|
||||
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y,maxobs=10 ';
|
||||
put ' ,maxobs=&workobs ';
|
||||
put ' ) ';
|
||||
put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; ';
|
||||
put ' put "}"; ';
|
||||
put ' %end; ';
|
||||
@@ -470,11 +550,13 @@ data _null_;
|
||||
put ' %end; ';
|
||||
put ' /* close off json */ ';
|
||||
put ' data _null_;file &fref mod encoding=''utf-8'' termstr=lf lrecl=32767; ';
|
||||
put ' _PROGRAM=quote(trim(resolve(symget(''_PROGRAM'')))); ';
|
||||
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
|
||||
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
|
||||
put ' length SYSPROCESSNAME syserrortext syswarningtext autoexec $512; ';
|
||||
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
|
||||
put ' _PROGRAM=quote(trim(resolve(symget(''_PROGRAM'')))); ';
|
||||
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
||||
put ' autoexec=quote(urlencode(trim(getoption(''autoexec'')))); ';
|
||||
put ' put '',"AUTOEXEC" : '' autoexec; ';
|
||||
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
|
||||
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
||||
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
|
||||
put ' syserrortext=cats(''"'',tranwrd(symget(''syserrortext''),''"'',''\"''),''"''); ';
|
||||
@@ -484,21 +566,18 @@ data _null_;
|
||||
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
||||
put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; ';
|
||||
put ' put ",""SYSPROCESSMODE"" : ""&SYSPROCESSMODE"" "; ';
|
||||
put ' length SYSPROCESSNAME $512; ';
|
||||
put ' SYSPROCESSNAME=quote(urlencode(cats(SYSPROCESSNAME))); ';
|
||||
put ' put ",""SYSPROCESSNAME"" : " SYSPROCESSNAME; ';
|
||||
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
|
||||
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
|
||||
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
||||
put ' put ",""SYSTCPIPHOSTNAME"" : ""&SYSTCPIPHOSTNAME"" "; ';
|
||||
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
|
||||
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
||||
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
||||
put ' syswarningtext=cats(''"'',tranwrd(symget(''syswarningtext''),''"'',''\"''),''"''); ';
|
||||
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
|
||||
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
|
||||
put ' length autoexec $512; ';
|
||||
put ' autoexec=quote(urlencode(trim(getoption(''autoexec'')))); ';
|
||||
put ' put '',"AUTOEXEC" : '' autoexec; ';
|
||||
put ' length memsize $32; ';
|
||||
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
||||
put ' memsize=quote(cats(memsize)); ';
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@param [in] action Either FETCH, OPEN, ARR, OBJ or CLOSE
|
||||
@param [in] ds The dataset to send back to the frontend
|
||||
@param [out] dslabel= value to use instead of table name for sending to JSON
|
||||
@param [in] fmt= (Y) Set to N to send back unformatted values
|
||||
@param [in] fmt= (N) Setting Y converts all vars to their formatted values
|
||||
@param [out] fref= (_webout) The fileref to which to write the JSON
|
||||
@param [in] missing= (NULL) Special numeric missing values can be sent as NULL
|
||||
(eg `null`) or as STRING values (eg `".a"` or `".b"`)
|
||||
@@ -31,6 +31,11 @@
|
||||
such as the column formats and types. The metadata is contained inside an
|
||||
object with the same name as the table but prefixed with a dollar sign - ie,
|
||||
`,"$tablename":{"formats":{"col1":"$CHAR1"},"types":{"COL1":"C"}}`
|
||||
@param [in] workobs= (0) When set to a positive integer, will create a new
|
||||
output object (WORK) which contains this number of observations from all
|
||||
tables in the WORK library.
|
||||
@param [in] maxobs= (MAX) Provide an integer to limit the number of input rows
|
||||
that should be converted to output JSON
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_getuser.sas
|
||||
@@ -46,8 +51,8 @@
|
||||
|
||||
**/
|
||||
|
||||
%macro ms_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL
|
||||
,showmeta=N
|
||||
%macro ms_webout(action,ds,dslabel=,fref=_webout,fmt=N,missing=NULL
|
||||
,showmeta=N,maxobs=MAX,workobs=0
|
||||
);
|
||||
%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug
|
||||
sasjs_tables;
|
||||
@@ -106,12 +111,12 @@
|
||||
%let missing=NULL;
|
||||
%end;
|
||||
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
|
||||
,engine=DATASTEP,missing=&missing,showmeta=&showmeta
|
||||
,engine=DATASTEP,missing=&missing,showmeta=&showmeta,maxobs=&maxobs
|
||||
)
|
||||
%end;
|
||||
%else %if &action=CLOSE %then %do;
|
||||
%if %str(&_debug) ge 131 %then %do;
|
||||
/* if debug mode, send back first 10 records of each work table also */
|
||||
%if %str(&workobs) > 0 %then %do;
|
||||
/* if debug mode, send back first XX records of each work table also */
|
||||
data;run;%let tempds=%scan(&syslast,2,.);
|
||||
ods output Members=&tempds;
|
||||
proc datasets library=WORK memtype=data;
|
||||
@@ -136,7 +141,9 @@
|
||||
put " ""&wt"" : {";
|
||||
put '"nlobs":' nlobs;
|
||||
put ',"nvars":' nvars;
|
||||
%mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y,maxobs=10)
|
||||
%mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y,maxobs=10
|
||||
,maxobs=&workobs
|
||||
)
|
||||
data _null_; file &fref mod encoding='utf-8' termstr=lf;
|
||||
put "}";
|
||||
%end;
|
||||
@@ -146,11 +153,13 @@
|
||||
%end;
|
||||
/* close off json */
|
||||
data _null_;file &fref mod encoding='utf-8' termstr=lf lrecl=32767;
|
||||
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
||||
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
||||
put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
|
||||
length SYSPROCESSNAME syserrortext syswarningtext autoexec $512;
|
||||
put ",""_DEBUG"" : ""&_debug"" ";
|
||||
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||
autoexec=quote(urlencode(trim(getoption('autoexec'))));
|
||||
put ',"AUTOEXEC" : ' autoexec;
|
||||
put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
|
||||
put ",""SYSCC"" : ""&syscc"" ";
|
||||
put ",""SYSENCODING"" : ""&sysencoding"" ";
|
||||
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"');
|
||||
@@ -160,21 +169,18 @@
|
||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||
put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" ";
|
||||
put ",""SYSPROCESSMODE"" : ""&SYSPROCESSMODE"" ";
|
||||
length SYSPROCESSNAME $512;
|
||||
SYSPROCESSNAME=quote(urlencode(cats(SYSPROCESSNAME)));
|
||||
put ",""SYSPROCESSNAME"" : " SYSPROCESSNAME;
|
||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||
put ",""SYSSCPL"" : ""&sysscpl"" ";
|
||||
put ",""SYSSITE"" : ""&syssite"" ";
|
||||
put ",""SYSTCPIPHOSTNAME"" : ""&SYSTCPIPHOSTNAME"" ";
|
||||
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
||||
sysvlong=quote(trim(symget('sysvlong')));
|
||||
put ',"SYSVLONG" : ' sysvlong;
|
||||
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"');
|
||||
put ',"SYSWARNINGTEXT" : ' syswarningtext;
|
||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
|
||||
length autoexec $512;
|
||||
autoexec=quote(urlencode(trim(getoption('autoexec'))));
|
||||
put ',"AUTOEXEC" : ' autoexec;
|
||||
length memsize $32;
|
||||
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
||||
memsize=quote(cats(memsize));
|
||||
|
||||
43
tests/base/mp_cleancsv.test.sas
Normal file
43
tests/base/mp_cleancsv.test.sas
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
@file
|
||||
@brief Testing mp_cleancsv.sas macro
|
||||
@details Credit for test 1 goes to
|
||||
[Tom](https://communities.sas.com/t5/user/viewprofilepage/user-id/159) from
|
||||
SAS Communities:
|
||||
https://communities.sas.com/t5/SAS-Programming/Removing-embedded-carriage-returns/m-p/824790#M325761
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_nobs.sas
|
||||
@li mp_cleancsv.sas
|
||||
@li mp_assert.sas
|
||||
@li mp_assertscope.sas
|
||||
|
||||
**/
|
||||
|
||||
/* test 1 - cope with empty rows on CR formatted file */
|
||||
|
||||
filename crlf "%sysfunc(pathname(work))/crlf";
|
||||
filename cr "%sysfunc(pathname(work))/cr";
|
||||
data _null_;
|
||||
file cr termstr=cr ;
|
||||
put 'line 1'///'line 4'/'line 5';
|
||||
run;
|
||||
|
||||
%mp_assertscope(SNAPSHOT)
|
||||
%mp_cleancsv(in=cr,out=crlf)
|
||||
%mp_assertscope(COMPARE)
|
||||
|
||||
/* 5 rows as all converted to OD0A */
|
||||
data test1;
|
||||
infile "%sysfunc(pathname(work))/crlf" lrecl=100 termstr=crlf;
|
||||
input;
|
||||
list;
|
||||
run;
|
||||
|
||||
%put test1=%mf_nobs(test1);
|
||||
|
||||
%mp_assert(
|
||||
iftrue=(%mf_nobs(work.test1)=5),
|
||||
desc=Checking blank rows on CR formatted file,
|
||||
outds=work.test_results
|
||||
)
|
||||
@@ -236,14 +236,14 @@ data _null_;
|
||||
file &adapter;
|
||||
put "/* Created on %sysfunc(datetime(),datetime19.) by &sysuserid */";
|
||||
/* WEBOUT BEGIN */
|
||||
put ' ';
|
||||
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
||||
put ' ,engine=DATASTEP ';
|
||||
put ' ,missing=NULL ';
|
||||
put ' ,showmeta=N ';
|
||||
put ' ,maxobs=MAX ';
|
||||
put ')/*/STORE SOURCE*/; ';
|
||||
put '%local tempds colinfo fmtds i numcols stmt_obs; ';
|
||||
put '%local tempds colinfo fmtds i numcols numobs stmt_obs lastobs optval ';
|
||||
put ' tmpds1 tmpds2 tmpds3 tmpds4; ';
|
||||
put '%let numcols=0; ';
|
||||
put '%if &maxobs ne MAX %then %let stmt_obs=%str(if _n_>&maxobs then stop;); ';
|
||||
put ' ';
|
||||
@@ -281,7 +281,7 @@ data _null_;
|
||||
put ' by varnum; ';
|
||||
put ' run; ';
|
||||
put ' /* move meta to mac vars */ ';
|
||||
put ' data _null_; ';
|
||||
put ' data &colinfo; ';
|
||||
put ' if _n_=1 then call symputx(''numcols'',nobs,''l''); ';
|
||||
put ' set &colinfo end=last nobs=nobs; ';
|
||||
put ' name=upcase(name); ';
|
||||
@@ -310,9 +310,15 @@ data _null_;
|
||||
put ' call symputx(cats(''type'',_n_),type,''l''); ';
|
||||
put ' call symputx(cats(''typelong'',_n_),typelong,''l''); ';
|
||||
put ' call symputx(cats(''label'',_n_),coalescec(label,name),''l''); ';
|
||||
put ' /* overwritten when fmt=Y and a custom format exists in catalog */ ';
|
||||
put ' if typelong=''num'' then call symputx(cats(''fmtlen'',_n_),200,''l''); ';
|
||||
put ' else call symputx(cats(''fmtlen'',_n_),min(32767,ceil((length+3)*1.5)),''l''); ';
|
||||
put ' run; ';
|
||||
put ' ';
|
||||
put ' %let tempds=%substr(_%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' proc sql; ';
|
||||
put ' select count(*) into: lastobs from &ds; ';
|
||||
put ' %if &maxobs ne MAX %then %let lastobs=%sysfunc(min(&lastobs,&maxobs)); ';
|
||||
put ' ';
|
||||
put ' %if &engine=PROCJSON %then %do; ';
|
||||
put ' %if &missing=STRING %then %do; ';
|
||||
@@ -349,27 +355,99 @@ data _null_;
|
||||
put ' %end; ';
|
||||
put ' ';
|
||||
put ' %if &fmt=Y %then %do; ';
|
||||
put ' data _data_; ';
|
||||
put ' /** ';
|
||||
put ' * Extract format definitions ';
|
||||
put ' * First, by getting library locations from dictionary.formats ';
|
||||
put ' * Then, by exporting the width using proc format ';
|
||||
put ' * Cannot use maxw from sashelp.vformat as not always populated ';
|
||||
put ' * Cannot use fmtinfo() as not supported in all flavours ';
|
||||
put ' */ ';
|
||||
put ' %let tmpds1=%substr(fmtsum%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' %let tmpds2=%substr(cntl%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' %let tmpds3=%substr(cntl%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' %let tmpds4=%substr(col%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||
put ' proc sql noprint; ';
|
||||
put ' create table &tmpds1 as ';
|
||||
put ' select cats(libname,''.'',memname) as fmtcat, ';
|
||||
put ' fmtname ';
|
||||
put ' from dictionary.formats ';
|
||||
put ' where fmttype=''F'' and libname is not null ';
|
||||
put ' and fmtname in (select format from &colinfo where format is not null) ';
|
||||
put ' order by 1; ';
|
||||
put ' create table &tmpds2( ';
|
||||
put ' FMTNAME char(32), ';
|
||||
put ' LENGTH num ';
|
||||
put ' ); ';
|
||||
put ' %local catlist cat fmtlist i; ';
|
||||
put ' select distinct fmtcat into: catlist separated by '' '' from &tmpds1; ';
|
||||
put ' %do i=1 %to %sysfunc(countw(&catlist,%str( ))); ';
|
||||
put ' %let cat=%scan(&catlist,&i,%str( )); ';
|
||||
put ' proc sql; ';
|
||||
put ' select distinct fmtname into: fmtlist separated by '' '' ';
|
||||
put ' from &tmpds1 where fmtcat="&cat"; ';
|
||||
put ' proc format lib=&cat cntlout=&tmpds3(keep=fmtname length); ';
|
||||
put ' select &fmtlist; ';
|
||||
put ' run; ';
|
||||
put ' proc sql; ';
|
||||
put ' insert into &tmpds2 select distinct fmtname,length from &tmpds3; ';
|
||||
put ' %end; ';
|
||||
put ' ';
|
||||
put ' proc sql; ';
|
||||
put ' create table &tmpds4 as ';
|
||||
put ' select a.*, b.length as maxw ';
|
||||
put ' from &colinfo a ';
|
||||
put ' left join &tmpds2 b ';
|
||||
put ' on cats(a.format)=cats(upcase(b.fmtname)) ';
|
||||
put ' order by a.varnum; ';
|
||||
put ' data _null_; ';
|
||||
put ' set &tmpds4; ';
|
||||
put ' if not missing(maxw); ';
|
||||
put ' call symputx( ';
|
||||
put ' cats(''fmtlen'',_n_), ';
|
||||
put ' /* vars need extra padding due to JSON escaping of special chars */ ';
|
||||
put ' min(32767,ceil((max(length,maxw)+3)*1.5)) ';
|
||||
put ' ,''l'' ';
|
||||
put ' ); ';
|
||||
put ' run; ';
|
||||
put ' ';
|
||||
put ' /* configure varlenchk - as we are explicitly shortening the variables */ ';
|
||||
put ' %let optval=%sysfunc(getoption(varlenchk)); ';
|
||||
put ' options varlenchk=NOWARN; ';
|
||||
put ' data _data_(compress=char); ';
|
||||
put ' /* shorten the new vars */ ';
|
||||
put ' length ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' &&name&i $&&fmtlen&i ';
|
||||
put ' %end; ';
|
||||
put ' ; ';
|
||||
put ' /* rename on entry */ ';
|
||||
put ' set &ds(rename=( ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' &&name&i=&&newname&i ';
|
||||
put ' &&name&i=&&newname&i ';
|
||||
put ' %end; ';
|
||||
put ' )); ';
|
||||
put ' &stmt_obs; ';
|
||||
put ' ';
|
||||
put ' drop ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' &&newname&i ';
|
||||
put ' %end; ';
|
||||
put ' ; ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' /* formatted values can be up to length 32767 */ ';
|
||||
put ' length &&name&i $32767; ';
|
||||
put ' %if &&typelong&i=num %then %do; ';
|
||||
put ' &&name&i=left(put(&&newname&i,&&fmt&i)); ';
|
||||
put ' &&name&i=cats(put(&&newname&i,&&fmt&i)); ';
|
||||
put ' %end; ';
|
||||
put ' %else %do; ';
|
||||
put ' &&name&i=put(&&newname&i,&&fmt&i); ';
|
||||
put ' %end; ';
|
||||
put ' drop &&newname&i; ';
|
||||
put ' %end; ';
|
||||
put ' if _error_ then call symputx(''syscc'',1012); ';
|
||||
put ' if _error_ then do; ';
|
||||
put ' call symputx(''syscc'',1012); ';
|
||||
put ' stop; ';
|
||||
put ' end; ';
|
||||
put ' run; ';
|
||||
put ' %let fmtds=&syslast; ';
|
||||
put ' options varlenchk=&optval; ';
|
||||
put ' %end; ';
|
||||
put ' ';
|
||||
put ' proc format; /* credit yabwon for special null removal */ ';
|
||||
@@ -388,8 +466,8 @@ data _null_;
|
||||
put ' attrib _all_ label=''''; ';
|
||||
put ' %do i=1 %to &numcols; ';
|
||||
put ' %if &&typelong&i=char or &fmt=Y %then %do; ';
|
||||
put ' length &&name&i $32767; ';
|
||||
put ' format &&name&i $32767.; ';
|
||||
put ' length &&name&i $&&fmtlen&i...; ';
|
||||
put ' format &&name&i $&&fmtlen&i...; ';
|
||||
put ' %end; ';
|
||||
put ' %end; ';
|
||||
put ' %if &fmt=Y %then %do; ';
|
||||
@@ -511,8 +589,8 @@ data _null_;
|
||||
put ' %quote(&user) ';
|
||||
put ' ';
|
||||
put '%mend mf_getuser; ';
|
||||
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y,missing=NULL ';
|
||||
put ' ,showmeta=N ';
|
||||
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=N,stream=Y,missing=NULL ';
|
||||
put ' ,showmeta=N,maxobs=MAX,workobs=0 ';
|
||||
put '); ';
|
||||
put '%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name ';
|
||||
put ' sasjs_tables SYS_JES_JOB_URI; ';
|
||||
@@ -614,13 +692,13 @@ data _null_;
|
||||
put ' run; ';
|
||||
put '%end; ';
|
||||
put '%else %if &action=ARR or &action=OBJ %then %do; ';
|
||||
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt ';
|
||||
put ' ,jref=&fref,engine=DATASTEP,missing=&missing,showmeta=&showmeta ';
|
||||
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref ';
|
||||
put ' ,engine=DATASTEP,missing=&missing,showmeta=&showmeta,maxobs=&maxobs ';
|
||||
put ' ) ';
|
||||
put '%end; ';
|
||||
put '%else %if &action=CLOSE %then %do; ';
|
||||
put ' %if %str(&_debug) ge 131 %then %do; ';
|
||||
put ' /* send back first 10 records of each work table for debugging */ ';
|
||||
put ' %if %str(&workobs) > 0 %then %do; ';
|
||||
put ' /* send back first XX records of each work table for debugging */ ';
|
||||
put ' data;run;%let tempds=%scan(&syslast,2,.); ';
|
||||
put ' ods output Members=&tempds; ';
|
||||
put ' proc datasets library=WORK memtype=data; ';
|
||||
@@ -643,7 +721,9 @@ data _null_;
|
||||
put ' put " ""&wt"" : {"; ';
|
||||
put ' put ''"nlobs":'' nlobs; ';
|
||||
put ' put '',"nvars":'' nvars; ';
|
||||
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y,maxobs=10) ';
|
||||
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y ';
|
||||
put ' ,maxobs=&workobs ';
|
||||
put ' ) ';
|
||||
put ' data _null_; file &fref mod;put "}"; ';
|
||||
put ' %end; ';
|
||||
put ' data _null_; file &fref mod;put "}";run; ';
|
||||
@@ -651,20 +731,28 @@ data _null_;
|
||||
put ' ';
|
||||
put ' /* close off json */ ';
|
||||
put ' data _null_;file &fref mod; ';
|
||||
put ' length SYSPROCESSNAME syserrortext syswarningtext autoexec $512; ';
|
||||
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
|
||||
put ' _PROGRAM=quote(trim(resolve(symget(''_PROGRAM'')))); ';
|
||||
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
|
||||
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
||||
put ' autoexec=quote(urlencode(trim(getoption(''autoexec'')))); ';
|
||||
put ' put '',"AUTOEXEC" : '' autoexec; ';
|
||||
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
|
||||
put ' SYS_JES_JOB_URI=quote(trim(resolve(symget(''SYS_JES_JOB_URI'')))); ';
|
||||
put ' put '',"SYS_JES_JOB_URI" : '' SYS_JES_JOB_URI ; ';
|
||||
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
|
||||
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
|
||||
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
||||
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
||||
put ' syserrortext=cats(''"'',tranwrd(symget(''syserrortext''),''"'',''\"''),''"''); ';
|
||||
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
|
||||
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
||||
put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; ';
|
||||
put ' put ",""SYSPROCESSMODE"" : ""&SYSPROCESSMODE"" "; ';
|
||||
put ' SYSPROCESSNAME=quote(urlencode(cats(SYSPROCESSNAME))); ';
|
||||
put ' put ",""SYSPROCESSNAME"" : " SYSPROCESSNAME; ';
|
||||
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
|
||||
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
|
||||
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
||||
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
|
||||
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
||||
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
||||
put ' syswarningtext=cats(''"'',tranwrd(symget(''syswarningtext''),''"'',''\"''),''"''); ';
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
@param [in] _webout= fileref for returning the json
|
||||
@param [out] fref=(_mvwtemp) Temp fileref to which to write the output
|
||||
@param [out] dslabel= value to use instead of table name for sending to JSON
|
||||
@param [in] fmt=(Y) change to N to strip formats from output
|
||||
@param [in] fmt= (N) Setting Y converts all vars to their formatted values
|
||||
@param [in] stream=(Y) Change to N if not streaming to _webout
|
||||
@param [in] missing= (NULL) Special numeric missing values can be sent as NULL
|
||||
(eg `null`) or as STRING values (eg `".a"` or `".b"`)
|
||||
@@ -33,17 +33,26 @@
|
||||
such as the column formats and types. The metadata is contained inside an
|
||||
object with the same name as the table but prefixed with a dollar sign - ie,
|
||||
`,"$tablename":{"formats":{"col1":"$CHAR1"},"types":{"COL1":"C"}}`
|
||||
@param [in] maxobs= (MAX) Provide an integer to limit the number of input rows
|
||||
that should be converted to output JSON
|
||||
@param [in] workobs= (0) When set to a positive integer, will create a new
|
||||
output object (WORK) which contains this number of observations from all
|
||||
tables in the WORK library.
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mp_jsonout.sas
|
||||
@li mf_getuser.sas
|
||||
|
||||
<h4> Related Macros </h4>
|
||||
@li ms_webout.sas
|
||||
@li mm_webout.sas
|
||||
|
||||
@version Viya 3.3
|
||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
||||
|
||||
**/
|
||||
%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y,missing=NULL
|
||||
,showmeta=N
|
||||
%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=N,stream=Y,missing=NULL
|
||||
,showmeta=N,maxobs=MAX,workobs=0
|
||||
);
|
||||
%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name
|
||||
sasjs_tables SYS_JES_JOB_URI;
|
||||
@@ -145,13 +154,13 @@
|
||||
run;
|
||||
%end;
|
||||
%else %if &action=ARR or &action=OBJ %then %do;
|
||||
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt
|
||||
,jref=&fref,engine=DATASTEP,missing=&missing,showmeta=&showmeta
|
||||
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
|
||||
,engine=DATASTEP,missing=&missing,showmeta=&showmeta,maxobs=&maxobs
|
||||
)
|
||||
%end;
|
||||
%else %if &action=CLOSE %then %do;
|
||||
%if %str(&_debug) ge 131 %then %do;
|
||||
/* send back first 10 records of each work table for debugging */
|
||||
%if %str(&workobs) > 0 %then %do;
|
||||
/* send back first XX records of each work table for debugging */
|
||||
data;run;%let tempds=%scan(&syslast,2,.);
|
||||
ods output Members=&tempds;
|
||||
proc datasets library=WORK memtype=data;
|
||||
@@ -174,7 +183,9 @@
|
||||
put " ""&wt"" : {";
|
||||
put '"nlobs":' nlobs;
|
||||
put ',"nvars":' nvars;
|
||||
%mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y,maxobs=10)
|
||||
%mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y
|
||||
,maxobs=&workobs
|
||||
)
|
||||
data _null_; file &fref mod;put "}";
|
||||
%end;
|
||||
data _null_; file &fref mod;put "}";run;
|
||||
@@ -182,20 +193,28 @@
|
||||
|
||||
/* close off json */
|
||||
data _null_;file &fref mod;
|
||||
length SYSPROCESSNAME syserrortext syswarningtext autoexec $512;
|
||||
put ",""_DEBUG"" : ""&_debug"" ";
|
||||
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
||||
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||
autoexec=quote(urlencode(trim(getoption('autoexec'))));
|
||||
put ',"AUTOEXEC" : ' autoexec;
|
||||
put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
|
||||
SYS_JES_JOB_URI=quote(trim(resolve(symget('SYS_JES_JOB_URI'))));
|
||||
put ',"SYS_JES_JOB_URI" : ' SYS_JES_JOB_URI ;
|
||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||
put ",""_DEBUG"" : ""&_debug"" ";
|
||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||
put ",""SYSCC"" : ""&syscc"" ";
|
||||
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"');
|
||||
put ',"SYSERRORTEXT" : ' syserrortext;
|
||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||
put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" ";
|
||||
put ",""SYSPROCESSMODE"" : ""&SYSPROCESSMODE"" ";
|
||||
SYSPROCESSNAME=quote(urlencode(cats(SYSPROCESSNAME)));
|
||||
put ",""SYSPROCESSNAME"" : " SYSPROCESSNAME;
|
||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||
put ",""SYSSCPL"" : ""&sysscpl"" ";
|
||||
put ",""SYSSITE"" : ""&syssite"" ";
|
||||
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
||||
sysvlong=quote(trim(symget('sysvlong')));
|
||||
put ',"SYSVLONG" : ' sysvlong;
|
||||
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"');
|
||||
|
||||
Reference in New Issue
Block a user