1
0
mirror of https://github.com/sasjs/core.git synced 2025-12-25 04:01:20 +00:00

Compare commits

...

13 Commits

Author SHA1 Message Date
Allan Bowe
76a39cad20 Merge pull request #138 from sasjs/webout_mac
fix: adding missing param to mx_createwebservice macros
2021-12-30 16:29:50 +02:00
munja
ebd567af48 fix: adding missing param to mx_createwebservice macros 2021-12-30 09:53:08 +00:00
Allan Bowe
a9c418e3f2 Merge pull request #137 from sasjs/specials
feat: updating mp_jsonout() to support special missing numeric values.
2021-12-30 11:43:00 +02:00
munja
e143acd67d chore: automated commit 2021-12-30 00:30:14 +00:00
munja
84eb2f1845 chore: automated commit 2021-12-30 00:29:48 +00:00
munja
b075e5d5d5 feat: updating mp_jsonout() to support special missing numeric values. Closes #136 2021-12-30 00:21:02 +00:00
Allan Bowe
a08f6aeea2 Merge pull request #135 from sasjs/abortfix
fix: removing 'Log Extract' from abort MSG in mp_abort when not capturing the log
2021-12-29 14:54:01 +02:00
munja
469bd574ac fix: removing 'Log Extract' from abort MSG in mp_abort when not capturing the log 2021-12-29 12:35:25 +00:00
Allan Bowe
c41918c0a8 Merge pull request #134 from sasjs/fmtfix
fix: preventing error when mp_applyformats has no formats to apply
2021-12-29 14:19:59 +02:00
munja
0361ca574d fix: preventing error when mp_applyformats has no formats to apply 2021-12-29 12:19:34 +00:00
Allan Bowe
c75c169b80 Merge pull request #133 from sasjs/fmtname
fix: adding fmtname to mp_getcols() macro
2021-12-28 15:39:07 +02:00
munja
eac47bd5db fix: adding fmtname to mp_getcols() macro 2021-12-28 13:25:53 +00:00
munja
d302ef266d chore: doc page formatting & content 2021-12-27 11:54:46 +00:00
17 changed files with 407 additions and 210 deletions

View File

