2016-03-01 1 views
2

В настоящее время у меня возникает проблема с использованием расширяемого диапазона данных для вывода таблицы, в которой используется таблица, заполненная электронными сообщениями с JobOffers, которые уже были переименованы с использованием VBA - это больше для моего собственного обучения, чем для чего-либо еще ,SAS SQL Macro Инкрементный диапазон дат

Я хочу, чтобы код в цикле через дни я могу установить в макрокоманды

%EmailDump('01Jan2015'd,'02Jan2015') 

И он будет работать макрос в коде ниже, и позвольте мне отступить все письма из в течение этого периода и экспортировать его (я понимаю, что я над записью таблицы каждый раз - однако это будет экспортироваться (каждый экспорт должен быть другим, потому что он имеет макрос для EmailStart внутри него)

Таким образом, некоторые фиктивные данные для этого будут выглядеть

Тема EmailS tartDate

Job Offer 12/01/2015

Job Offer 25/01/2015

Job Offer 12/05/2015

Кодекс используется ниже

%Macro EmailDump(begindate,endindate); 

%do 
EmailStart = &begindate. 
%to &endindate. 
%by 1; 

%end; 

PROC SQL; 

CREATE TABLE WORK.EMAILDUMP AS 

SELECT * FROM WORK.EMAILS 

WHERE TOPIC = 'JobOffer' 

and EmailStartDate = &EmailStart 

;QUIT; 

proc export data=work.EMAILDUMP 

dbms=XLSX 

outfile="/p01/Output File &EmailStart " replace; 

run; 

%Mend EmailDump; 

%EmailDump('01Jan2015'd,'02Jan2015'd); 

Сообщение об ошибке выглядит следующим образом:

ОШИБКА. В функции% EVAL или% IF, где требуется числовой операнд, был найден операнд символов. Состояние было: & begindate. ОШИБКА: Значение% FROM цикла% DO EmailStart недействительно. ОШИБКА. В функции% EVAL или% IF, где требуется числовой операнд, был найден операнд символов. Состояние было: & endindate. ОШИБКА: Недопустимое значение% TO для цикла% DO EmailStart. ОШИБКА: Макрос EmailDump остановит выполнение


Не уверен, что если кто-нибудь может мне помочь с этим? Был бы очень признателен за любую помощь!

+0

0 Вы должны более точно описать проблему, с которой вы сталкиваетесь. Сообщать сообщения об ошибках, если они встречаются. Укажите конкретно, что вы хотите сделать код. – floydn

+0

С беглого представления кода я вижу, что оператор% end должен быть перемещен вниз и помещен после экспорта proc. Предполагается, что вы хотите, чтобы proc sql и proc export запускались каждый день в цикле. Конечно, я могу только предположить, потому что вы не поделились своими ожиданиями от кода. – floydn

+0

Перемещая оператор конца%, ваш макрос будет генерировать пару транзакций proc sql и proc для каждого дня, но файл work.emaildump и файл Excel будут перезаписаны во время каждого выполнения цикла. Независимо от того, сколько дней вы проходите, эти 2 файла будут содержать только последний день в цикле. Я больше не буду комментировать, пока вы не уточните цель и ожидаемый результат программы. – floydn

ответ

3

Ниже ваш код упрощен, чтобы содержать только то, что требуется, чтобы воспроизвести проблему:

%macro emaildump(begindate,endindate); 
    %do emailstart = &begindate %to &endindate; 
    %put &emailstart; 
    %end; 
%mend emaildump; 

Если мы называем его литералов, мы получаем сообщение, которое вы описали:

%emaildump('01jan2015'd,'02jan2015'd); 

дает:

ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric 
     operand is required. The condition was: &begindate 
ERROR: The %FROM value of the %DO EMAILSTART loop is invalid. 
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric 
     operand is required. The condition was: &endindate 
ERROR: The %TO value of the %DO EMAILSTART loop is invalid. 
ERROR: The macro EMAILDUMP will stop executing. 

Однако, если мы передаем значения исходной даты (которые представлены только как целые числа) он отлично работает. Мы можем рассчитать необработанные значения даты с помощью функции mdy().Потому что мы делаем это в макроязыке мы должны обернуть mdy() с %sysfunc():

%let start = %sysfunc(mdy(1,1,2015)); 
%let end = %sysfunc(mdy(1,2,2015)); 
%emaildump(&start,&end); 

дает желаемый результат:

20089 
20090 

В качестве альтернативы, вы можете также использовать %sysevalf() оценить литералы и преобразовать их в числа, как это:

%let start = %sysevalf('01Jan2015'd); 
%let end = %sysevalf('02Jan2015'd); 
%emaildump(&start,&end); 

Как Квентин указывает в комментариях ниже ... причина это происходит потому, что:

it's a limitation of the fact that %DO statement implicitly calls %EVAL , and %EVAL can't handle date literals.

+0

Это замечательно - большое спасибо! – Brecon

+3

Я не думаю, что это ошибка. Но это ограничение того факта, что оператор% DO неявно называет% EVAL, а% EVAL не может обрабатывать литералы даты. '% put% eval ('01Jan2015'd);' будет ошибка, но '% put% sysevalf (' 01Jan2015'd);' не будет. Предполагая, что, возможно, '% do emailstart =% sysevalf (& begindate)% to% sysevalf (& endindate);' является опцией. – Quentin

+0

Ах, потрясающе, спасибо Квентин, я всегда задавался вопросом, что происходит за кулисами, чтобы вызвать проблему. Я обновлю ответ, чтобы включить эту информацию. –