diff --git a/README.md b/README.md index 59357b9..48a9756 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ This is a list of locations where the SAS Packages Framework is used: If you want to share that you are using the SPF let me know and I'll update the list. -If you find the SPF usefull **share info** about it or **give it a [star](https://github.com/yabwon/SAS_PACKAGES/stargazers)** so more people will know. +If you find the SPF useful **share info** about it or **give it a [star](https://github.com/yabwon/SAS_PACKAGES/stargazers)** so more people will know. --- @@ -146,7 +146,7 @@ SHA256 digest for macroArray: DF63B0E027827A82038F1C8422787A0BC569BA93104BA1778D [Documentation for macroArray](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/macroarray.md "Documentation for macroArray") -- **BasePlus**\[1.14\] adds a bunch of functionalities I am missing in BASE SAS, such as: +- **BasePlus**\[1.15\] adds a bunch of functionalities I am missing in BASE SAS, such as: ```sas call arrMissToRight(myArray); call arrFillMiss(17, myArray); @@ -164,7 +164,7 @@ format x bool.; %zipLibrary(sashelp,libOut=work) ``` -SHA256 digest for BasePlus: 12A9A2155D9C6F969DF0A66E3A18D0938B8194FA3AA9D70EDDE1CB71DEF9691E +SHA256 digest for BasePlus: 0331C673052D5221DA98C5CC93295634D8A0BC62C7D2FEF9D0D85B0B2DEDE4E9 [Documentation for BasePlus](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md "Documentation for BasePlus") diff --git a/packages/README.md b/packages/README.md index f66ea8e..ffd560f 100644 --- a/packages/README.md +++ b/packages/README.md @@ -90,7 +90,7 @@ SHA256 digest for macroArray: DF63B0E027827A82038F1C8422787A0BC569BA93104BA1778D --- -- **BasePlus**\[1.14\] adds a bunch of functionalities I am missing in BASE SAS, such as: +- **BasePlus**\[1.15\] adds a bunch of functionalities I am missing in BASE SAS, such as: ```sas call arrMissToRight(myArray); call arrFillMiss(17, myArray); @@ -108,7 +108,7 @@ format x bool.; %zipLibrary(sashelp,libOut=work) ``` -SHA256 digest for BasePlus: 12A9A2155D9C6F969DF0A66E3A18D0938B8194FA3AA9D70EDDE1CB71DEF9691E +SHA256 digest for BasePlus: 0331C673052D5221DA98C5CC93295634D8A0BC62C7D2FEF9D0D85B0B2DEDE4E9 [Documentation for BasePlus](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md "Documentation for BasePlus") diff --git a/packages/SHA256_for_packages.txt b/packages/SHA256_for_packages.txt index ad126d9..3e6c78f 100644 --- a/packages/SHA256_for_packages.txt +++ b/packages/SHA256_for_packages.txt @@ -1,3 +1,6 @@ +/* 20220508 */ +BasePlus: 0331C673052D5221DA98C5CC93295634D8A0BC62C7D2FEF9D0D85B0B2DEDE4E9 + /* 20220420 */ BasePlus: 12A9A2155D9C6F969DF0A66E3A18D0938B8194FA3AA9D70EDDE1CB71DEF9691E DFA: 6B3FB0B06B47A7EF1BB004B483B0F39B8F553F7F16D02A7E24CDE388BBA704EA diff --git a/packages/baseplus.md b/packages/baseplus.md index 6095908..3c24ca3 100644 --- a/packages/baseplus.md +++ b/packages/baseplus.md @@ -45,12 +45,17 @@ * [`%RainCloudPlot()` macro](#raincloudplot-macro) * [`%zipLibrary()` macro](#ziplibrary-macro) * [`%unzipLibrary()` macro](#unziplibrary-macro) + * [`%LDSN()` macro](#ldsn-macro) + * [`%LVarNm()` macro](#lvarnm-macro) + * [`%LVarNmLab()` macro](#lvarnmlab-macro) + + * [License](#license) --- -# The BasePlus package [ver. 1.14] ############################################### +# The BasePlus package [ver. 1.15] ############################################### The **BasePlus** package implements useful functions and functionalities I miss in the BASE SAS. @@ -67,7 +72,9 @@ Kudos to all who inspired me to generate this package: *Richard DeVenezia*, *Christian Graffeuille*, *Allan Bowe*, -*Anamaria Calai*. +*Anamaria Calai*, +*Michal Ludwicki*, +*Quentin McMullen*. --- @@ -187,7 +194,6 @@ Kudos to all who inspired me to generate this package: %rainCloudPlot(sashelp.cars,DriveTrain,Invoice) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -![Rain Cloud Plot](./baseplus_RainCloudPlot_Ex0_9.png) **Example 10**: Zip SAS library. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas @@ -196,64 +202,77 @@ Kudos to all who inspired me to generate this package: %unzipLibrary(%sysfunc(pathname(work)), zip=sashelp, mode=S, clean=1) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +**Example 11**: Long dataset names. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +data %LDSN( work. peanut butter & jelly time with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s (drop = sex rename=(name=first_name) where = (age in (12,13,14))) ); + set sashelp.class; +run; +proc print data = %LDSN( work. peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s ); +run; +data MyNextDataset; + set %LDSN( work. peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s ); + where age > 12; +run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- Package contains: -1. macro deduplistc -2. macro deduplistp -3. macro deduplists -4. macro deduplistx -5. macro functionexists -6. macro getvars -7. macro qdeduplistx -8. macro qgetvars -9. macro qzipevalf -10. macro raincloudplot -11. macro symdelglobal -12. macro unziplibrary -13. macro zipevalf -14. macro ziplibrary -15. format bool -16. format boolz -17. format ceil -18. format floor -19. format int -20. function arrfill -21. function arrfillc -22. function arrmissfill -23. function arrmissfillc -24. function arrmisstoleft -25. function arrmisstoleftc -26. function arrmisstoright -27. function arrmisstorightc -28. function bracketsc -29. function bracketsn -30. function catxfc -31. function catxfi -32. function catxfj -33. function catxfn -34. function deldataset -35. function semicolonc -36. function semicolonn -37. format brackets -38. format semicolon -39. proto qsortincbyprocproto -40. function frommissingtonumberbs -41. function fromnumbertomissing -42. function quicksort4notmiss -43. function quicksorthash -44. function quicksorthashsddv -45. function quicksortlight - - +1. macro deduplistc +2. macro deduplistp +3. macro deduplists +4. macro deduplistx +5. macro functionexists +6. macro getvars +7. macro ldsn +8. macro lvarnm +9. macro lvarnmlab +10. macro qdeduplistx +11. macro qgetvars +12. macro qzipevalf +13. macro raincloudplot +14. macro symdelglobal +15. macro unziplibrary +16. macro zipevalf +17. macro ziplibrary +18. format bool +19. format boolz +20. format ceil +21. format floor +22. format int +23. functions arrfill +24. functions arrfillc +25. functions arrmissfill +26. functions arrmissfillc +27. functions arrmisstoleft +28. functions arrmisstoleftc +29. functions arrmisstoright +30. functions arrmisstorightc +31. functions bracketsc +32. functions bracketsn +33. functions catxfc +34. functions catxfi +35. functions catxfj +36. functions catxfn +37. functions deldataset +38. functions semicolonc +39. functions semicolonn +40. format brackets +41. format semicolon +42. proto qsortincbyprocproto +43. functions frommissingtonumberbs +44. functions fromnumbertomissing +45. functions quicksort4notmiss +46. functions quicksorthash +47. functions quicksorthashsddv +48. functions quicksortlight *SAS package generated by generatePackage, version 20220420* The SHA256 hash digest for package BasePlus: -`12A9A2155D9C6F969DF0A66E3A18D0938B8194FA3AA9D70EDDE1CB71DEF9691E` +`0331C673052D5221DA98C5CC93295634D8A0BC62C7D2FEF9D0D85B0B2DEDE4E9` --- # Content description ############################################################################################ @@ -3497,6 +3516,286 @@ run; --- +## >>> `%LDSN()` macro: <<< ####################### + +The LDSN (Long DataSet Names) macro function +allows to use an "arbitrary" text string to name a dataset. + +--- + +The idea for the macro came from the following story: + +Good friend of mine, who didn't use SAS for quite some time, +told me that he lost a few hours for debugging because +he forgot that the SAS dataset name limitation is 32 bytes. + +I replied that it shouldn't be a problem to do a workaround +for this inconvenience with a macro and the `MD5()` hashing function. + +I said: *The macro should take an "arbitrary string" for a dataset +name, convert it, with help of `MD5()`, to a hash digest, and +create a dataset with an "artificial" `hex16.` formated name.* + +Starting with something like this: + +~~~~~~~~~~~~~~~~~~~~~~~sas +data %LDSN(work. peanut butter & jelly with a hot-dog in [a box] and s*t*a*r*s (drop = sex rename=(name=first_name) where = (age in (12,13,14))) ); + set sashelp.class; +run; +~~~~~~~~~~~~~~~~~~~~~~~ + +the macro would do: + +~~~~~~~~~~~~~~~~~~~~~~~sas +%sysfunc(MD5(peanut butter & jelly with a hot-dog in [a box] and s*t*a*r*s), hex16.) +~~~~~~~~~~~~~~~~~~~~~~~ + +and (under the hood) return and execute the following code: + +~~~~~~~~~~~~~~~~~~~~~~~sas +data work.DSN_41D599EF51FBA58_(drop = sex rename=(name=first_name) where = (age in (12,13,14))) ; + set sashelp.class; +run; +~~~~~~~~~~~~~~~~~~~~~~~ + +Also in the next data step user should be able to do: + +~~~~~~~~~~~~~~~~~~~~~~~sas +data my_next_data_step; + set %DSN(work. peanut butter & jelly with a hot-dog in [a box] and s*t*a*r*s); +run; +~~~~~~~~~~~~~~~~~~~~~~~ + +and work without the "dataset-name-length-limitation" issue. + +--- + +See examples below for the details. + +The `%LDSN()` macro executes like a pure macro code. + +**Known "Limitations":** + +- dataset name _cannot_ contain dots (`.`) since they are used as separators! + +- dataset name _cannot_ contain round brackets(`(` and `)`) since they are used as separators + (but `[]` and `{}` are allowed)! + +- dataset name _cannot_ contain unpaired quotes (`'` and `"`), + text: `a "hot-dog"` is ok, but `John's dog` is not! + +**Behaviour:** + +- dataset name text is *converted to upcase* + +- dataset name text *leading and trailing spaces are ignored*, + e.g. the following will give the same hash digest: + `%ldsn(work.test)`, `%ldsn( work.test)`, `%ldsn(work.test )`, + `%ldsn(work .test)`, `%ldsn(work. test)`, `%ldsn(work . test)`. + +- if the user want to add an extra suffix to the dataset the `%ldsn()` macro + **has** to be wrapped inside the `%unquote()` macro function. +~~~~~~~~~~~~~~~~~~~~~~~sas +data + %unquote(%LDSN(WORK.some strange! DS name))_1 + %unquote(%LDSN(WORK.some strange! DS name))_2 +; + set sashelp.class; + + if SEX="M" then output %unquote(%LDSN(WORK.some strange! DS name))_1; + else output %unquote(%LDSN(WORK.some strange! DS name))_2; +run; +~~~~~~~~~~~~~~~~~~~~~~~ + The reason for this is a "bug" like behaviour of SAS tokenizer/macroprocesor. + See the following SAS-L discussion thread: + `https://listserv.uga.edu/scripts/wa-UGA.exe?A2=SAS-L;4b2bcf80.2205A&S=` + +- macro calls of the form: + `data %LDSN(); run;`, `data %LDSN( ); run;`, `data %LDSN( . ); run;` or even + `data %LDSN( . (keep=x)); run;` are resolved to empty string, so the result is + equivalent to `data; run;` + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%LDSN( + arbitrary text string (in line with limitations) +) +~~~~~~~~~~~~~~~~~~~~~~~ + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +options nomprint source nomlogic nosymbolgen ls = max ps = max; + +data %LDSN( work. peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s (drop = sex rename=(name=first_name) where = (age in (12,13,14))) ); + set sashelp.class; +run; + +proc print data = %LDSN( work. peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s ); +run; + +data MyNextDataset; + set %LDSN( work. peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s ); + where age > 12; +run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `%LVarNm()` macro: <<< ####################### + +The LVarNm() macro function works like the LDSN() macro function, but for variables. +Supported by LVarNmLab() macro function which allows to remember "user names" in labels. + +The motivation for the macro was similar one as for the LDSN() macro. + +--- + +See examples below for the details. + +The `%LVarNm()` macro executes like a pure macro code. + +**Known "Limitations":** + +- variable name _cannot_ contain unpaired quotes (`'` and `"`), + text: `a "hot-dog"` is ok, but `John's dog` is not! + +**Behaviour:** + +- variable name text is *converted to upcase* + +- variable name text *leading and trailing spaces are ignored*, + e.g. the following will give the same hash digest: + `%LVarNm(test)`, `%LVarNm( test)`, `%LVarNm(test )`. + +- if the user want to add an extra suffix to the variable, + e.g. to get a numerical suffix, the `%LVarNm()` macro + **has** to be wrapped inside the `%unquote()` macro function. +~~~~~~~~~~~~~~~~~~~~~~~sas +data test4; + array X[*] %unquote(%LVarNm(some strange! name))_0 - %unquote(%LVarNm(some strange! name))_10; + + do i = lbound(X) to hbound(X); + X[i] = 2**(i-1); + put X[i]=; + end; +run; +~~~~~~~~~~~~~~~~~~~~~~~ + The reason for this is a "bug" like behaviour of SAS tokenizer/macroprocesor. + See the following SAS-L discussion thread: + `https://listserv.uga.edu/scripts/wa-UGA.exe?A2=SAS-L;4b2bcf80.2205A&S=` + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%LVarNm( + arbitrary text string (in line with limitations) +) +~~~~~~~~~~~~~~~~~~~~~~~ + +--- + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +options ls=max; +data test; + %LVarNmLab( peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s ) + + do %LVarNm( peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s ) = 1 to 10; + + y = 5 + %LVarNm( peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s ) * 17; + output; + end; +run; + +data test2; + set test; + where %LVarNm( peanut butter & jelly with a "Hot-Dog" in [a box], popcorn, and s*t*a*r*s ) < 5; +run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +data test3; + %LVarNmLab() = 17; + + %LVarNm() = 17; + + %LVarNm( ) = 42; + + %LVarNm( ) = 303; +run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +data test3; + %LVarNm(test) = 1; + + %LVarNm( test) = 2; + + %LVarNm(test ) = 3; +run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +data test4; + array X[*] %unquote(%LVarNm(some strange! name))_0 - %unquote(%LVarNm(some strange! name))_10; + + do i = lbound(X) to hbound(X); + X[i] = 2**(i-1); + put X[i]=; + end; +run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## >>> `%LVarNmLab()` macro: <<< ####################### + +The LVarNmLab() macro function supports LVarNm() and allows to remember "user names" in labels. + +The motivation for the macro was similar one as for the LDSN() macro. + +--- + +See examples in LVarNm() documentation for the details. + +The `%LVarNmLab()` macro executes like a pure macro code. + +**Known "Limitations":** + +- variable name _cannot_ contain unpaired quotes (`'` and `"`), + text: `a "hot-dog"` is ok, but `John's dog` is not! + +**Behaviour:** + +- variable name text is *converted to upcase* + +- variable name text *leading and trailing spaces are ignored*, + e.g. the following will give the same hash digest: + `%LVarNmLab(test)`, `%LVarNmLab( test)`, `%LVarNmLab(test )`. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%LVarNmLab( + arbitrary text string (in line with limitations) +) +~~~~~~~~~~~~~~~~~~~~~~~ + +--- + ## License #################################################################### Copyright (c) 2020 Bartosz Jablonski diff --git a/packages/baseplus.zip b/packages/baseplus.zip index f8b7385..311f4f8 100644 Binary files a/packages/baseplus.zip and b/packages/baseplus.zip differ