@@ -188,6 +188,13 @@ When contributing to this library, it is therefore important to ensure that all
- All macros should be compatible with SAS versions from support level B and above (so currently 9.2 and later). If an earlier version is not supported, then the macro should say as such in the header documentation, and exit gracefully (eg `%if %sysevalf(&sysver<9.3) %then %return`).
## Breaking Changes
We are currently on major release v3. The following changes are planned when the next major (breaking) release becomes necessary:
* Remove `dbg` parameter from mp_jsonout.sas (implement mdebug instead)
* Remove `END_DTTM` and `START_DTTM` from mx_webout JSON
## Star Gazing
If you find this library useful, please leave a [star](https://github.com/sasjs/core/stargazers) and help us grow our star graph!

206
all.sas
View File

@@ -2135,8 +2135,8 @@ Usage:
%if %symexist(SYSPRINTTOLOG) %then %let logloc=&SYSPRINTTOLOG;
%else %let logloc=%qsysfunc(getoption(LOG));
proc printto log=log;run;
%let logline=0;
%if %length(&logloc)>0 %then %do;
%let logline=0;
data _null_;
infile &logloc lrecl=5000;
input; putlog _infile_;
@@ -2185,7 +2185,10 @@ Usage:
file _webout mod lrecl=32000 encoding='utf-8';
length msg $32767 ;
sasdatetime=datetime();
msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
msg=symget('msg');
%if &logline>0 %then %do;
msg=cats(msg,'\n\nLog Extract:\n',symget('logmsg'));
%end;
/* escape the quotes */
msg=tranwrd(msg,'"','\"');
/* ditch the CRLFs as chrome complains */
@@ -2478,16 +2481,16 @@ run;
proc sql noprint;
select distinct lib into: liblist separated by ' ' from &inds;
%put &=liblist;
%do i=1 %to %sysfunc(countw(&liblist));
%if %length(&liblist)>0 %then %do i=1 %to %sysfunc(countw(&liblist));
%let lib=%scan(&liblist,1);
%let engine=%mf_getengine(&lib);
%if &engine ne V9 and &engine ne BASE %then %do;
%let msg=&lib has &engine engine - formats cannot be applied;
proc sql;
insert into &outds set lib="&lib",ds="_all_",var="_all", msg="&msg" ;
%if &errds=0 %then %put %str(ERR)OR: &msg;
%end;
%end;
quit;
%if %mf_nobs(&outds)>0 %then %return;
@@ -5539,11 +5542,11 @@ filename &fref1 clear;
@param ds The dataset from which to obtain column metadata
@param outds= (work.cols) The output dataset to create. Sample data:
|NAME $|LENGTH 8|VARNUM 8|LABEL $|FORMAT $49|TYPE $1 |DDTYPE $|
|---|---|---|---|---|---|---|
|AIR|8|2|international airline travel (thousands)|8.|N|NUMERIC|
|DATE|8|1|DATE|MONYY.|N|DATE|
|REGION|3|3|REGION|$3.|C|CHARACTER|
|NAME:$32.|LENGTH:best.|VARNUM:best.|LABEL:$256.|FMTNAME:$32.|FORMAT:$49.|TYPE:$1.|DDTYPE:$9.|
|---|---|---|---|---|---|---|---|
|`AIR `|`8 `|`2 `|`international airline travel (thousands) `|` `|`8. `|`N `|`NUMERIC `|
|`DATE `|`8 `|`1 `|`DATE `|`MONYY `|`MONYY. `|`N `|`DATE `|
|`REGION `|`3 `|`3 `|`REGION `|` `|`$3. `|`C `|`CHARACTER `|
<h4> Related Macros </h4>
@li mf_getvarlist.sas
@@ -5555,26 +5558,27 @@ filename &fref1 clear;
**/
%macro mp_getcols(ds, outds=work.cols);
%local dropds;
proc contents noprint data=&ds
out=_data_ (keep=name type length label varnum format:);
run;
data &outds(keep=name type length varnum format label ddtype);
set &syslast(rename=(format=format2 type=type2));
%let dropds=&syslast;
data &outds(keep=name type length varnum format label ddtype fmtname);
set &dropds(rename=(format=fmtname type=type2));
name=upcase(name);
if type2=2 then do;
length format $49.;
if format2='' then format=cats('$',length,'.');
else if formatl=0 then format=cats(format2,'.');
else format=cats(format2,formatl,'.');
if fmtname='' then format=cats('$',length,'.');
else if formatl=0 then format=cats(fmtname,'.');
else format=cats(fmtname,formatl,'.');
type='C';
ddtype='CHARACTER';
end;
else do;
if format2='' then format=cats(length,'.');
else if formatl=0 then format=cats(format2,'.');
else if formatd=0 then format=cats(format2,formatl,'.');
else format=cats(format2,formatl,'.',formatd);
if fmtname='' then format=cats(length,'.');
else if formatl=0 then format=cats(fmtname,'.');
else if formatd=0 then format=cats(fmtname,formatl,'.');
else format=cats(fmtname,formatl,'.',formatd);
type='N';
if format=:'DATETIME' or format=:'E8601DT' then ddtype='DATETIME';
else if format=:'DATE' or format=:'DDMMYY' or format=:'MMDDYY'
@@ -5586,7 +5590,8 @@ data &outds(keep=name type length varnum format label ddtype);
end;
if label='' then label=name;
run;
proc sql;
drop table &dropds;
%mend mp_getcols;/**
@file mp_getconstraints.sas
@brief Get constraint details at column level
@@ -7535,22 +7540,20 @@ filename &tempref clear;
[sasjs adapter](https://github.com/sasjs/adapter).
For more information see https://sasjs.io
@param action Valid values:
@param [in] action Valid values:
@li OPEN - opens the JSON
@li OBJ - sends a table with each row as an object
@li ARR - sends a table with each row in an array
@li CLOSE - closes the JSON
@param ds the dataset to send. Must be a work table.
@param jref= the fileref to which to send the JSON
@param dslabel= the name to give the table in the exported JSON
@param fmt= Whether to keep or strip formats from the table
@param engine= Which engine to use to send the JSON, valid options are:
@param [in] ds The dataset to send. Must be a work table.
@param [out] jref= (_webout) The fileref to which to send the JSON
@param [out] dslabel= The name to give the table in the exported JSON
@param [in] fmt= (Y) Whether to keep (Y) or strip (N) formats from the table
@param [in] engine= (DATASTEP) Which engine to use to send the JSON. Options:
@li PROCJSON (default)
@li DATASTEP (more reliable when data has non standard characters)
@param dbg= DEPRECATED - was used to conditionally add PRETTY to
proc json but this can cause line truncation in large files.
@param [in] missing= (NULL) Special numeric missing values can be sent as NULL
(eg `null`) or as STRING values (eg `".a"` or `".b"`)
<h4> Related Macros <h4>
@li mp_ds2fmtds.sas
@@ -7561,9 +7564,11 @@ filename &tempref clear;
**/
%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP,dbg=0
%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP
,dbg=0 /* DEPRECATED */
,missing=NULL
)/*/STORE SOURCE*/;
%put output location=&jref;
%put &sysmacroname: output location=&jref;
%if &action=OPEN %then %do;
options nobomfile;
data _null_;file &jref encoding='utf-8' ;
@@ -7576,10 +7581,16 @@ filename &tempref clear;
put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":";
%if &engine=PROCJSON %then %do;
%if &missing=STRING %then %do;
%put &sysmacroname: Special Missings are not supported in proc json.;
%put &sysmacroname: Switching to DATASTEP engine;
%goto datastep;
%end;
data;run;%let tempds=&syslast;
proc sql;drop table &tempds;
data &tempds /view=&tempds;set &ds;
%if &fmt=N %then format _numeric_ best32.;;
/* PRETTY is necessary to avoid line truncation in large files */
proc json out=&jref pretty
%if &action=ARR %then nokeys ;
;export &tempds / nosastags fmtnumeric;
@@ -7587,6 +7598,7 @@ filename &tempref clear;
proc sql;drop view &tempds;
%end;
%else %if &engine=DATASTEP %then %do;
%datastep:
%local cols i tempds;
%let cols=0;
%if %sysfunc(exist(&ds)) ne 1 & %sysfunc(exist(&ds,VIEW)) ne 1 %then %do;
@@ -7667,7 +7679,15 @@ filename &tempref clear;
run;
proc format; /* credit yabwon for special null removal */
value bart ._ - .z = null
value bart
%if &missing=NULL %then %do;
._ - .z = null
%end;
%else %do;
._ = [quote()]
. = null
.a - .z = [quote()]
%end;
other = [best.];
data;run; %let tempds=&syslast; /* temp table for spesh char management */
@@ -12651,9 +12671,11 @@ data _null_;
put "/* Created on %sysfunc(datetime(),datetime19.) by %mf_getuser() */";
/* WEBOUT BEGIN */
put ' ';
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP,dbg=0 ';
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP ';
put ' ,dbg=0 /* DEPRECATED */ ';
put ' ,missing=NULL ';
put ')/*/STORE SOURCE*/; ';
put '%put output location=&jref; ';
put '%put &sysmacroname: output location=&jref; ';
put '%if &action=OPEN %then %do; ';
put ' options nobomfile; ';
put ' data _null_;file &jref encoding=''utf-8'' ; ';
@@ -12666,10 +12688,16 @@ data _null_;
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
put ' ';
put ' %if &engine=PROCJSON %then %do; ';
put ' %if &missing=STRING %then %do; ';
put ' %put &sysmacroname: Special Missings are not supported in proc json.; ';
put ' %put &sysmacroname: Switching to DATASTEP engine; ';
put ' %goto datastep; ';
put ' %end; ';
put ' data;run;%let tempds=&syslast; ';
put ' proc sql;drop table &tempds; ';
put ' data &tempds /view=&tempds;set &ds; ';
put ' %if &fmt=N %then format _numeric_ best32.;; ';
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
put ' proc json out=&jref pretty ';
put ' %if &action=ARR %then nokeys ; ';
put ' ;export &tempds / nosastags fmtnumeric; ';
@@ -12677,6 +12705,7 @@ data _null_;
put ' proc sql;drop view &tempds; ';
put ' %end; ';
put ' %else %if &engine=DATASTEP %then %do; ';
put ' %datastep: ';
put ' %local cols i tempds; ';
put ' %let cols=0; ';
put ' %if %sysfunc(exist(&ds)) ne 1 & %sysfunc(exist(&ds,VIEW)) ne 1 %then %do; ';
@@ -12757,7 +12786,15 @@ data _null_;
put ' run; ';
put ' ';
put ' proc format; /* credit yabwon for special null removal */ ';
put ' value bart ._ - .z = null ';
put ' value bart ';
put ' %if &missing=NULL %then %do; ';
put ' ._ - .z = null ';
put ' %end; ';
put ' %else %do; ';
put ' ._ = [quote()] ';
put ' . = null ';
put ' .a - .z = [quote()] ';
put ' %end; ';
put ' other = [best.]; ';
put ' ';
put ' data;run; %let tempds=&syslast; /* temp table for spesh char management */ ';
@@ -12825,7 +12862,7 @@ data _null_;
put ' run; ';
put '%end; ';
put '%mend mp_jsonout; ';
put '%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y); ';
put '%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL); ';
put '%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug ';
put ' sasjs_tables; ';
put '%local i tempds jsonengine; ';
@@ -12890,7 +12927,7 @@ 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,dbg=%str(&_debug) ';
put ' ,engine=&jsonengine,missing=&missing ';
put ' ) ';
put '%end; ';
put '%else %if &action=CLOSE %then %do; ';
@@ -12980,8 +13017,8 @@ data _null_;
put ' ';
put '%mend mf_getuser; ';
/* WEBOUT END */
put '%macro webout(action,ds,dslabel=,fmt=);';
put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt)';
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL);';
put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing)';
put '%mend;';
run;
@@ -16310,17 +16347,19 @@ run;
%mm_webout(CLOSE)
@param action Either FETCH, OPEN, ARR, OBJ or CLOSE
@param ds The dataset to send back to the frontend
@param dslabel= value to use instead of the real name for sending to JSON
@param fmt=(Y) Set to N to send back unformatted values
@param fref=(_webout) The fileref to which to write the JSON
@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 [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"`)
@version 9.3
@author Allan Bowe
**/
%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y);
%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL);
%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug
sasjs_tables;
%local i tempds jsonengine;
@@ -16385,7 +16424,7 @@ run;
%else %if &action=ARR or &action=OBJ %then %do;
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
,engine=&jsonengine,dbg=%str(&_debug)
,engine=&jsonengine,missing=&missing
)
%end;
%else %if &action=CLOSE %then %do;
@@ -16609,11 +16648,13 @@ run;
%ms_webout(CLOSE)
@param action Either FETCH, OPEN, ARR, OBJ or CLOSE
@param ds The dataset to send back to the frontend
@param dslabel= value to use instead of the real name for sending to JSON
@param fmt=(Y) Set to N to send back unformatted values
@param fref=(_webout) The fileref to which to write the JSON
@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 [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"`)
<h4> SAS Macros </h4>
@li mp_jsonout.sas
@@ -16628,7 +16669,7 @@ run;
**/
%macro ms_webout(action,ds,dslabel=,fref=_webout,fmt=Y);
%macro ms_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL);
%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug
sasjs_tables;
@@ -16680,7 +16721,7 @@ run;
%else %if &action=ARR or &action=OBJ %then %do;
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
,engine=DATASTEP,dbg=%str(&_debug)
,engine=DATASTEP,missing=&missing
)
%end;
%else %if &action=CLOSE %then %do;
@@ -17552,9 +17593,9 @@ run;
that location
@param [in] adapter= the macro uses the sasjs adapter by default. To use
another adapter, add a (different) fileref here.
@param [in] contextname= Choose a specific context on which to run the Job. Leave
blank to use the default context. From Viya 3.5 it is possible to configure
a shared context - see
@param [in] contextname= Choose a specific context on which to run the Job.
Leave blank to use the default context. From Viya 3.5 it is possible to
configure a shared context - see
https://go.documentation.sas.com/?docsetId=calcontexts&docsetTarget=n1hjn8eobk5pyhn1wg3ja0drdl6h.htm&docsetVersion=3.5&locale=en
@param [in] mdebug=(0) set to 1 to enable DEBUG messages
@@ -17735,9 +17776,11 @@ data _null_;
put "/* Created on %sysfunc(datetime(),datetime19.) by &sysuserid */";
/* WEBOUT BEGIN */
put ' ';
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP,dbg=0 ';
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP ';
put ' ,dbg=0 /* DEPRECATED */ ';
put ' ,missing=NULL ';
put ')/*/STORE SOURCE*/; ';
put '%put output location=&jref; ';
put '%put &sysmacroname: output location=&jref; ';
put '%if &action=OPEN %then %do; ';
put ' options nobomfile; ';
put ' data _null_;file &jref encoding=''utf-8'' ; ';
@@ -17750,10 +17793,16 @@ data _null_;
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
put ' ';
put ' %if &engine=PROCJSON %then %do; ';
put ' %if &missing=STRING %then %do; ';
put ' %put &sysmacroname: Special Missings are not supported in proc json.; ';
put ' %put &sysmacroname: Switching to DATASTEP engine; ';
put ' %goto datastep; ';
put ' %end; ';
put ' data;run;%let tempds=&syslast; ';
put ' proc sql;drop table &tempds; ';
put ' data &tempds /view=&tempds;set &ds; ';
put ' %if &fmt=N %then format _numeric_ best32.;; ';
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
put ' proc json out=&jref pretty ';
put ' %if &action=ARR %then nokeys ; ';
put ' ;export &tempds / nosastags fmtnumeric; ';
@@ -17761,6 +17810,7 @@ data _null_;
put ' proc sql;drop view &tempds; ';
put ' %end; ';
put ' %else %if &engine=DATASTEP %then %do; ';
put ' %datastep: ';
put ' %local cols i tempds; ';
put ' %let cols=0; ';
put ' %if %sysfunc(exist(&ds)) ne 1 & %sysfunc(exist(&ds,VIEW)) ne 1 %then %do; ';
@@ -17841,7 +17891,15 @@ data _null_;
put ' run; ';
put ' ';
put ' proc format; /* credit yabwon for special null removal */ ';
put ' value bart ._ - .z = null ';
put ' value bart ';
put ' %if &missing=NULL %then %do; ';
put ' ._ - .z = null ';
put ' %end; ';
put ' %else %do; ';
put ' ._ = [quote()] ';
put ' . = null ';
put ' .a - .z = [quote()] ';
put ' %end; ';
put ' other = [best.]; ';
put ' ';
put ' data;run; %let tempds=&syslast; /* temp table for spesh char management */ ';
@@ -17909,7 +17967,7 @@ data _null_;
put ' run; ';
put '%end; ';
put '%mend mp_jsonout; ';
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y); ';
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y,missing=NULL); ';
put '%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name ';
put ' sasjs_tables SYS_JES_JOB_URI; ';
put '%if %index("&_debug",log) %then %let _debug=131; ';
@@ -18036,7 +18094,7 @@ data _null_;
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,dbg=%str(&_debug) ';
put ' ,jref=&fref,engine=DATASTEP,missing=&missing ';
put ' ) ';
put '%end; ';
put '%else %if &action=CLOSE %then %do; ';
@@ -18127,8 +18185,8 @@ data _null_;
put '%global __program _program;';
put '%let _program=%sysfunc(coalescec(&__program,&_program));';
put ' ';
put '%macro webout(action,ds,dslabel=,fmt=);';
put ' %mv_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt)';
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL);';
put ' %mv_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing)';
put '%mend;';
run;
@@ -21741,13 +21799,15 @@ filename &fref1 clear;
%mv_webout(CLOSE)
@param action Either OPEN, ARR, OBJ or CLOSE
@param ds The dataset to send back to the frontend
@param _webout= fileref for returning the json
@param fref=(_mvwtemp) Temp fileref to which to write the output
@param dslabel= value to use instead of the real name for sending to JSON
@param fmt=(Y) change to N to strip formats from output
@param stream=(Y) Change to N if not streaming to _webout
@param [in] action Either OPEN, ARR, OBJ or CLOSE
@param [in] ds The dataset to send back to the frontend
@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] 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"`)
<h4> SAS Macros </h4>
@li mp_jsonout.sas
@@ -21757,7 +21817,7 @@ filename &fref1 clear;
@author Allan Bowe, source: https://github.com/sasjs/core
**/
%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y);
%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y,missing=NULL);
%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name
sasjs_tables SYS_JES_JOB_URI;
%if %index("&_debug",log) %then %let _debug=131;
@@ -21884,7 +21944,7 @@ filename &fref1 clear;
%end;
%else %if &action=ARR or &action=OBJ %then %do;
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt
,jref=&fref,engine=DATASTEP,dbg=%str(&_debug)
,jref=&fref,engine=DATASTEP,missing=&missing
)
%end;
%else %if &action=CLOSE %then %do;

