/*** HELP START ***//*
 
## >>> `%QgetVars()` macro: <<< <a name="qgetvars-macro"></a> #######################  

The getVars() and QgetVars() macro functions
allow to extract variables names form a dataset
according to a given pattern into a list.

The getVars() returns unquoted value [by %unquote()].
The QgetVars() returns quoted value [by %superq()].

The `%QgetVars()` macro executes like a pure macro code.

### SYNTAX: ###################################################################

The basic syntax is the following, the `<...>` means optional parameters:
~~~~~~~~~~~~~~~~~~~~~~~sas
%QgetVars(
   ds               
 <,sep=>
 <,pattern=>
 <,varRange=>
 <,quote=>
 <,ignoreCases=> 
)
~~~~~~~~~~~~~~~~~~~~~~~

**Arguments description**:

1. `ds`              - *Required*, the name of the dataset from 
                       which variables are to be taken.

* `sep = %str( )`    - *Optional*, default value `%str( )`, 
                       a variables separator on the created list. 

* `pattern = .*`     - *Optional*, default value `.*` (i.e. any text), 
                       a variable name regexp pattern, case INSENSITIVE! 

* `varRange = _all_` - *Optional*, default value `_all_`, 
                       a named range list of variables. 

* `quote =`          - *Optional*, default value is blank, a quotation 
                       symbol to be used around values.

* `ignoreCases=`     - *Optional*, default value is 1.  
                        Indicates if search should be case insensitive.

* `nlit=`            - *Optional*, default value is 0.
                        Introduced to improve `validvarname=ANY` handling.
                        Indicates if the `NLITERAL()` function should be 
                        executed to cover spacial characters.

*//*** HELP END ***/

%macro QgetVars(
  ds               
, sep = %str( )    
, pattern = .*     
, varRange = _all_ 
, quote = 
, ignoreCases = 1  
, nlit = 0         /* executes NLITERAL() function */
)
/des = 'The %getVars() and %QgetVars() macro functions allows to extract variables list from dataset.'
;
/*%local t;*/
/*%let t = %sysfunc(time());*/

  %local VarList di dx i VarName VarCnt;
  %let VarCnt = 0;
  %let ignoreCases = %sysevalf(1=%superq(ignoreCases));
  %if &ignoreCases. %then %let ignoreCases=i;
                    %else %let ignoreCases=;
  %let nlit = %sysevalf(not(0=%superq(nlit)));

  %let di = %sysfunc(open(&ds.(keep=&varRange.), IN)); /* open dataset with subset of variables */
  %let dx = %sysfunc(open(&ds.                 , IN)); /* open dataset with ALL variables */
  %if &di. > 0 %then 
    %do;
      %if ANY=%sysfunc(getoption(validvarname)) %then 
        %do;
          %put NOTE: [&sysmacroname.] Option VALIDVARNAME=ANY is not fully supported.;
          %if NOT (1=&nlit.) %then %put NOTE- Set the NLIT= parameter to 1, to improve the support.;  
        %end;
      %do i = 1 %to %sysfunc(attrn(&dx., NVARS)); /* iterate over ALL variables names */
        %let VarName = %qsysfunc(varname(&dx., &i.));

        %if %sysfunc(varnum(&di., &VarName.)) > 0 /* test if the variable is in the subset */
            AND
            %sysfunc(prxmatch(/%bquote(&pattern.)/&ignoreCases., &VarName.)) > 0 /* check the pattern */
        %then
          %do;
            %let VarCnt = %eval(&VarCnt. + 1);
            %if 1=&nlit. %then %let VarName = %qsysfunc(nliteral(&VarName.));
            %local VarList&VarCnt.; 
              %let VarList&VarCnt. = %nrbquote(&quote.)%superq(VarName)%nrbquote(&quote.);
            /*
            %if %bquote(&VarList.) = %then 
              %let VarList = %nrbquote(&quote.)&VarName.%nrbquote(&quote.);
            %else 
              %let VarList = &VarList.%nrbquote(&sep.)%nrbquote(&quote.)&VarName.%nrbquote(&quote.);
            */ 
          %end;
      %end; 
    %end;
  %else
    %do;
      %put WARNING: [&sysmacroname.] Cannot open data set %superq(ds)!;
      %put %superq(openMsg);
    %end;
  %let di = %sysfunc(close(&di.));
  %let dx = %sysfunc(close(&dx.));
/*%put (%sysevalf(%sysfunc(time()) - &t.));*/
%do i = 1 %to &VarCnt.;%superq(VarList&i.)%if &i. NE &VarCnt. %then %do;%superq(sep)%end;%end;
%mend QgetVars;


/*** HELP START ***//*
 
### EXAMPLES AND USECASES: ####################################################

See examples in `%getVars()` help for the details.

---

*//*** HELP END ***/
 
/**###################################################################**/
/*                                                                     */
/*  Copyright Bartosz Jablonski, since 2020.                           */
/*                                                                     */
/*  Code is under the MIT license. If you want - you can use it.       */
/*  But it comes with absolutely no warranty whatsoever.               */
/*  If you cause any damage or something - it will be your own fault.  */
/*  You've been warned! You are using it on your own risk.             */
/*  However, if you decide to use it don't forget to mention author.   */
/*  Bartosz Jablonski (yabwon@gmail.com)                               */
/*                                                                     */
/**###################################################################**/
