diff --git a/all.sas b/all.sas
index 6600af6..3cff281 100644
--- a/all.sas
+++ b/all.sas
@@ -3315,12 +3315,21 @@ run;
@file
@brief Create a CARDS file from a SAS dataset.
@details Uses dataset attributes to convert all data into datalines.
- Running the generated file will rebuild the original dataset.
+ Running the generated file will rebuild the original dataset. Includes
+ support for large decimals, binary data, PROCESSED_DTTM columns, and
+ alternative encoding. If the input dataset is empty, the cards file will
+ still be created.
+
+ Additional support to generate a random sample and max rows.
+
Usage:
%mp_ds2cards(base_ds=sashelp.class
+ , tgt_ds=work.class
, cards_file= "C:\temp\class.sas"
- , maxobs=5)
+ , showlog=NO
+ , maxobs=5
+ )
TODO:
- labelling the dataset
@@ -3331,15 +3340,24 @@ run;
that is converted to a cards file.
@param [in] tgt_ds= Table that the generated cards file would create.
Optional - if omitted, will be same as BASE_DS.
- @param [out] cards_file= Location in which to write the (.sas) cards file
- @param [in] maxobs= to limit output to the first maxobs
- observations
- @param [in] showlog= whether to show generated cards file in the SAS log
- (YES/NO)
- @param [in] outencoding= provide encoding value for file statement (eg utf-8)
- @param [in] append= If NO then will rebuild the cards file if it already
+ @param [out] cards_file= ("%sysfunc(pathname(work))/cardgen.sas") Location in
+ which to write the (.sas) cards file
+ @param [in] maxobs= (max) To limit output to the first maxobs
+ observations, enter an integer here.
+ @param [in] random_sample= (NO) Set to YES to generate a random sample of
+ data. Can be quite slow.
+ @param [in] showlog= (YES) Whether to show generated cards file in the SAS
+ log. Valid values:
+ @li YES
+ @li NO
+ @param [in] outencoding= Provide encoding value for file statement (eg utf-8)
+ @param [in] append= (NO) If NO then will rebuild the cards file if it already
exists, otherwise will append to it. Used by the mp_lib2cards.sas macro.
+
Related Macros
+ @li mp_lib2cards.sas
+ @li mp_ds2inserts.sas
+ @li mp_mdtablewrite.sas
@version 9.2
@author Allan Bowe
@@ -3364,7 +3382,7 @@ run;
%if (&tgt_ds = ) %then %let tgt_ds=&base_ds;
%if %index(&tgt_ds,.)=0 %then %let tgt_ds=WORK.%scan(&base_ds,2,.);
%if ("&outencoding" ne "") %then %let outencoding=encoding="&outencoding";
-%if ("&append" = "") %then %let append=;
+%if ("&append" = "" or "&append" = "NO") %then %let append=;
%else %let append=mod;
/* get varcount */
@@ -3450,6 +3468,11 @@ data datalines_2;
,put(',name,',best32.-l)
,substrn(put(',name,',bestd32.-l),1
,findc(put(',name,',bestd32.-l),"0","TBK")))');
+ /**
+ * binary data must be converted, to store in text format. It is identified
+ * by the presence of the $HEX keyword in the format.
+ */
+ else if upcase(format)=:'$HEX' then dataline=cats('put(',name,',',format,')');
else dataline=name;
run;
@@ -3475,7 +3498,8 @@ data _null_;
/* Build input statement */
- if type='char' then type3=':$char.';
+ if upcase(format)=:'$HEX' then type3=':'!!format;
+ else if type='char' then type3=':$char.';
str2=put(name,$33.)||type3;
@@ -3529,7 +3553,7 @@ data _null_;
put "input ";
%do i = 1 %to &nvars.;
%if(%length(&&input_stmt_&i..)) %then
- put " &&input_stmt_&i..";
+ put " &&input_stmt_&i..";
;
%end;
put ";";
diff --git a/base/mp_ds2cards.sas b/base/mp_ds2cards.sas
index 8c78e83..3fc69c9 100644
--- a/base/mp_ds2cards.sas
+++ b/base/mp_ds2cards.sas
@@ -2,12 +2,21 @@
@file
@brief Create a CARDS file from a SAS dataset.
@details Uses dataset attributes to convert all data into datalines.
- Running the generated file will rebuild the original dataset.
+ Running the generated file will rebuild the original dataset. Includes
+ support for large decimals, binary data, PROCESSED_DTTM columns, and
+ alternative encoding. If the input dataset is empty, the cards file will
+ still be created.
+
+ Additional support to generate a random sample and max rows.
+
Usage:
%mp_ds2cards(base_ds=sashelp.class
+ , tgt_ds=work.class
, cards_file= "C:\temp\class.sas"
- , maxobs=5)
+ , showlog=NO
+ , maxobs=5
+ )
TODO:
- labelling the dataset
@@ -18,15 +27,24 @@
that is converted to a cards file.
@param [in] tgt_ds= Table that the generated cards file would create.
Optional - if omitted, will be same as BASE_DS.
- @param [out] cards_file= Location in which to write the (.sas) cards file
- @param [in] maxobs= to limit output to the first maxobs
- observations
- @param [in] showlog= whether to show generated cards file in the SAS log
- (YES/NO)
- @param [in] outencoding= provide encoding value for file statement (eg utf-8)
- @param [in] append= If NO then will rebuild the cards file if it already
+ @param [out] cards_file= ("%sysfunc(pathname(work))/cardgen.sas") Location in
+ which to write the (.sas) cards file
+ @param [in] maxobs= (max) To limit output to the first maxobs
+ observations, enter an integer here.
+ @param [in] random_sample= (NO) Set to YES to generate a random sample of
+ data. Can be quite slow.
+ @param [in] showlog= (YES) Whether to show generated cards file in the SAS
+ log. Valid values:
+ @li YES
+ @li NO
+ @param [in] outencoding= Provide encoding value for file statement (eg utf-8)
+ @param [in] append= (NO) If NO then will rebuild the cards file if it already
exists, otherwise will append to it. Used by the mp_lib2cards.sas macro.
+ Related Macros
+ @li mp_lib2cards.sas
+ @li mp_ds2inserts.sas
+ @li mp_mdtablewrite.sas
@version 9.2
@author Allan Bowe
@@ -51,7 +69,7 @@
%if (&tgt_ds = ) %then %let tgt_ds=&base_ds;
%if %index(&tgt_ds,.)=0 %then %let tgt_ds=WORK.%scan(&base_ds,2,.);
%if ("&outencoding" ne "") %then %let outencoding=encoding="&outencoding";
-%if ("&append" = "") %then %let append=;
+%if ("&append" = "" or "&append" = "NO") %then %let append=;
%else %let append=mod;
/* get varcount */
@@ -137,6 +155,11 @@ data datalines_2;
,put(',name,',best32.-l)
,substrn(put(',name,',bestd32.-l),1
,findc(put(',name,',bestd32.-l),"0","TBK")))');
+ /**
+ * binary data must be converted, to store in text format. It is identified
+ * by the presence of the $HEX keyword in the format.
+ */
+ else if upcase(format)=:'$HEX' then dataline=cats('put(',name,',',format,')');
else dataline=name;
run;
@@ -162,7 +185,8 @@ data _null_;
/* Build input statement */
- if type='char' then type3=':$char.';
+ if upcase(format)=:'$HEX' then type3=':'!!format;
+ else if type='char' then type3=':$char.';
str2=put(name,$33.)||type3;
@@ -216,7 +240,7 @@ data _null_;
put "input ";
%do i = 1 %to &nvars.;
%if(%length(&&input_stmt_&i..)) %then
- put " &&input_stmt_&i..";
+ put " &&input_stmt_&i..";
;
%end;
put ";";
diff --git a/tests/crossplatform/mp_ds2cards.test.sas b/tests/crossplatform/mp_ds2cards.test.sas
new file mode 100644
index 0000000..2af7ede
--- /dev/null
+++ b/tests/crossplatform/mp_ds2cards.test.sas
@@ -0,0 +1,60 @@
+/**
+ @file
+ @brief Testing mp_ds2cards.sas macro
+
+ SAS Macros
+ @li mp_ds2cards.sas
+ @li mp_assert.sas
+
+**/
+
+/**
+ * test 1 - rebuild an existing dataset
+ * Cars is a great dataset - it contains leading spaces, and formatted numerics
+ */
+
+%mp_ds2cards(base_ds=sashelp.cars
+ , tgt_ds=work.test
+ , cards_file= "%sysfunc(pathname(work))/cars.sas"
+ , showlog=NO
+)
+%inc "%sysfunc(pathname(work))/cars.sas"/source2;
+
+proc compare base=sashelp.cars compare=work.test;
+quit;
+
+%mp_assert(
+ iftrue=(&sysinfo=1),
+ desc=sashelp.cars is identical except for ds label,
+ outds=work.test_results
+)
+
+/**
+ * test 2 - binary data compare
+ */
+data work.binarybase;
+ format bin $hex500. z $hex.;
+ do x=1 to 250;
+ z=byte(x);
+ bin=trim(bin)!!z;
+ output;
+ end;
+run;
+
+%mp_ds2cards(base_ds=work.binarybase
+ , showlog=YES
+ , cards_file="%sysfunc(pathname(work))/c2.sas"
+ , tgt_ds=work.binarycompare
+ , append=
+)
+
+%inc "%sysfunc(pathname(work))/c2.sas"/source2;
+
+proc compare base=work.binarybase compare=work.binarycompare;
+run;
+
+%mp_assert(
+ iftrue=(&sysinfo=1),
+ desc=work.binarybase dataset is identical except for ds label,
+ outds=work.test_results
+)
\ No newline at end of file