View File

@@ -110,8 +110,8 @@
%if %symexist(SYSPRINTTOLOG) %then %let logloc=&SYSPRINTTOLOG;
%else %let logloc=%qsysfunc(getoption(LOG));
proc printto log=log;run;
%let logline=0;
%if %length(&logloc)>0 %then %do;
%let logline=0;
data _null_;
infile &logloc lrecl=5000;
input; putlog _infile_;
@@ -160,7 +160,10 @@
file _webout mod lrecl=32000 encoding='utf-8';
length msg $32767 ;
sasdatetime=datetime();
msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
msg=symget('msg');
%if &logline>0 %then %do;
msg=cats(msg,'\n\nLog Extract:\n',symget('logmsg'));
%end;
/* escape the quotes */
msg=tranwrd(msg,'"','\"');
/* ditch the CRLFs as chrome complains */

View File

@@ -142,16 +142,16 @@ run;
proc sql noprint;
select distinct lib into: liblist separated by ' ' from &inds;
%put &=liblist;
%do i=1 %to %sysfunc(countw(&liblist));
%if %length(&liblist)>0 %then %do i=1 %to %sysfunc(countw(&liblist));
%let lib=%scan(&liblist,1);
%let engine=%mf_getengine(&lib);
%if &engine ne V9 and &engine ne BASE %then %do;
%let msg=&lib has &engine engine - formats cannot be applied;
proc sql;
insert into &outds set lib="&lib",ds="_all_",var="_all", msg="&msg" ;
%if &errds=0 %then %put %str(ERR)OR: &msg;
%end;
%end;
quit;
%if %mf_nobs(&outds)>0 %then %return;

