diff --git a/base/mf_getfmtlist.sas b/base/mf_getfmtlist.sas
new file mode 100644
index 0000000..1aac14b
--- /dev/null
+++ b/base/mf_getfmtlist.sas
@@ -0,0 +1,61 @@
+/**
+ @file
+ @brief Returns a distinct list of formats from a table
+ @details Reads the dataset header and returns a distinct list of formats
+ applied.
+
+ %put NOTE- %mf_getfmtlist(sashelp.prdsale);
+ %put NOTE- %mf_getfmtlist(sashelp.shoes);
+ %put NOTE- %mf_getfmtlist(sashelp.demographics);
+
+ returns:
+
+ > DOLLAR $CHAR W MONNAME
+ > $CHAR BEST DOLLAR
+ > BEST Z $CHAR COMMA PERCENTN
+
+
+ @param [in] libds Two part library.dataset reference.
+
+
SAS Macros
+ @li mf_getfmtname.sas
+
+ @version 9.2
+ @author Allan Bowe
+
+**/
+
+%macro mf_getfmtlist(libds
+)/*/STORE SOURCE*/;
+/* declare local vars */
+%local out dsid nvars x rc fmt;
+
+/* open dataset in macro */
+%let dsid=%sysfunc(open(&libds));
+
+/* continue if dataset exists */
+%if &dsid %then %do;
+ /* loop each variable in the dataset */
+ %let nvars=%sysfunc(attrn(&dsid,NVARS));
+ %do x=1 %to &nvars;
+ /* grab format and check it exists */
+ %let fmt=%sysfunc(varfmt(&dsid,&x));
+ %if %quote(&fmt) ne %quote() %then %let fmt=%mf_getfmtname(&fmt);
+ %else %do;
+ /* assign default format depending on variable type */
+ %if %sysfunc(vartype(&dsid, &x))=C %then %let fmt=$CHAR;
+ %else %let fmt=BEST;
+ %end;
+ /* concatenate unique list of formats */
+ %if %sysfunc(indexw(&out,&fmt,%str( )))=0 %then %let out=&out &fmt;
+ %end;
+ %let rc=%sysfunc(close(&dsid));
+%end;
+%else %do;
+ %put &sysmacroname: Unable to open &libds (rc=&dsid);
+ %put &sysmacroname: SYSMSG= %sysfunc(sysmsg());
+ %let rc=%sysfunc(close(&dsid));
+%end;
+/* send them out without spaces or quote markers */
+%do;%unquote(&out)%end;
+%mend mf_getfmtlist;
\ No newline at end of file
diff --git a/base/mf_getfmtname.sas b/base/mf_getfmtname.sas
new file mode 100644
index 0000000..8ad3761
--- /dev/null
+++ b/base/mf_getfmtname.sas
@@ -0,0 +1,44 @@
+/**
+ @file
+ @brief Extracts a format name from a fully defined format
+ @details Converts formats in like $thi3. and th13.2 $THI and TH.
+ Usage:
+
+ %put %mf_getfmtname(8.);
+ %put %mf_getfmtname($4.);
+ %put %mf_getfmtname(comma14.10);
+
+ Returns:
+
+ > W
+ > $CHAR
+ > COMMA
+
+ Note that system defaults are inferred from the values provided.
+
+ @param [in] fmt The fully defined format. If left blank, nothing is returned.
+
+ @returns The name (without width or decimal) of the format.
+
+ @version 9.2
+ @author Allan Bowe
+
+**/
+
+%macro mf_getfmtname(fmt
+)/*/STORE SOURCE*/ /minoperator mindelimiter=' ';
+
+%local out dsid nvars x rc fmt;
+
+/* extract actual format name from the format definition */
+%let fmt=%scan(&fmt,1,.);
+%do %while(%substr(&fmt,%length(&fmt),1) in 1 2 3 4 5 6 7 8 9 0);
+ %if %length(&fmt)=1 %then %let fmt=W;
+ %else %let fmt=%substr(&fmt,1,%length(&fmt)-1);
+%end;
+
+%if &fmt=$ %then %let fmt=$CHAR;
+
+/* send them out without spaces or quote markers */
+%do;%unquote(%upcase(&fmt))%end;
+%mend mf_getfmtname;
\ No newline at end of file
diff --git a/base/mp_init.sas b/base/mp_init.sas
index 25471c3..ab51148 100644
--- a/base/mp_init.sas
+++ b/base/mp_init.sas
@@ -34,15 +34,17 @@
)/*/STORE SOURCE*/;
%global
- &prefix._INIT_NUM /* initialisation time as numeric */
- &prefix._INIT_DTTM /* initialisation time in E8601DT26.6 format */
+ &prefix._INIT_NUM /* initialisation time as numeric */
+ &prefix._INIT_DTTM /* initialisation time in E8601DT26.6 format */
+ &prefix.WORK /* avoid typing %sysfunc(pathname(work)) every time */
;
%if %eval(&&&prefix._INIT_NUM>0) %then %return; /* only run once */
data _null_;
dttm=datetime();
- call symputx("&prefix._init_num",dttm);
- call symputx("&prefix._init_dttm",put(dttm,E8601DT26.6));
+ call symputx("&prefix._init_num",dttm,'g');
+ call symputx("&prefix._init_dttm",put(dttm,E8601DT26.6),'g');
+ call symputx("&prefix.work",pathname('WORK'),'g');
run;
options
@@ -56,7 +58,7 @@
noquotelenmax /* avoid warnings for long strings */
noreplace /* avoid overwriting permanent datasets */
ps=max /* reduce log size slightly */
- ls=max /* reduce log a bit more, + avoid word truncation */
+ ls=max /* reduce log even more and avoid word truncation */
validmemname=COMPATIBLE /* avoid special characters etc in table names */
validvarname=V7 /* avoid special characters etc in variable names */
varinitchk=%str(ERR)OR /* avoid data mistakes from variable name typos */
diff --git a/tests/crossplatform/mf_getfmtlist.test.sas b/tests/crossplatform/mf_getfmtlist.test.sas
new file mode 100644
index 0000000..d0b19e8
--- /dev/null
+++ b/tests/crossplatform/mf_getfmtlist.test.sas
@@ -0,0 +1,33 @@
+/**
+ @file
+ @brief Testing mf_getfmtlist macro
+
+ SAS Macros
+ @li mf_getfmtlist.sas
+ @li mp_assert.sas
+
+**/
+
+%mp_assert(
+ iftrue=(
+ "%mf_getfmtlist(sashelp.prdsale)"="DOLLAR $CHAR W MONNAME"
+ ),
+ desc=Checking basic numeric,
+ outds=work.test_results
+)
+
+%mp_assert(
+ iftrue=(
+ "%mf_getfmtlist(sashelp.shoes)"="$CHAR BEST DOLLAR"
+ ),
+ desc=Checking basic char,
+ outds=work.test_results
+)
+
+%mp_assert(
+ iftrue=(
+ "%mf_getfmtlist(sashelp.demographics)"="BEST Z $CHAR COMMA PERCENTN"
+ ),
+ desc=Checking longer numeric,
+ outds=work.test_results
+)
\ No newline at end of file
diff --git a/tests/crossplatform/mf_getfmtname.test.sas b/tests/crossplatform/mf_getfmtname.test.sas
new file mode 100644
index 0000000..da37b05
--- /dev/null
+++ b/tests/crossplatform/mf_getfmtname.test.sas
@@ -0,0 +1,33 @@
+/**
+ @file
+ @brief Testing mf_getfmtname macro
+
+ SAS Macros
+ @li mf_getfmtname.sas
+ @li mp_assert.sas
+
+**/
+
+%mp_assert(
+ iftrue=(
+ "%mf_getfmtname(8.)"="W"
+ ),
+ desc=Checking basic numeric,
+ outds=work.test_results
+)
+
+%mp_assert(
+ iftrue=(
+ "%mf_getfmtname($4.)"="$CHAR"
+ ),
+ desc=Checking basic char,
+ outds=work.test_results
+)
+
+%mp_assert(
+ iftrue=(
+ "%mf_getfmtname(comma14.10)"="COMMA"
+ ),
+ desc=Checking longer numeric,
+ outds=work.test_results
+)
\ No newline at end of file