SAS: Если условие не распознает макропеременную в datastep

#sas

Вопрос:

В приведенном ниже коде неверно оценивается оператор IF, отправляющий электронное письмо. Я не уверен, почему. Я попытался проверить наличие нуля, но это тоже не сработало. Это просто всегда отправляет первое действие в этом заявлении. В приведенной ниже инструкции ТАБЛИЦА 1 существует без записей, а ТАБЛИЦА 2 не существует. Я думаю, что это как-то связано с тем, что amp;CNT3 заполняется числом(*) в инструкции proc sql.

 %IF %SYSFUNC(exist(TABLE1)) %THEN %DO;

    PROC SQL;
        SELECT COUNT(*) INTO : CNT3 FROM TABLE1;
    QUIT;
    %END;
%ELSE %DO;

    %LET CNT3=0;
    %END;

    %put amp;cnt3.;

%IF %SYSFUNC(exist(TABLE2)) %THEN %DO;

    PROC SQL;
        SELECT COUNT(*) INTO : CNT4 FROM TABLE2;
    QUIT;
    %END;
%ELSE %DO;

    %LET CNT4=0;
    %END;
    %put amp;cnt4.;



%IF (amp;CNT3 ^=0 AND amp;CNT3^='0') %THEN %DO;

    PROC EXPORT DATA=TABLE1.
        DBMS=XLSX
        OUTFILE="data/REPORT1.xlsx"
        REPLACE;
        SHEET="TEST1";
    RUN;
%END;

%IF (amp;CNT4 ^=0 AND amp;CNT4^='0') %THEN %DO;

    PROC EXPORT DATA=amp;ENV..AUTH_ERRORLOG_amp;REC_DATE.
        DBMS=XLSX
        OUTFILE="data/REPORT1.xlsx"
        REPLACE;
        SHEET="TEST2";
    RUN;
%END;

%let EMAIL_SUBJECT = "TEST EMAIL.";

FILENAME OUTBOX EMAIL 'TEST@TEST.COM';

DATA _NULL_;
    IF (amp;CNT3 ^=0 AND amp;CNT3 ^='0') OR (amp;CNT4 ^=0 AND amp;CNT4^='0') THEN
        DO;
            FILE OUTBOX
                TO=('TEST@TEST.COM')
                SUBJECT= amp;EMAIL_SUBJECT.
                ATTACH=("/data/REPORT1.xlsx" CONTENT_TYPE="APPLICATION/XLSX");
            
        END;
        ELSE DO;

                FILE OUTBOX
                TO=('TEST@TEST.COM')
                SUBJECT= amp;EMAIL_SUBJECT.;
                PUT"NO ERRORS FOUND";
        END;
            

RUN;
 

Комментарии:

1. Вы включили symbolgen и mlogic ? Это значительно поможет в устранении неполадок.

2. Похоже, что amp;CNT3 принимает значение 0, но перед ним много пробелов. Я попытался подровнять его, но, похоже, это ничего не изменило.

3. Если вы не хотите, чтобы PROC SQL включал пробелы в созданные макропеременные, используйте ключевое слово TRIMMED. ... into :cnt3 trimmed ...

4. Этот код отлично работает для меня, когда я использую его как есть без изменений (кроме создания таблицы 1 с 0 записями), поэтому вы предоставляете недостаточно информации, чтобы ответить на вопрос.

Ответ №1:

Здесь может происходить множество вещей, поэтому давайте попробуем немного прояснить это, чтобы посмотреть, решит ли это ваши проблемы.

Во-первых, давайте возьмем количество наблюдений из метаданных интересующих таблиц вместо подсчета всех наблюдений. Это отличный воспроизводимый макрос, который я настоятельно рекомендую сохранить в качестве всегда доступного sasauto:

 %macro nobs(data);
    %local dsid nobs rc;

    %let nobs = -1;

    %if(%sysfunc(exist(amp;data.)) ) %then %do;

        %let dsid = %sysfunc(open(amp;data.));
        %let nobs = %sysfunc(attrn(amp;dsid., nlobs));
        %let rc   = %sysfunc(close(amp;dsid.));
    %end;

    amp;nobs.
%mend;
 

Это будет действовать как функция и возвращать количество наблюдений для таблицы SAS. Если он не существует, он возвращает -1. Например:

 %put The number of obs in sashelp.cars is %nobs(sashelp.cars);
%put The number of obs in a non-existent table is %nobs(doesntexist);
 

Выход:

 The number of obs in sashelp.cars is 428
The number of obs in a non-existent table is -1
 

Теперь мы гарантируем, что всегда возвращаем число без пробелов. Давайте заменим логику программы:

 %if(%nobs(table1) > 0) %then %do;

    PROC EXPORT DATA=TABLE1
        DBMS=XLSX
        OUTFILE="data/REPORT1.xlsx"
        REPLACE;
        SHEET="TEST1";
    RUN;

%end;

%if(%nobs(table2) > 0) %then %do;

    PROC EXPORT DATA=amp;ENV..AUTH_ERRORLOG_amp;REC_DATE.
        DBMS=XLSX
        OUTFILE="data/REPORT1.xlsx"
        REPLACE;
        SHEET="TEST2";
    RUN;

%end;

%let EMAIL_SUBJECT = "TEST EMAIL.";

FILENAME OUTBOX EMAIL 'TEST@TEST.COM';

DATA _NULL_;
    IF (%nobs(table1) > 0 OR %nobs(table2) > 0) then do;
        FILE OUTBOX
             TO=('TEST@TEST.COM')
             SUBJECT= amp;EMAIL_SUBJECT.
             ATTACH=("/data/REPORT1.xlsx" CONTENT_TYPE="APPLICATION/XLSX");
            
        END;
            ELSE DO;
                    FILE OUTBOX
                    TO=('TEST@TEST.COM')
                    SUBJECT= amp;EMAIL_SUBJECT.;
                    PUT"NO ERRORS FOUND";
            END; 
RUN;
 

Ответ №2:

Этот тест не имеет никакого смысла

 amp;CNT3 ^=0 AND amp;CNT3 ^='0'
 

либо в логике макросов, либо в логике шага данных.

Если CNT3 будет иметь такие значения 0 , как 123 или даже 123 тогда, просто проверьте, равен ли он нулю или нет:

 amp;cnt3 ne 0