View File

@@ -14,11 +14,11 @@
@param ds The dataset from which to obtain column metadata
@param outds= (work.cols) The output dataset to create. Sample data:
|NAME $|LENGTH 8|VARNUM 8|LABEL $|FORMAT $49|TYPE $1 |DDTYPE $|
|---|---|---|---|---|---|---|
|AIR|8|2|international airline travel (thousands)|8.|N|NUMERIC|
|DATE|8|1|DATE|MONYY.|N|DATE|
|REGION|3|3|REGION|$3.|C|CHARACTER|
|NAME:$32.|LENGTH:best.|VARNUM:best.|LABEL:$256.|FMTNAME:$32.|FORMAT:$49.|TYPE:$1.|DDTYPE:$9.|
|---|---|---|---|---|---|---|---|
|`AIR `|`8 `|`2 `|`international airline travel (thousands) `|` `|`8. `|`N `|`NUMERIC `|
|`DATE `|`8 `|`1 `|`DATE `|`MONYY `|`MONYY. `|`N `|`DATE `|
|`REGION `|`3 `|`3 `|`REGION `|` `|`$3. `|`C `|`CHARACTER `|
<h4> Related Macros </h4>
@li mf_getvarlist.sas
@@ -30,26 +30,27 @@
**/
%macro mp_getcols(ds, outds=work.cols);
%local dropds;
proc contents noprint data=&ds
out=_data_ (keep=name type length label varnum format:);
run;
data &outds(keep=name type length varnum format label ddtype);
set &syslast(rename=(format=format2 type=type2));
%let dropds=&syslast;
data &outds(keep=name type length varnum format label ddtype fmtname);
set &dropds(rename=(format=fmtname type=type2));
name=upcase(name);
if type2=2 then do;
length format $49.;
if format2='' then format=cats('$',length,'.');
else if formatl=0 then format=cats(format2,'.');
else format=cats(format2,formatl,'.');
if fmtname='' then format=cats('$',length,'.');
else if formatl=0 then format=cats(fmtname,'.');
else format=cats(fmtname,formatl,'.');
type='C';
ddtype='CHARACTER';
end;
else do;
if format2='' then format=cats(length,'.');
else if formatl=0 then format=cats(format2,'.');
else if formatd=0 then format=cats(format2,formatl,'.');
else format=cats(format2,formatl,'.',formatd);
if fmtname='' then format=cats(length,'.');
else if formatl=0 then format=cats(fmtname,'.');
else if formatd=0 then format=cats(fmtname,formatl,'.');
else format=cats(fmtname,formatl,'.',formatd);
type='N';
if format=:'DATETIME' or format=:'E8601DT' then ddtype='DATETIME';
else if format=:'DATE' or format=:'DDMMYY' or format=:'MMDDYY'
@@ -61,5 +62,6 @@ data &outds(keep=name type length varnum format label ddtype);
end;
if label='' then label=name;
run;
proc sql;
drop table &dropds;
%mend mp_getcols;

