BookmarkSubscribeRSS Feed
saspert
Pyrite | Level 9

Hi,

I am having issues with a rather complex SAS code. The SAS macro create_page generates code in Javascript which is then run by the stored process facility using the _webout option. The SAS code works fine for most data values but seems to trip up for data values which have special characters. The original SAS code is here -

put '<tr><td><b>Population:</b></td>';
put '<td>';
put '<select name="POPULATION">'; 
%let i = 1;
put "<option value='(none)'>Select One</option>";
%if %symexist(POPULATION_LIST) %then %do;
%do %while(%qscan(&POPULATION_LIST,&i,-) ne);
%let n&i = %scan(&POPULATION_LIST,&i,-);
%if %str(&&n&i)= %str(&POPULATION) %then %do;
put %unquote(%str(%'<option value="&&n&i" selected>&&n&i</option>%'));
  %end;
      %else %do;
       put %unquote(%str(%'<option value="&&n&i">&&n&i</option>%'));
     %end;

%let i = %eval(&i+1);
%end;
%end;
put '</SELECT>';
put '</td></tr>';

The java script being created is here -

</SELECT></td></tr><tr><td><b>Population:</b></td><td><select name="POPULATION"><option value='(none)'>Select One</option>

   </SELECT></td></tr>

Depending on the number of records extracted from the database, the list of values for this javascript drop down keep increasing. For some values which have special characters the process is breaking though.

MPRINT(CREATE_PAGE):   put '</SELECT>';
MPRINT(CREATE_PAGE):   put '</td></tr>';
MPRINT(CREATE_PAGE):   put '<tr><td><b>Population:</b></td>';
MPRINT(CREATE_PAGE):   put '<td>';
MPRINT(CREATE_PAGE):   put '<select name="POPULATION">';
MPRINT(CREATE_PAGE):   put "<option value='(none)'>Select One</option>";
SYMBOLGEN:  Macro variable POPULATION_LIST resolves to Boeing All Others-Boeing ForAsgmt (exPat)-Boeing ForAsgmt SP/DP (exPat)-Boeing ILHE-Boeing USA EE-Boeing USA SP/DP
SYMBOLGEN:  Macro variable I resolves to 1
SYMBOLGEN:  Macro variable I resolves to 1
SYMBOLGEN:  Macro variable POPULATION_LIST resolves to Boeing All Others-Boeing ForAsgmt (exPat)-Boeing ForAsgmt SP/DP (exPat)-Boeing ILHE-Boeing USA EE-Boeing USA SP/DP
SYMBOLGEN:  Macro variable I resolves to 1
SYMBOLGEN:  && resolves to &.
SYMBOLGEN:  Macro variable I resolves to 1
SYMBOLGEN:  Macro variable N1 resolves to Boeing All Others
SYMBOLGEN:  Macro variable POPULATION resolves to (none)
SYMBOLGEN:  && resolves to &.
SYMBOLGEN:  Macro variable I resolves to 1
SYMBOLGEN:  Macro variable N1 resolves to Boeing All Others
SYMBOLGEN:  && resolves to &.
SYMBOLGEN:  Macro variable I resolves to 1
SYMBOLGEN:  Macro variable N1 resolves to Boeing All Others
MPRINT(CREATE_PAGE):   put '<option value="Boeing All Others">Boeing All Others</option>';
SYMBOLGEN:  Macro variable I resolves to 1
SYMBOLGEN:  Macro variable POPULATION_LIST resolves to Boeing All Others-Boeing ForAsgmt (exPat)-Boeing ForAsgmt SP/DP (exPat)-Boeing ILHE-Boeing USA EE-Boeing USA SP/DP
SYMBOLGEN:  Macro variable I resolves to 2
SYMBOLGEN:  Macro variable I resolves to 2
SYMBOLGEN:  Macro variable POPULATION_LIST resolves to Boeing All Others-Boeing ForAsgmt (exPat)-Boeing ForAsgmt SP/DP (exPat)-Boeing ILHE-Boeing USA EE-Boeing USA SP/DP
SYMBOLGEN:  Macro variable I resolves to 2
SYMBOLGEN:  && resolves to &.
SYMBOLGEN:  Macro variable I resolves to 2
                                                                                          The SAS System

SYMBOLGEN:  Macro variable N2 resolves to Boeing ForAsgmt (exPat)
ERROR: Required operator not found in expression: &&n&i= &POPULATION
SYMBOLGEN:  Macro variable POPULATION resolves to (none)
ERROR: The macro CREATE_PAGE will stop executing.

The original piece of code is using the %str function to mask the () characters. So, my question is what am I missing here? Or what I should try to ensure that piece of macro logic works regardless of database values?

This is a production issue which means a few sleepless nights for me. Any help will be appreciated.

Thanks,

saspert

3 REPLIES 3
chang_y_chung_hotmail_com
Obsidian | Level 7

It gets easier if you separate out the macro part from the non-macro part. Here is one way.

   %*-- args pass by names, not by values --*;
   %macro options(_list=, _pop=);
      %if ^%symexist(&_list) %then %return;

      %local i value qvalue dash selected pop;
      %let pop = %qsysfunc(strip(%superq(&_pop)));
      %let dash = %str(-);

      %let i = 1;
      %let value = %qsysfunc(strip(%qscan(%superq(&_list), &i, &dash)));
      %do %while (&value^=);
         %if &value = &pop %then %let selected = selected;
         %else %let selected =;
         %let value = %qsysfunc(htmlencode(&value));
         %let qvalue = %qsysfunc(quote(&value));

         %*;%unquote(
            put "<option value="&qvalue" &selected>&value</option>";
         )

         %let i = %eval(&i + 1);
         %let value = %qsysfunc(strip(%qscan(%superq(&_list), &i, &dash)));
      %end;
   %mend  options;


   %*-- check --*;
   %let population_list = Boeing All Others-
      Boeing ForAsgmt (exPat)-Boeing ForAsgmt SP/DP (exPat)
      -Boeing ILHE-Boeing USA EE-Boeing USA SP/DP;
   %let population = Boeing ILHE;

   data _null_;
      put '<tr><th>Population:</th>';
      put '<td><select name="population">';
      put '<option value="(none)">Select One</option>';

      %options(_list=population_list, _pop=population)

      put '</select></td>';
      put '</tr>';
   run;
   %*-- on log
   <tr><th>Population:</th>
   <td><select name="population">
   <option value="(none)">Select One</option>
   <option value="Boeing All Others" >Boeing All Others</option>
   <option value="Boeing ForAsgmt (exPat)" >Boeing ForAsgmt (exPat)</option>
   <option value="Boeing ForAsgmt SP/DP (exPat)" >Boeing ForAsgmt SP/DP (exPat)</option>
   <option value="Boeing ILHE" selected>Boeing ILHE</option>
   <option value="Boeing USA EE" >Boeing USA EE</option>
   <option value="Boeing USA SP/DP" >Boeing USA SP/DP</option>
   </select></td>
   </tr>
   --*;

saspert
Pyrite | Level 9

Hi,

Appreciate your solution to decode. Since I was short on time, I tried a couple of alternative macro qoutation functions and %bquote seem to work. So I replaced %str (in red above in my code) to %bquote and it seemed to work for now.

I do want to spend some time on your code and understand your logic. It seems impressive to go through the code and split out the required javascript from that.

Regards,

saspert.

Tom
Super User Tom
Super User

Why are you processing the text with macro logic instead of using DATA step statements instead? You will not have any macro quoting issues then.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 1451 views
  • 3 likes
  • 3 in conversation