Ошибка SAS MACRO: вложение операторов% IF в открытый код не поддерживается. % IF игнорируется - PullRequest
0 голосов
/ 06 ноября 2019

Когда я выполняю этот код, возникает ошибка: Вложение операторов% IF в открытый код не поддерживается. % IF игнорируется. Код выглядит следующим образом:

%let Vis_Perform_Filter = VISYN^=:"Y";
data cp_ref_patient_visits;
    length CP_VISIT_PERFORMED 8.;
    set cp_ref_patient_visits;

    /* Are all visit identifiers related to actual performed visits? */
    /* if select 'Yes' */
    %IF %superQ(Vis_Perform_Filter) eq %THEN %DO;
      CP_VISIT_PERFORMED = 1; /* 1 OR 0 */
    %END;
    /* if select 'No' then apply filter condition */
    %ELSE %IF %superQ(Vis_Perform_Filter) ne %THEN %DO;
      if &Vis_Perform_Filter. then CP_VISIT_PERFORMED = 0;
      else CP_VISIT_PERFORMED = 1;
    %END;

    label CP_VISIT_ID = "Internal Visit Identifier"
          CP_VISIT_PERFORMED = "Visit Performed Flag";

    proc sort; by SUBJID CP_PATIENT CP_VISIT_ID;
run;

И ошибка:

31 %ELSE %IF %superQ(Vis_Perform_Filter) ne %THEN %DO;
ERROR: Nesting of %IF statements in open code is not supported. %IF ignored.
ERROR: Skipping to next %END statement.

Я хочу знать, почему возникает эта ошибка? Как решить эту ошибку? Спасибо за вашу помощь ~

Ответы [ 3 ]

1 голос
/ 06 ноября 2019

Как в этом блоге раскрывается

% if%, тогда операторы% else не поддерживаются в открытом коде до SAS 9.4M5. И есть ограничения на его использование.

Я предлагаю избавиться от макрофункций, когда вы находитесь внутри шага данных. Например, замените

%IF %superQ(Vis_Perform_Filter) eq %THEN %DO;
  CP_VISIT_PERFORMED = 1; /* 1 OR 0 */
%END;

на

if VISYN ne "Y" then CP_VISIT_PERFORMED = 1;
0 голосов
/ 06 ноября 2019

Вам, вероятно, следует переместить свою логику относительно значения макропеременной за пределы логики шага данных, чтобы прояснить ситуацию. Похоже, что когда переменная макроса пуста, вы хотите выполнить предложение ELSE оператора IF. Так что просто установите значение, равное false.

%let Vis_Perform_Filter = VISYN^=:"Y";
%IF %superQ(Vis_Perform_Filter) eq %THEN %DO;
  %let Vis_Perform_Filter=0;
%END;

Тогда для генерации кода шага данных не требуется никакой макропрограммы, а тем более вложенной макропрограммы. Вы просто расширяете значение макропеременной, где оператор IF ожидает, что код будет использоваться для оценки условия.

data cp_ref_patient_visits;
    length CP_VISIT_PERFORMED 8.;
    set cp_ref_patient_visits;

    /* Are all visit identifiers related to actual performed visits? */
    if &Vis_Perform_Filter. then CP_VISIT_PERFORMED = 0;
    else CP_VISIT_PERFORMED = 1;

    label CP_VISIT_ID = "Internal Visit Identifier"
          CP_VISIT_PERFORMED = "Visit Performed Flag"
    ;
run;

proc sort; by SUBJID CP_PATIENT CP_VISIT_ID;
run;
0 голосов
/ 06 ноября 2019

Если у вас есть много фильтров, которые указаны как «фрагменты исходного кода шага данных» в возможных макропеременных, вы можете закодировать отдельный макрос (CODEGEN_flag_logic), чтобы проверить фильтры по имени и определить, стоит лиэтот исходный код должен быть передан как часть шага данных.

Пример:

%MACRO CODEGEN_flag_logic (FILTER, DEFAULT=1);
  %* FILTER is name of macro variable containing source code that is data step logical evaluation snippet;
  %if %length(&FILTER) %then 
    %if %symexist (&FILTER) %then 
      %if %length (&&&FILTER) %then
&&&FILTER;
          %else
&DEFAULT;
        %else
&DEFAULT;
      %else
&DEFAULT;
%MEND;

%let name_flag_logic = name =: "J";  /* extant source code */

data want;
  set sashelp.class;

  name_flag = %codegen_flag_logic (name_flag_logic);
  name_flag_inverse = %codegen_flag_logic (name_flag_logic, DEFAULT=0);
run;

%let name_flag_logic = ;  /* extant macro variable with no source code */

data want;
  set sashelp.class;

  name_flag = %codegen_flag_logic (name_flag_logic);
run;

%SYMDEL name_flag_logic;  /* macro variable not present in session or scope */

data want;
  set sashelp.class;

  name_flag = %codegen_flag_logic (name_flag_logic);
run;

Все еще будут проблемы, если указанные фильтры содержат недопустимый код SAS или имеют дело с переменными, ожидаемыми в PDVчто нет.

Например,

/* snippet uses homeroom (which will be noted in LOG as uninitialized */
%let name_flag_logic = homeroom = 'sunny'; 

/* snippet is invalid sas code and will show ERROR in the LOG */
%let name_flag_logic = busroute one of (1,2,3); 
...