View File

@@ -31,22 +31,20 @@
[sasjs adapter](https://github.com/sasjs/adapter).
For more information see https://sasjs.io
@param action Valid values:
@param [in] action Valid values:
@li OPEN - opens the JSON
@li OBJ - sends a table with each row as an object
@li ARR - sends a table with each row in an array
@li CLOSE - closes the JSON
@param ds the dataset to send. Must be a work table.
@param jref= the fileref to which to send the JSON
@param dslabel= the name to give the table in the exported JSON
@param fmt= Whether to keep or strip formats from the table
@param engine= Which engine to use to send the JSON, valid options are:
@param [in] ds The dataset to send. Must be a work table.
@param [out] jref= (_webout) The fileref to which to send the JSON
@param [out] dslabel= The name to give the table in the exported JSON
@param [in] fmt= (Y) Whether to keep (Y) or strip (N) formats from the table
@param [in] engine= (DATASTEP) Which engine to use to send the JSON. Options:
@li PROCJSON (default)
@li DATASTEP (more reliable when data has non standard characters)
@param dbg= DEPRECATED - was used to conditionally add PRETTY to
proc json but this can cause line truncation in large files.
@param [in] missing= (NULL) Special numeric missing values can be sent as NULL
(eg `null`) or as STRING values (eg `".a"` or `".b"`)
<h4> Related Macros <h4>
@li mp_ds2fmtds.sas
@@ -57,9 +55,11 @@
**/
%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP,dbg=0
%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP
,dbg=0 /* DEPRECATED */
,missing=NULL
)/*/STORE SOURCE*/;
%put output location=&jref;
%put &sysmacroname: output location=&jref;
%if &action=OPEN %then %do;
options nobomfile;
data _null_;file &jref encoding='utf-8' ;
@@ -72,10 +72,16 @@
put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":";
%if &engine=PROCJSON %then %do;
%if &missing=STRING %then %do;
%put &sysmacroname: Special Missings are not supported in proc json.;
%put &sysmacroname: Switching to DATASTEP engine;
%goto datastep;
%end;
data;run;%let tempds=&syslast;
proc sql;drop table &tempds;
data &tempds /view=&tempds;set &ds;
%if &fmt=N %then format _numeric_ best32.;;
/* PRETTY is necessary to avoid line truncation in large files */
proc json out=&jref pretty
%if &action=ARR %then nokeys ;
;export &tempds / nosastags fmtnumeric;
@@ -83,6 +89,7 @@
proc sql;drop view &tempds;
%end;
%else %if &engine=DATASTEP %then %do;
%datastep:
%local cols i tempds;
%let cols=0;
%if %sysfunc(exist(&ds)) ne 1 & %sysfunc(exist(&ds,VIEW)) ne 1 %then %do;
@@ -163,7 +170,15 @@
run;
proc format; /* credit yabwon for special null removal */
value bart ._ - .z = null
value bart
%if &missing=NULL %then %do;
._ - .z = null
%end;
%else %do;
._ = [quote()]
. = null
.a - .z = [quote()]
%end;
other = [best.];
data;run; %let tempds=&syslast; /* temp table for spesh char management */

