1
0
mirror of https://github.com/sasjs/core.git synced 2025-12-10 14:04:36 +00:00

fix: auto-detect cmplib in mcfxx funcs, mp_ds2csv supports dates etc, fix to mp_abort in viya due to abort cancel FILE hard stop (according to docs it should continue outside of the include)

This commit is contained in:
munja
2022-02-02 21:18:51 +01:00
parent 64f53acce2
commit 3554991ff8
10 changed files with 293 additions and 57 deletions

View File

@@ -196,6 +196,8 @@ When contributing to this library, it is therefore important to ensure that all
We are currently on major release v4. Breaking changes should be marked with the [deprecated](https://www.doxygen.nl/manual/commands.html#cmddeprecated) doxygen tag. The following changes are planned when the next major (breaking) release becomes necessary: We are currently on major release v4. Breaking changes should be marked with the [deprecated](https://www.doxygen.nl/manual/commands.html#cmddeprecated) doxygen tag. The following changes are planned when the next major (breaking) release becomes necessary:
* mp_testservice.sas to be renamed as mp_execute.sas (as it doesn't actually test anything) * mp_testservice.sas to be renamed as mp_execute.sas (as it doesn't actually test anything)
* `insert_cmplib` option of mcf_xxx macros will be deprecated (the option is now checked automatically with value inserted only if needed)
* mcf_xxx macros to have `wrap=` option defaulted to YES for convenience
## Star Gazing ## Star Gazing

138
all.sas
View File

@@ -2106,7 +2106,10 @@ Usage:
%if %length(&mac)>0 %then %put NOTE- called by &mac; %if %length(&mac)>0 %then %put NOTE- called by &mac;
%put NOTE - &msg; %put NOTE - &msg;
%if %symexist(_SYSINCLUDEFILEDEVICE) %then %do; %if %symexist(_SYSINCLUDEFILEDEVICE)
/* abort cancel FILE does not restart outside the INCLUDE on Viya 3.5 */
and "&SYSPROCESSNAME " ne "Compute Server "
%then %do;
%if "*&_SYSINCLUDEFILEDEVICE*" ne "**" %then %do; %if "*&_SYSINCLUDEFILEDEVICE*" ne "**" %then %do;
data &errds; data &errds;
iftrue='1=1'; iftrue='1=1';
@@ -4666,10 +4669,28 @@ quit;
@brief Export a dataset to a CSV file WITH leading blanks @brief Export a dataset to a CSV file WITH leading blanks
@details Export a dataset to a file or fileref, retaining leading blanks. @details Export a dataset to a file or fileref, retaining leading blanks.
When using SASJS headerformat, the input statement is provided in the first
row of the CSV.
Usage: Usage:
%mp_ds2csv(sashelp.class,outref="%sysfunc(pathname(work))/file.csv") %mp_ds2csv(sashelp.class,outref="%sysfunc(pathname(work))/file.csv")
filename example temp;
%mp_ds2csv(sashelp.air,outref=example,headerformat=SASJS)
data; infile example; input;put _infile_; if _n_>5 then stop;run;
data _null_;
infile example;
input;
call symputx('stmnt',_infile_);
stop;
run;
data work.want;
infile example dsd firstobs=2;
input &stmnt;
run;
Why use mp_ds2csv over, say, proc export? Why use mp_ds2csv over, say, proc export?
1. Ability to retain leading blanks (this is a major one) 1. Ability to retain leading blanks (this is a major one)
@@ -4686,7 +4707,12 @@ quit;
@li LABEL - Use the variable label (or name, if blank) @li LABEL - Use the variable label (or name, if blank)
@li NAME - Use the variable name @li NAME - Use the variable name
@li SASJS - Used to create sasjs-formatted input CSVs, eg for use in @li SASJS - Used to create sasjs-formatted input CSVs, eg for use in
mp_testservice.sas mp_testservice.sas. This format will supply an input statement in the
first row, making ingestion by datastep a breeze. Special misisng values
will be prefixed with a period (eg `.A`) to enable ingestion on both SAS 9
and Viya. Dates / Datetimes etc are identified by the format type (lookup
with mcf_getfmttype.sas) and converted to human readable formats (not
numbers).
@param [out] outfile= The output filename - should be quoted. @param [out] outfile= The output filename - should be quoted.
@param [out] outref= (0) The output fileref (takes precedence if provided) @param [out] outref= (0) The output fileref (takes precedence if provided)
@param [in] outencoding= (0) The output encoding to use (unquoted) @param [in] outencoding= (0) The output encoding to use (unquoted)
@@ -4696,7 +4722,9 @@ quit;
@li LF @li LF
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_getfmttype.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_getvarformat.sas
@li mf_getvarlist.sas @li mf_getvarlist.sas
@li mf_getvartype.sas @li mf_getvartype.sas
@@ -4713,7 +4741,7 @@ quit;
,termstr=CRLF ,termstr=CRLF
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local outloc delim i varlist var vcnt vat dsv vcom vmiss; %local outloc delim i varlist var vcnt vat dsv vcom vmiss fmttype vfmt;
%if not %sysfunc(exist(&ds)) %then %do; %if not %sysfunc(exist(&ds)) %then %do;
%put %str(WARN)ING: &ds does not exist; %put %str(WARN)ING: &ds does not exist;
@@ -4731,6 +4759,7 @@ quit;
%if &headerformat=SASJS %then %do; %if &headerformat=SASJS %then %do;
%let delim=","; %let delim=",";
%let termstr=CRLF; %let termstr=CRLF;
%mcf_getfmttype(wrap=YES)
%end; %end;
%else %if &dlm=COMMA %then %let delim=","; %else %if &dlm=COMMA %then %let delim=",";
%else %let delim=";"; %else %let delim=";";
@@ -4740,7 +4769,8 @@ quit;
/* first get headers */ /* first get headers */
data _null_; data _null_;
file &outloc &outencoding lrecl=32767 termstr=&termstr; file &outloc &outencoding lrecl=32767 termstr=&termstr;
length header $ 2000 varnm $32 dlm $1; length header $ 2000 varnm vfmt $32 dlm $1 fmttype $8;
call missing(of _all_);
dsid=open("&ds.","i"); dsid=open("&ds.","i");
num=attrn(dsid,"nvars"); num=attrn(dsid,"nvars");
dlm=&delim; dlm=&delim;
@@ -4755,7 +4785,14 @@ data _null_;
%end; %end;
%else %if &headerformat=SASJS %then %do; %else %if &headerformat=SASJS %then %do;
if vartype(dsid,i)='C' then header=cats(varnm,':$char',varlen(dsid,i),'.'); if vartype(dsid,i)='C' then header=cats(varnm,':$char',varlen(dsid,i),'.');
else header=cats(varnm,':best.'); else do;
vfmt=coalescec(varfmt(dsid,i),'0');
fmttype=mcf_getfmttype(vfmt);
if fmttype='DATE' then header=cats(varnm,':date9.');
else if fmttype='DATETIME' then header=cats(varnm,':E8601DT26.6');
else if fmttype='TIME' then header=cats(varnm,':TIME12.');
else header=cats(varnm,':best.');
end;
%end; %end;
%else %do; %else %do;
%put &sysmacroname: Invalid headerformat value (&headerformat); %put &sysmacroname: Invalid headerformat value (&headerformat);
@@ -4810,14 +4847,29 @@ data _null_;
%let vcom=; %let vcom=;
%end; %end;
%if %mf_getvartype(&ds,&var)=N %then %do; %if %mf_getvartype(&ds,&var)=N %then %do;
%if &headerformat = SASJS %then %do;
%let vcom=&delim;
%let fmttype=%sysfunc(mcf_getfmttype(%mf_getvarformat(&ds,&var)0));
%if &fmttype=DATE %then %let vfmt=DATE9.;
%else %if &fmttype=DATETIME %then %let vfmt=E8601DT26.6;
%else %if &fmttype=TIME %then %let vfmt=TIME12.;
%else %do;
%let vfmt=;
%let vcom=;
%end;
%end;
%else %let vcom=;
/* must use period - in order to work in both 9.4 and Viya 3.5 */ /* must use period - in order to work in both 9.4 and Viya 3.5 */
if missing(&var) and &var ne %sysfunc(getoption(MISSING)) then do; if missing(&var) and &var ne %sysfunc(getoption(MISSING)) then do;
&vmiss=cats('.',&var); &vmiss=cats('.',&var);
put &vmiss &vat; put &vmiss &vat;
end; end;
else put &var &vat; else put &var &vfmt &vcom &vat;
%end; %end;
%else %do; %else %do;
%if &i ne &vcnt %then %let vcom=&delim;
put &var &&vlen&i &vcom &vat; put &var &&vlen&i &vcom &vat;
%end; %end;
%end; %end;
@@ -7878,9 +7930,10 @@ https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/mcrolref/n1j5tcc0n2xczyn1
this dataset. this dataset.
It will then run an abort cancel FILE to stop the include running, and pass It will then run an abort cancel FILE to stop the include running, and pass
the dataset back. the dataset back.
NOTE - it is NOT possible to read this dataset as part of _this_ macro -
when running abort cancel FILE, ALL macros are closed, so instead it is IMPORTANT NOTE - it is NOT possible to read this dataset as part of _this_
necessary to invoke "%mp_abort(mode=INCLUDE)" OUTSIDE of any macro wrappers. macro! When running abort cancel FILE, ALL macros are closed, so instead it
is necessary to invoke "%mp_abort(mode=INCLUDE)" OUTSIDE of macro wrappers.
@version 9.4 @version 9.4
@@ -23585,12 +23638,12 @@ run;
> fmt3=TIME > fmt3=TIME
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
@param [out] insert_cmplib= (NO) Choose YES to insert the package into the
CMPLIB reference.
@param [out] lib= (work) The output library in which to create the catalog. @param [out] lib= (work) The output library in which to create the catalog.
@param [out] cat= (sasjs) The output catalog in which to create the package. @param [out] cat= (sasjs) The output catalog in which to create the package.
@param [out] pkg= (utils) The output package in which to create the function. @param [out] pkg= (utils) The output package in which to create the function.
Uses a 3 part format: libref.catalog.package Uses a 3 part format: libref.catalog.package
@param [out] insert_cmplib= DEPRECATED - The CMPLIB option is checked and
values inserted only if needed.
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_init.sas @li mcf_init.sas
@@ -23605,11 +23658,12 @@ run;
**/ **/
%macro mcf_getfmttype(wrap=NO %macro mcf_getfmttype(wrap=NO
,insert_cmplib=NO ,insert_cmplib=DEPRECATED
,lib=WORK ,lib=WORK
,cat=SASJS ,cat=SASJS
,pkg=UTILS ,pkg=UTILS
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local i var cmpval found;
%if %mcf_init(mcf_getfmttype)=1 %then %return; %if %mcf_init(mcf_getfmttype)=1 %then %return;
@@ -23657,7 +23711,14 @@ endsub;
quit; quit;
%end; %end;
%if &insert_cmplib=YES %then %do; /* insert the CMPLIB if not already there */
%let cmpval=%sysfunc(getoption(cmplib));
%let found=0;
%do i=1 %to %sysfunc(countw(&cmpval,%str( %(%))));
%let var=%scan(&cmpval,&i,%str( %(%)));
%if &var=&lib..&cat %then %let found=1;
%end;
%if &found=0 %then %do;
options insert=(CMPLIB=(&lib..&cat)); options insert=(CMPLIB=(&lib..&cat));
%end; %end;
@@ -23739,12 +23800,12 @@ endsub;
> outa=3 outb=4 outc=5 outd=0 > outa=3 outb=4 outc=5 outd=0
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
@param [out] insert_cmplib= (NO) Choose YES to insert the package into the
CMPLIB reference.
@param [out] lib= (work) The output library in which to create the catalog. @param [out] lib= (work) The output library in which to create the catalog.
@param [out] cat= (sasjs) The output catalog in which to create the package. @param [out] cat= (sasjs) The output catalog in which to create the package.
@param [out] pkg= (utils) The output package in which to create the function. @param [out] pkg= (utils) The output package in which to create the function.
Uses a 3 part format: libref.catalog.package Uses a 3 part format: libref.catalog.package
@param [out] insert_cmplib= DEPRECATED - The CMPLIB option is checked and
values inserted only if needed.
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_init.sas @li mcf_init.sas
@@ -23756,12 +23817,12 @@ endsub;
**/ **/
%macro mcf_length(wrap=NO %macro mcf_length(wrap=NO
,insert_cmplib=NO ,insert_cmplib=DEPRECATED
,lib=WORK ,lib=WORK
,cat=SASJS ,cat=SASJS
,pkg=UTILS ,pkg=UTILS
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local i var cmpval found;
%if %mcf_init(mcf_length)=1 %then %return; %if %mcf_init(mcf_length)=1 %then %return;
%if &wrap=YES %then %do; %if &wrap=YES %then %do;
@@ -23783,7 +23844,14 @@ endsub;
quit; quit;
%end; %end;
%if &insert_cmplib=YES %then %do; /* insert the CMPLIB if not already there */
%let cmpval=%sysfunc(getoption(cmplib));
%let found=0;
%do i=1 %to %sysfunc(countw(&cmpval,%str( %(%))));
%let var=%scan(&cmpval,&i,%str( %(%)));
%if &var=&lib..&cat %then %let found=1;
%end;
%if &found=0 %then %do;
options insert=(CMPLIB=(&lib..&cat)); options insert=(CMPLIB=(&lib..&cat));
%end; %end;
@@ -23836,12 +23904,12 @@ endsub;
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
@param [out] insert_cmplib= (NO) Choose YES to insert the package into the
CMPLIB reference.
@param [out] lib= (work) The output library in which to create the catalog. @param [out] lib= (work) The output library in which to create the catalog.
@param [out] cat= (sasjs) The output catalog in which to create the package. @param [out] cat= (sasjs) The output catalog in which to create the package.
@param [out] pkg= (utils) The output package in which to create the function. @param [out] pkg= (utils) The output package in which to create the function.
Uses a 3 part format: libref.catalog.package Uses a 3 part format: libref.catalog.package
@param [out] insert_cmplib= DEPRECATED - The CMPLIB option is checked and
values inserted only if needed.
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_init.sas @li mcf_init.sas
@@ -23853,12 +23921,12 @@ endsub;
**/ **/
%macro mcf_stpsrv_header(wrap=NO %macro mcf_stpsrv_header(wrap=NO
,insert_cmplib=NO ,insert_cmplib=DEPRECATED
,lib=WORK ,lib=WORK
,cat=SASJS ,cat=SASJS
,pkg=UTILS ,pkg=UTILS
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local i var cmpval found;
%if %mcf_init(stpsrv_header)=1 %then %return; %if %mcf_init(stpsrv_header)=1 %then %return;
%if &wrap=YES %then %do; %if &wrap=YES %then %do;
@@ -23885,7 +23953,14 @@ endsub;
quit; quit;
%end; %end;
%if &insert_cmplib=YES %then %do; /* insert the CMPLIB if not already there */
%let cmpval=%sysfunc(getoption(cmplib));
%let found=0;
%do i=1 %to %sysfunc(countw(&cmpval,%str( %(%))));
%let var=%scan(&cmpval,&i,%str( %(%)));
%if &var=&lib..&cat %then %let found=1;
%end;
%if &found=0 %then %do;
options insert=(CMPLIB=(&lib..&cat)); options insert=(CMPLIB=(&lib..&cat));
%end; %end;
@@ -23923,12 +23998,12 @@ endsub;
run; run;
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
@param [out] insert_cmplib= (NO) Choose YES to insert the package into the
CMPLIB reference.
@param [out] lib= (work) The output library in which to create the catalog. @param [out] lib= (work) The output library in which to create the catalog.
@param [out] cat= (sasjs) The output catalog in which to create the package. @param [out] cat= (sasjs) The output catalog in which to create the package.
@param [out] pkg= (utils) The output package in which to create the function. @param [out] pkg= (utils) The output package in which to create the function.
Uses a 3 part format: libref.catalog.package Uses a 3 part format: libref.catalog.package
@param [out] insert_cmplib= DEPRECATED - The CMPLIB option is checked and
values inserted only if needed.
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_init.sas @li mcf_init.sas
@@ -23940,12 +24015,12 @@ endsub;
**/ **/
%macro mcf_string2file(wrap=NO %macro mcf_string2file(wrap=NO
,insert_cmplib=NO ,insert_cmplib=DEPRECATED
,lib=WORK ,lib=WORK
,cat=SASJS ,cat=SASJS
,pkg=UTILS ,pkg=UTILS
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local i var cmpval found;
%if %mcf_init(mcf_string2file)=1 %then %return; %if %mcf_init(mcf_string2file)=1 %then %return;
%if &wrap=YES %then %do; %if &wrap=YES %then %do;
@@ -23972,7 +24047,14 @@ endsub;
quit; quit;
%end; %end;
%if &insert_cmplib=YES %then %do; /* insert the CMPLIB if not already there */
%let cmpval=%sysfunc(getoption(cmplib));
%let found=0;
%do i=1 %to %sysfunc(countw(&cmpval,%str( %(%))));
%let var=%scan(&cmpval,&i,%str( %(%)));
%if &var=&lib..&cat %then %let found=1;
%end;
%if &found=0 %then %do;
options insert=(CMPLIB=(&lib..&cat)); options insert=(CMPLIB=(&lib..&cat));
%end; %end;

View File

@@ -66,7 +66,10 @@
%if %length(&mac)>0 %then %put NOTE- called by &mac; %if %length(&mac)>0 %then %put NOTE- called by &mac;
%put NOTE - &msg; %put NOTE - &msg;
%if %symexist(_SYSINCLUDEFILEDEVICE) %then %do; %if %symexist(_SYSINCLUDEFILEDEVICE)
/* abort cancel FILE does not restart outside the INCLUDE on Viya 3.5 */
and "&SYSPROCESSNAME " ne "Compute Server "
%then %do;
%if "*&_SYSINCLUDEFILEDEVICE*" ne "**" %then %do; %if "*&_SYSINCLUDEFILEDEVICE*" ne "**" %then %do;
data &errds; data &errds;
iftrue='1=1'; iftrue='1=1';

View File

@@ -3,10 +3,28 @@
@brief Export a dataset to a CSV file WITH leading blanks @brief Export a dataset to a CSV file WITH leading blanks
@details Export a dataset to a file or fileref, retaining leading blanks. @details Export a dataset to a file or fileref, retaining leading blanks.
When using SASJS headerformat, the input statement is provided in the first
row of the CSV.
Usage: Usage:
%mp_ds2csv(sashelp.class,outref="%sysfunc(pathname(work))/file.csv") %mp_ds2csv(sashelp.class,outref="%sysfunc(pathname(work))/file.csv")
filename example temp;
%mp_ds2csv(sashelp.air,outref=example,headerformat=SASJS)
data; infile example; input;put _infile_; if _n_>5 then stop;run;
data _null_;
infile example;
input;
call symputx('stmnt',_infile_);
stop;
run;
data work.want;
infile example dsd firstobs=2;
input &stmnt;
run;
Why use mp_ds2csv over, say, proc export? Why use mp_ds2csv over, say, proc export?
1. Ability to retain leading blanks (this is a major one) 1. Ability to retain leading blanks (this is a major one)
@@ -23,7 +41,12 @@
@li LABEL - Use the variable label (or name, if blank) @li LABEL - Use the variable label (or name, if blank)
@li NAME - Use the variable name @li NAME - Use the variable name
@li SASJS - Used to create sasjs-formatted input CSVs, eg for use in @li SASJS - Used to create sasjs-formatted input CSVs, eg for use in
mp_testservice.sas mp_testservice.sas. This format will supply an input statement in the
first row, making ingestion by datastep a breeze. Special misisng values
will be prefixed with a period (eg `.A`) to enable ingestion on both SAS 9
and Viya. Dates / Datetimes etc are identified by the format type (lookup
with mcf_getfmttype.sas) and converted to human readable formats (not
numbers).
@param [out] outfile= The output filename - should be quoted. @param [out] outfile= The output filename - should be quoted.
@param [out] outref= (0) The output fileref (takes precedence if provided) @param [out] outref= (0) The output fileref (takes precedence if provided)
@param [in] outencoding= (0) The output encoding to use (unquoted) @param [in] outencoding= (0) The output encoding to use (unquoted)
@@ -33,7 +56,9 @@
@li LF @li LF
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_getfmttype.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_getvarformat.sas
@li mf_getvarlist.sas @li mf_getvarlist.sas
@li mf_getvartype.sas @li mf_getvartype.sas
@@ -50,7 +75,7 @@
,termstr=CRLF ,termstr=CRLF
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local outloc delim i varlist var vcnt vat dsv vcom vmiss; %local outloc delim i varlist var vcnt vat dsv vcom vmiss fmttype vfmt;
%if not %sysfunc(exist(&ds)) %then %do; %if not %sysfunc(exist(&ds)) %then %do;
%put %str(WARN)ING: &ds does not exist; %put %str(WARN)ING: &ds does not exist;
@@ -68,6 +93,7 @@
%if &headerformat=SASJS %then %do; %if &headerformat=SASJS %then %do;
%let delim=","; %let delim=",";
%let termstr=CRLF; %let termstr=CRLF;
%mcf_getfmttype(wrap=YES)
%end; %end;
%else %if &dlm=COMMA %then %let delim=","; %else %if &dlm=COMMA %then %let delim=",";
%else %let delim=";"; %else %let delim=";";
@@ -77,7 +103,8 @@
/* first get headers */ /* first get headers */
data _null_; data _null_;
file &outloc &outencoding lrecl=32767 termstr=&termstr; file &outloc &outencoding lrecl=32767 termstr=&termstr;
length header $ 2000 varnm $32 dlm $1; length header $ 2000 varnm vfmt $32 dlm $1 fmttype $8;
call missing(of _all_);
dsid=open("&ds.","i"); dsid=open("&ds.","i");
num=attrn(dsid,"nvars"); num=attrn(dsid,"nvars");
dlm=&delim; dlm=&delim;
@@ -92,7 +119,14 @@ data _null_;
%end; %end;
%else %if &headerformat=SASJS %then %do; %else %if &headerformat=SASJS %then %do;
if vartype(dsid,i)='C' then header=cats(varnm,':$char',varlen(dsid,i),'.'); if vartype(dsid,i)='C' then header=cats(varnm,':$char',varlen(dsid,i),'.');
else header=cats(varnm,':best.'); else do;
vfmt=coalescec(varfmt(dsid,i),'0');
fmttype=mcf_getfmttype(vfmt);
if fmttype='DATE' then header=cats(varnm,':date9.');
else if fmttype='DATETIME' then header=cats(varnm,':E8601DT26.6');
else if fmttype='TIME' then header=cats(varnm,':TIME12.');
else header=cats(varnm,':best.');
end;
%end; %end;
%else %do; %else %do;
%put &sysmacroname: Invalid headerformat value (&headerformat); %put &sysmacroname: Invalid headerformat value (&headerformat);
@@ -147,14 +181,29 @@ data _null_;
%let vcom=; %let vcom=;
%end; %end;
%if %mf_getvartype(&ds,&var)=N %then %do; %if %mf_getvartype(&ds,&var)=N %then %do;
%if &headerformat = SASJS %then %do;
%let vcom=&delim;
%let fmttype=%sysfunc(mcf_getfmttype(%mf_getvarformat(&ds,&var)0));
%if &fmttype=DATE %then %let vfmt=DATE9.;
%else %if &fmttype=DATETIME %then %let vfmt=E8601DT26.6;
%else %if &fmttype=TIME %then %let vfmt=TIME12.;
%else %do;
%let vfmt=;
%let vcom=;
%end;
%end;
%else %let vcom=;
/* must use period - in order to work in both 9.4 and Viya 3.5 */ /* must use period - in order to work in both 9.4 and Viya 3.5 */
if missing(&var) and &var ne %sysfunc(getoption(MISSING)) then do; if missing(&var) and &var ne %sysfunc(getoption(MISSING)) then do;
&vmiss=cats('.',&var); &vmiss=cats('.',&var);
put &vmiss &vat; put &vmiss &vat;
end; end;
else put &var &vat; else put &var &vfmt &vcom &vat;
%end; %end;
%else %do; %else %do;
%if &i ne &vcnt %then %let vcom=&delim;
put &var &&vlen&i &vcom &vat; put &var &&vlen&i &vcom &vat;
%end; %end;
%end; %end;

View File

@@ -51,9 +51,10 @@ https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/mcrolref/n1j5tcc0n2xczyn1
this dataset. this dataset.
It will then run an abort cancel FILE to stop the include running, and pass It will then run an abort cancel FILE to stop the include running, and pass
the dataset back. the dataset back.
NOTE - it is NOT possible to read this dataset as part of _this_ macro -
when running abort cancel FILE, ALL macros are closed, so instead it is IMPORTANT NOTE - it is NOT possible to read this dataset as part of _this_
necessary to invoke "%mp_abort(mode=INCLUDE)" OUTSIDE of any macro wrappers. macro! When running abort cancel FILE, ALL macros are closed, so instead it
is necessary to invoke "%mp_abort(mode=INCLUDE)" OUTSIDE of macro wrappers.
@version 9.4 @version 9.4

View File

@@ -31,12 +31,12 @@
> fmt3=TIME > fmt3=TIME
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
@param [out] insert_cmplib= (NO) Choose YES to insert the package into the
CMPLIB reference.
@param [out] lib= (work) The output library in which to create the catalog. @param [out] lib= (work) The output library in which to create the catalog.
@param [out] cat= (sasjs) The output catalog in which to create the package. @param [out] cat= (sasjs) The output catalog in which to create the package.
@param [out] pkg= (utils) The output package in which to create the function. @param [out] pkg= (utils) The output package in which to create the function.
Uses a 3 part format: libref.catalog.package Uses a 3 part format: libref.catalog.package
@param [out] insert_cmplib= DEPRECATED - The CMPLIB option is checked and
values inserted only if needed.
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_init.sas @li mcf_init.sas
@@ -51,11 +51,12 @@
**/ **/
%macro mcf_getfmttype(wrap=NO %macro mcf_getfmttype(wrap=NO
,insert_cmplib=NO ,insert_cmplib=DEPRECATED
,lib=WORK ,lib=WORK
,cat=SASJS ,cat=SASJS
,pkg=UTILS ,pkg=UTILS
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local i var cmpval found;
%if %mcf_init(mcf_getfmttype)=1 %then %return; %if %mcf_init(mcf_getfmttype)=1 %then %return;
@@ -103,7 +104,14 @@ endsub;
quit; quit;
%end; %end;
%if &insert_cmplib=YES %then %do; /* insert the CMPLIB if not already there */
%let cmpval=%sysfunc(getoption(cmplib));
%let found=0;
%do i=1 %to %sysfunc(countw(&cmpval,%str( %(%))));
%let var=%scan(&cmpval,&i,%str( %(%)));
%if &var=&lib..&cat %then %let found=1;
%end;
%if &found=0 %then %do;
options insert=(CMPLIB=(&lib..&cat)); options insert=(CMPLIB=(&lib..&cat));
%end; %end;

View File

@@ -32,12 +32,12 @@
> outa=3 outb=4 outc=5 outd=0 > outa=3 outb=4 outc=5 outd=0
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
@param [out] insert_cmplib= (NO) Choose YES to insert the package into the
CMPLIB reference.
@param [out] lib= (work) The output library in which to create the catalog. @param [out] lib= (work) The output library in which to create the catalog.
@param [out] cat= (sasjs) The output catalog in which to create the package. @param [out] cat= (sasjs) The output catalog in which to create the package.
@param [out] pkg= (utils) The output package in which to create the function. @param [out] pkg= (utils) The output package in which to create the function.
Uses a 3 part format: libref.catalog.package Uses a 3 part format: libref.catalog.package
@param [out] insert_cmplib= DEPRECATED - The CMPLIB option is checked and
values inserted only if needed.
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_init.sas @li mcf_init.sas
@@ -49,12 +49,12 @@
**/ **/
%macro mcf_length(wrap=NO %macro mcf_length(wrap=NO
,insert_cmplib=NO ,insert_cmplib=DEPRECATED
,lib=WORK ,lib=WORK
,cat=SASJS ,cat=SASJS
,pkg=UTILS ,pkg=UTILS
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local i var cmpval found;
%if %mcf_init(mcf_length)=1 %then %return; %if %mcf_init(mcf_length)=1 %then %return;
%if &wrap=YES %then %do; %if &wrap=YES %then %do;
@@ -76,7 +76,14 @@ endsub;
quit; quit;
%end; %end;
%if &insert_cmplib=YES %then %do; /* insert the CMPLIB if not already there */
%let cmpval=%sysfunc(getoption(cmplib));
%let found=0;
%do i=1 %to %sysfunc(countw(&cmpval,%str( %(%))));
%let var=%scan(&cmpval,&i,%str( %(%)));
%if &var=&lib..&cat %then %let found=1;
%end;
%if &found=0 %then %do;
options insert=(CMPLIB=(&lib..&cat)); options insert=(CMPLIB=(&lib..&cat));
%end; %end;

View File

@@ -47,12 +47,12 @@
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
@param [out] insert_cmplib= (NO) Choose YES to insert the package into the
CMPLIB reference.
@param [out] lib= (work) The output library in which to create the catalog. @param [out] lib= (work) The output library in which to create the catalog.
@param [out] cat= (sasjs) The output catalog in which to create the package. @param [out] cat= (sasjs) The output catalog in which to create the package.
@param [out] pkg= (utils) The output package in which to create the function. @param [out] pkg= (utils) The output package in which to create the function.
Uses a 3 part format: libref.catalog.package Uses a 3 part format: libref.catalog.package
@param [out] insert_cmplib= DEPRECATED - The CMPLIB option is checked and
values inserted only if needed.
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_init.sas @li mcf_init.sas
@@ -64,12 +64,12 @@
**/ **/
%macro mcf_stpsrv_header(wrap=NO %macro mcf_stpsrv_header(wrap=NO
,insert_cmplib=NO ,insert_cmplib=DEPRECATED
,lib=WORK ,lib=WORK
,cat=SASJS ,cat=SASJS
,pkg=UTILS ,pkg=UTILS
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local i var cmpval found;
%if %mcf_init(stpsrv_header)=1 %then %return; %if %mcf_init(stpsrv_header)=1 %then %return;
%if &wrap=YES %then %do; %if &wrap=YES %then %do;
@@ -96,7 +96,14 @@ endsub;
quit; quit;
%end; %end;
%if &insert_cmplib=YES %then %do; /* insert the CMPLIB if not already there */
%let cmpval=%sysfunc(getoption(cmplib));
%let found=0;
%do i=1 %to %sysfunc(countw(&cmpval,%str( %(%))));
%let var=%scan(&cmpval,&i,%str( %(%)));
%if &var=&lib..&cat %then %let found=1;
%end;
%if &found=0 %then %do;
options insert=(CMPLIB=(&lib..&cat)); options insert=(CMPLIB=(&lib..&cat));
%end; %end;

View File

@@ -32,12 +32,12 @@
run; run;
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
@param [out] insert_cmplib= (NO) Choose YES to insert the package into the
CMPLIB reference.
@param [out] lib= (work) The output library in which to create the catalog. @param [out] lib= (work) The output library in which to create the catalog.
@param [out] cat= (sasjs) The output catalog in which to create the package. @param [out] cat= (sasjs) The output catalog in which to create the package.
@param [out] pkg= (utils) The output package in which to create the function. @param [out] pkg= (utils) The output package in which to create the function.
Uses a 3 part format: libref.catalog.package Uses a 3 part format: libref.catalog.package
@param [out] insert_cmplib= DEPRECATED - The CMPLIB option is checked and
values inserted only if needed.
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_init.sas @li mcf_init.sas
@@ -49,12 +49,12 @@
**/ **/
%macro mcf_string2file(wrap=NO %macro mcf_string2file(wrap=NO
,insert_cmplib=NO ,insert_cmplib=DEPRECATED
,lib=WORK ,lib=WORK
,cat=SASJS ,cat=SASJS
,pkg=UTILS ,pkg=UTILS
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local i var cmpval found;
%if %mcf_init(mcf_string2file)=1 %then %return; %if %mcf_init(mcf_string2file)=1 %then %return;
%if &wrap=YES %then %do; %if &wrap=YES %then %do;
@@ -81,7 +81,14 @@ endsub;
quit; quit;
%end; %end;
%if &insert_cmplib=YES %then %do; /* insert the CMPLIB if not already there */
%let cmpval=%sysfunc(getoption(cmplib));
%let found=0;
%do i=1 %to %sysfunc(countw(&cmpval,%str( %(%))));
%let var=%scan(&cmpval,&i,%str( %(%)));
%if &var=&lib..&cat %then %let found=1;
%end;
%if &found=0 %then %do;
options insert=(CMPLIB=(&lib..&cat)); options insert=(CMPLIB=(&lib..&cat));
%end; %end;

View File

@@ -93,4 +93,74 @@ run;
iftrue=("&test3b"="PASS"), iftrue=("&test3b"="PASS"),
desc=Checking data row Test 3, desc=Checking data row Test 3,
outds=work.test_results outds=work.test_results
) )
/* test 4 - sasjs with compare */
filename example temp;
%mp_ds2csv(sashelp.air,outref=example,headerformat=SASJS)
data _null_; infile example; input;put _infile_; if _n_>5 then stop;run;
data _null_;
infile example;
input;
call symputx('stmnt',_infile_);
stop;
run;
data work.want;
infile example dsd firstobs=2;
input &stmnt;
run;
%mp_assert(
iftrue=(&syscc =0),
desc=Checking syscc prior to compare of sashelp.air,
outds=work.test_results
)
proc compare base=want compare=sashelp.air;
run;
%mp_assert(
iftrue=(&sysinfo le 41),
desc=Checking compare of sashelp.air,
outds=work.test_results
)
/* test 5 - sasjs with time/datetime/date */
filename f2 temp;
data work.test5;
do x=1 to 5;
y=x;
z=x;
end;
format x date9. y datetime19. z time.;
run;
%mp_ds2csv(work.test5,outref=f2,headerformat=SASJS)
data _null_; infile example; input;put _infile_; if _n_>5 then stop;run;
data _null_;
infile f2;
input;
putlog _infile_;
call symputx('stmnt2',_infile_);
stop;
run;
data work.want5;
infile f2 dsd firstobs=2;
input &stmnt2;
putlog _infile_;
run;
%mp_assert(
iftrue=(&syscc=0),
desc=Checking syscc prior to compare of test5,
outds=work.test_results
)
proc compare base=want5 compare=work.test5;
run;
%mp_assert(
iftrue=(&sysinfo le 41),
desc=Checking compare of work.test5,
outds=work.test_results
)