View File

@@ -89,9 +89,11 @@ data _null_;
put "/* Created on %sysfunc(datetime(),datetime19.) by %mf_getuser() */";
/* WEBOUT BEGIN */
put ' ';
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP,dbg=0 ';
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP ';
put ' ,dbg=0 /* DEPRECATED */ ';
put ' ,missing=NULL ';
put ')/*/STORE SOURCE*/; ';
put '%put output location=&jref; ';
put '%put &sysmacroname: output location=&jref; ';
put '%if &action=OPEN %then %do; ';
put ' options nobomfile; ';
put ' data _null_;file &jref encoding=''utf-8'' ; ';
@@ -104,10 +106,16 @@ data _null_;
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
put ' ';
put ' %if &engine=PROCJSON %then %do; ';
put ' %if &missing=STRING %then %do; ';
put ' %put &sysmacroname: Special Missings are not supported in proc json.; ';
put ' %put &sysmacroname: Switching to DATASTEP engine; ';
put ' %goto datastep; ';
put ' %end; ';
put ' data;run;%let tempds=&syslast; ';
put ' proc sql;drop table &tempds; ';
put ' data &tempds /view=&tempds;set &ds; ';
put ' %if &fmt=N %then format _numeric_ best32.;; ';
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
put ' proc json out=&jref pretty ';
put ' %if &action=ARR %then nokeys ; ';
put ' ;export &tempds / nosastags fmtnumeric; ';
@@ -115,6 +123,7 @@ data _null_;
put ' proc sql;drop view &tempds; ';
put ' %end; ';
put ' %else %if &engine=DATASTEP %then %do; ';
put ' %datastep: ';
put ' %local cols i tempds; ';
put ' %let cols=0; ';
put ' %if %sysfunc(exist(&ds)) ne 1 & %sysfunc(exist(&ds,VIEW)) ne 1 %then %do; ';
@@ -195,7 +204,15 @@ data _null_;
put ' run; ';
put ' ';
put ' proc format; /* credit yabwon for special null removal */ ';
put ' value bart ._ - .z = null ';
put ' value bart ';
put ' %if &missing=NULL %then %do; ';
put ' ._ - .z = null ';
put ' %end; ';
put ' %else %do; ';
put ' ._ = [quote()] ';
put ' . = null ';
put ' .a - .z = [quote()] ';
put ' %end; ';
put ' other = [best.]; ';
put ' ';
put ' data;run; %let tempds=&syslast; /* temp table for spesh char management */ ';
@@ -263,7 +280,7 @@ data _null_;
put ' run; ';
put '%end; ';
put '%mend mp_jsonout; ';
put '%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y); ';
put '%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL); ';
put '%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug ';
put ' sasjs_tables; ';
put '%local i tempds jsonengine; ';
@@ -328,7 +345,7 @@ 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,dbg=%str(&_debug) ';
put ' ,engine=&jsonengine,missing=&missing ';
put ' ) ';
put '%end; ';
put '%else %if &action=CLOSE %then %do; ';
@@ -418,8 +435,8 @@ data _null_;
put ' ';
put '%mend mf_getuser; ';
/* WEBOUT END */
put '%macro webout(action,ds,dslabel=,fmt=);';
put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt)';
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL);';
put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing)';
put '%mend;';
run;

View File

@@ -23,17 +23,19 @@
%mm_webout(CLOSE)
@param action Either FETCH, OPEN, ARR, OBJ or CLOSE
@param ds The dataset to send back to the frontend
@param dslabel= value to use instead of the real name for sending to JSON
@param fmt=(Y) Set to N to send back unformatted values
@param fref=(_webout) The fileref to which to write the JSON
@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 [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"`)
@version 9.3
@author Allan Bowe
**/
%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y);
%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL);
%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug
sasjs_tables;
%local i tempds jsonengine;
@@ -98,7 +100,7 @@
%else %if &action=ARR or &action=OBJ %then %do;
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
,engine=&jsonengine,dbg=%str(&_debug)
,engine=&jsonengine,missing=&missing
)
%end;
%else %if &action=CLOSE %then %do;

View File

@@ -1,6 +1,6 @@
{
"name": "@sasjs/core",
"description": "Production Ready Macros for SAS Application Developers",
"description": "Macros for SAS Application Developers",
"license": "MIT",
"keywords": [
"SAS",
@@ -38,4 +38,4 @@
"dependencies": {
"ts-loader": "^9.2.6"
}
}
}

View File

@@ -1,67 +1,73 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- HTML header for doxygen 1.8.17-->
<html xmlns="https://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=9" />
<meta property="og:type" content="website">
<meta name="author" content="Allan Bowe">
<meta name="generator" content="Doxygen $doxygenversion" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!--BEGIN PROJECT_NAME-->
<meta name="description" content="$projectbrief" />
<!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME-->
<title>$title</title>
<!--END !PROJECT_NAME-->
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="$relpath^jquery.js"></script>
<script type="text/javascript" src="$relpath^dynsections.js"></script>
$treeview $search $mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
<link rel="shortcut icon" href="$relpath^favicon.ico" type="image/x-icon" />
$extrastylesheet
</head>
<body>
<div id="top">
<!-- do not remove this div, it is closed by doxygen! -->
<!--BEGIN TITLEAREA-->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px">
<!--BEGIN PROJECT_LOGO-->
<td id="projectlogo">
<a href="$relpath^"
><img alt="Logo" src="$relpath^$projectlogo"
/></a>
</td>
<!--END PROJECT_LOGO-->
<td id="projectalign" style="padding-left: 0.5em">
<div id="projectbrief">
Production Ready Macros for SAS Application Developers<br />
<a href="https://github.com/sasjs/core">
https://github.com/sasjs/core
</a>
</div>
</td>
</tr>
</table>
</td>
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=9" />
<meta property="og:type" content="website">
<meta property="og:title" content="MacroCore" />
<meta property="og:url" content="https://core.sasjs.io" />
<meta property="og:image" content="https://core.sasjs.io/Macro_core_website_1.png" />
<meta name="author" content="Allan Bowe">
<meta name="generator" content="Doxygen $doxygenversion" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!--BEGIN PROJECT_NAME-->
<meta name="description" content="$projectbrief" />
<meta name="og:description" content="$projectbrief" />
<!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME-->
<title>$title</title>
<!--END !PROJECT_NAME-->
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="$relpath^jquery.js"></script>
<script type="text/javascript" src="$relpath^dynsections.js"></script>
$treeview $search $mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
<link rel="shortcut icon" href="$relpath^favicon.ico" type="image/x-icon" />
$extrastylesheet
</head>
<body>
<div id="top">
<!-- do not remove this div, it is closed by doxygen! -->
<!--BEGIN TITLEAREA-->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px">
<!--BEGIN PROJECT_LOGO-->
<td id="projectlogo">
<a href="$relpath^"><img alt="Logo" src="$relpath^$projectlogo" /></a>
</td>
<!--END PROJECT_LOGO-->
<td id="projectalign" style="padding-left: 0.5em">
<div id="projectbrief">
Macros for SAS Application Developers<br />
<a href="https://github.com/sasjs/core">
https://github.com/sasjs/core
</a>
</div>
</td>
</tr>
</table>
</td>
<!--BEGIN DISABLE_INDEX-->
<!--BEGIN SEARCHENGINE-->
<td>$searchbox</td>
<!--END SEARCHENGINE-->
<!--END DISABLE_INDEX-->
</tr>
</tbody>
</table>
</div>
<!--END TITLEAREA-->
<!-- end header part -->
<!--BEGIN DISABLE_INDEX-->
<!--BEGIN SEARCHENGINE-->
<td>$searchbox</td>
<!--END SEARCHENGINE-->
<!--END DISABLE_INDEX-->
</tr>
</tbody>
</table>
</div>
</body>
</html>
<!--END TITLEAREA-->
<!-- end header part -->
</div>
</body>
</html>

View File

@@ -1,5 +1,5 @@
{
"$schema": "https://cli.sasjs.io/sasjsconfig-schema.json",
"$schema": "https://raw.githubusercontent.com/sasjs/utils/main/src/types/sasjsconfig-schema.json",
"macroFolders": [
"base",
"fcmp",

View File

@@ -20,11 +20,13 @@
%ms_webout(CLOSE)
@param action Either FETCH, OPEN, ARR, OBJ or CLOSE
@param ds The dataset to send back to the frontend
@param dslabel= value to use instead of the real name for sending to JSON
@param fmt=(Y) Set to N to send back unformatted values
@param fref=(_webout) The fileref to which to write the JSON
@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 [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"`)
<h4> SAS Macros </h4>
@li mp_jsonout.sas
@@ -39,7 +41,7 @@
**/
%macro ms_webout(action,ds,dslabel=,fref=_webout,fmt=Y);
%macro ms_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL);
%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug
sasjs_tables;
@@ -91,7 +93,7 @@
%else %if &action=ARR or &action=OBJ %then %do;
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
,engine=DATASTEP,dbg=%str(&_debug)
,engine=DATASTEP,missing=&missing
)
%end;
%else %if &action=CLOSE %then %do;

View File

@@ -4,6 +4,7 @@
<h4> SAS Macros </h4>
@li mp_getcols.sas
@li mp_assertcols.sas
@li mp_assertcolvals.sas
@li mp_assertdsobs.sas
@@ -30,4 +31,10 @@ run;
checkvals=work.check.val,
desc=All values have a match,
test=ALLVALS
)
%mp_assertcols(work.info,
cols=name type length varnum format label ddtype fmtname,
test=ALL,
desc=check all columns exist
)

View File

@@ -34,6 +34,11 @@ data work.test;
call symputx('dtval',dtval);
run;
%mp_assert(
iftrue=(&syscc=0),
desc=Checking for error condition,
outds=work.test_results
)
%mp_assert(
iftrue=(&dtval=&compare),

View File

@@ -0,0 +1,52 @@
/**
@file
@brief Testing mp_jsonout.sas macro with special missings
<h4> SAS Macros </h4>
@li mp_jsonout.sas
@li mp_assert.sas
**/
filename webref temp;
data demo;
do x=._,.,.a,.b,.c,.d,.e,-99, 0, 1,2, 3.333333;
output;
end;
run;
%mp_jsonout(OPEN,jref=webref)
%mp_jsonout(OBJ,demo,jref=webref,fmt=N,missing=STRING)
%mp_jsonout(CLOSE,jref=webref)
data _null_;
infile webref;
input;
putlog _infile_;
run;
libname web JSON fileref=webref;
/* proc json turns to char - so switch back to numeric */
data work.test(keep=x);
set web.demo(rename=(x=y));
if y ='_' then x=._;
else if anyalpha(y) then x=input(cats(".",y),best.);
else x=input(y,best.);
put (_all_)(=);
run;
%mp_assert(
iftrue=(&syscc=0),
desc=Checking for error condition with special missing export,
outds=work.test_results
)
proc compare base=work.demo compare=work.test;
quit;
%mp_assert(
iftrue=(&sysinfo=0),
desc=Returned json is identical to input table for all special missings,
outds=work.test_results
)

View File

@@ -54,9 +54,9 @@
that location
@param [in] adapter= the macro uses the sasjs adapter by default. To use
another adapter, add a (different) fileref here.
@param [in] contextname= Choose a specific context on which to run the Job. Leave
blank to use the default context. From Viya 3.5 it is possible to configure
a shared context - see
@param [in] contextname= Choose a specific context on which to run the Job.
Leave blank to use the default context. From Viya 3.5 it is possible to
configure a shared context - see
https://go.documentation.sas.com/?docsetId=calcontexts&docsetTarget=n1hjn8eobk5pyhn1wg3ja0drdl6h.htm&docsetVersion=3.5&locale=en
@param [in] mdebug=(0) set to 1 to enable DEBUG messages
@@ -237,9 +237,11 @@ data _null_;
put "/* Created on %sysfunc(datetime(),datetime19.) by &sysuserid */";
/* WEBOUT BEGIN */
put ' ';
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP,dbg=0 ';
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y,engine=DATASTEP ';
put ' ,dbg=0 /* DEPRECATED */ ';
put ' ,missing=NULL ';
put ')/*/STORE SOURCE*/; ';
put '%put output location=&jref; ';
put '%put &sysmacroname: output location=&jref; ';
put '%if &action=OPEN %then %do; ';
put ' options nobomfile; ';
put ' data _null_;file &jref encoding=''utf-8'' ; ';
@@ -252,10 +254,16 @@ data _null_;
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
put ' ';
put ' %if &engine=PROCJSON %then %do; ';
put ' %if &missing=STRING %then %do; ';
put ' %put &sysmacroname: Special Missings are not supported in proc json.; ';
put ' %put &sysmacroname: Switching to DATASTEP engine; ';
put ' %goto datastep; ';
put ' %end; ';
put ' data;run;%let tempds=&syslast; ';
put ' proc sql;drop table &tempds; ';
put ' data &tempds /view=&tempds;set &ds; ';
put ' %if &fmt=N %then format _numeric_ best32.;; ';
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
put ' proc json out=&jref pretty ';
put ' %if &action=ARR %then nokeys ; ';
put ' ;export &tempds / nosastags fmtnumeric; ';
@@ -263,6 +271,7 @@ data _null_;
put ' proc sql;drop view &tempds; ';
put ' %end; ';
put ' %else %if &engine=DATASTEP %then %do; ';
put ' %datastep: ';
put ' %local cols i tempds; ';
put ' %let cols=0; ';
put ' %if %sysfunc(exist(&ds)) ne 1 & %sysfunc(exist(&ds,VIEW)) ne 1 %then %do; ';
@@ -343,7 +352,15 @@ data _null_;
put ' run; ';
put ' ';
put ' proc format; /* credit yabwon for special null removal */ ';
put ' value bart ._ - .z = null ';
put ' value bart ';
put ' %if &missing=NULL %then %do; ';
put ' ._ - .z = null ';
put ' %end; ';
put ' %else %do; ';
put ' ._ = [quote()] ';
put ' . = null ';
put ' .a - .z = [quote()] ';
put ' %end; ';
put ' other = [best.]; ';
put ' ';
put ' data;run; %let tempds=&syslast; /* temp table for spesh char management */ ';
@@ -411,7 +428,7 @@ data _null_;
put ' run; ';
put '%end; ';
put '%mend mp_jsonout; ';
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y); ';
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y,missing=NULL); ';
put '%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name ';
put ' sasjs_tables SYS_JES_JOB_URI; ';
put '%if %index("&_debug",log) %then %let _debug=131; ';
@@ -538,7 +555,7 @@ data _null_;
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,dbg=%str(&_debug) ';
put ' ,jref=&fref,engine=DATASTEP,missing=&missing ';
put ' ) ';
put '%end; ';
put '%else %if &action=CLOSE %then %do; ';
@@ -629,8 +646,8 @@ data _null_;
put '%global __program _program;';
put '%let _program=%sysfunc(coalescec(&__program,&_program));';
put ' ';
put '%macro webout(action,ds,dslabel=,fmt=);';
put ' %mv_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt)';
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL);';
put ' %mv_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing)';
put '%mend;';
run;

View File

@@ -20,13 +20,15 @@
%mv_webout(CLOSE)
@param action Either OPEN, ARR, OBJ or CLOSE
@param ds The dataset to send back to the frontend
@param _webout= fileref for returning the json
@param fref=(_mvwtemp) Temp fileref to which to write the output
@param dslabel= value to use instead of the real name for sending to JSON
@param fmt=(Y) change to N to strip formats from output
@param stream=(Y) Change to N if not streaming to _webout
@param [in] action Either OPEN, ARR, OBJ or CLOSE
@param [in] ds The dataset to send back to the frontend
@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] 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"`)
<h4> SAS Macros </h4>
@li mp_jsonout.sas
@@ -36,7 +38,7 @@
@author Allan Bowe, source: https://github.com/sasjs/core
**/
%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y);
%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y,missing=NULL);
%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name
sasjs_tables SYS_JES_JOB_URI;
%if %index("&_debug",log) %then %let _debug=131;
@@ -163,7 +165,7 @@
%end;
%else %if &action=ARR or &action=OBJ %then %do;
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt
,jref=&fref,engine=DATASTEP,dbg=%str(&_debug)
,jref=&fref,engine=DATASTEP,missing=&missing
)
%end;
%else %if &action=CLOSE %then %do;