Написание кода vba в sas

Я хочу внедрить свой код VBA в свой код SAS, чтобы выполнить весь процесс за один запуск. Мой код SAS считывает большую таблицу SAS, выполняет некоторые преобразования и, наконец, экспортирует в Excel файл (код ниже). Я также написал некоторый код VBA в файле Excel (например, автофильтр для некоторых переменных, вы можете увидеть код ниже).

Таблица выглядит так:

A B C Var1 Var2 Var3
--------------------
1 1 1 10 15 20
1 1 2 15 20 30
1 2 1 20 30 40
1 2 2 30 40 50
2 1 1 40 50 60
2 1 2 50 60 70
2 2 1 60 70 80
..............
..............

Однако я хочу внедрить свой код VBA в код SAS, чтобы выполнить весь процесс за один прогон. я знаю, как открыть и запустить файл Excel в SAS (код приведен ниже ), но я не знаю, как реализовать код VBA в моем SAS.

Если вам интересно, почему я хочу реализовать свой макрокод в своем SAS, я буду работать с подобными SAS-таблицами много раз в будущем, поэтому было бы практичнее хранить весь код в одном месте.

Я только что понял, что не могу экспортировать таблицу в SAS в формате Excel с поддержкой макросов, XLSM. Думаю, это тоже вызов. Также нецелесообразно сохранять макрокод из файла Excel, т.к. он должен быть сохранен в меню надстроек. Так что было бы намного лучше управлять всем процессом в одном месте, например, в редакторе SAS.

Код в SAS, который экспортирует итоговую таблицу в файл Excel:

PROC EXPORT DATA=File1
        OUTFILE= "&server\&env\test1.xlsx" 
        DBMS=EXCEL REPLACE; 
   SHEET="sheet1"; 
RUN;

Пример кода VBA в файле Excel для создания автофильтра для переменных в файле Excel:

Sub Macro1()
    Dim N As Long, r As Range
With Sheets("sheet1")
    N = .Cells(Rows.Count, "B").End(xlUp).Row
    ReDim ary(1 To N)
    For i = 1 To N
        ary(i) = .Cells(i, 1)
    Next i
End With

Range("A1:F20").AutoFilter
ActiveSheet.Range("$A$1:$F$20").AutoFilter Field:=1, Criteria1:=ary, Operator:=xlFilterValues
End Sub

Код в SAS для запуска и запуска файла Excel в SAS:

OPTIONS NOXWAIT NOXSYNC;
   DATA _NULL_;
   RC=SYSTEM('START EXCEL');
   RC=SLEEP(0.5);
RUN;
FILENAME CMDS DDE 'EXCEL|SYSTEM';
DATA _NULL_;
   FILE CMDS;
   PUT "[OPEN(""&server\&env\test1.XLS"")]";
   PUT '[RUN("Macro1")]';
   PUT '[SAVE.AS("&server\&env\FORMATTED_FILE.XLSM")';
   PUT "[QUIT()]";
RUN;
QUIT;

person user3714330    schedule 26.06.2015    source источник
comment
Вы говорите, что хотите иметь возможность создать новый файл Excel через DDE, а затем создать в нем новый макрос VBA программно через SAS?   -  person Joe    schedule 26.06.2015
comment
В принципе да. Я хочу, чтобы мой SAS-код читал SAS-таблицу, экспортировал результат в файл Excel (если возможно, XLSM), а мой SAS-код также запускал некоторый код VBA, чтобы сделать файл Excel более красивым. и я хочу, чтобы все эти процессы были только с одним запуском только в одном коде...   -  person user3714330    schedule 26.06.2015
comment
Макрос excel, который вы используете, всегда один и тот же? Будет ли работать метод с использованием шаблона Excel? Я думаю, что это стандартный способ сделать это; вы сохраняете макрос excel в статической книге «шаблон» и выполняете его оттуда (при записи в другую книгу или вы можете записать в книгу шаблона, а затем СОХРАНИТЬ КАК другое имя книги).   -  person Joe    schedule 26.06.2015
comment
Я планировал использовать VBA в SAS для тех же табличных переменных, но с изменением данных в каждом файле Excel. Я бы сделал только изменения в макропеременных в начале файла SAS с помощью %let var1=&var. Вы имеете в виду сохранение макроса Excel в виде книги статического шаблона, вы имеете в виду формат XLSB? и вы имеете в виду, что я просто сохраняю свой макрокод в любом шаблоне и копирую-вставляю его всякий раз, когда мне это нужно?   -  person user3714330    schedule 26.06.2015
comment
Если ваш пример - автофильтр, я бы сказал, что наборы тегов уже предоставляют отличный механизм для этого. Также вы можете экспортировать в XLSM, я делал это много раз. Какая у вас версия SAS?   -  person Reeza    schedule 26.06.2015
comment
Вы можете просто сохранить его как любой шаблон (любой .XLSM), а затем открыть рабочую книгу шаблона, а затем выполнить из нее макрос. Я не использую шаблон в официальном смысле шаблона Excel, просто в книге, которую вы используете для начала   -  person Joe    schedule 26.06.2015
comment
@Reeza, это версия 9.2, я искал ее раньше, думаю, в этой версии это невозможно. Я получил ошибку, когда пытался экспортировать в xlsm.   -  person user3714330    schedule 26.06.2015
comment
Если вы используете DDE, почему бы не экспортировать с помощью DDE?   -  person Reeza    schedule 26.06.2015
comment
Вы всегда можете использовать файл VBScript и вызывать его с помощью x (при условии, что вы работаете в Windows). Если вам нужно передать параметры, вы можете сделать это как часть вызова x.   -  person Tim Williams    schedule 26.06.2015


Ответы (3)


Обычный способ сделать это — использовать файл шаблона. У вас есть сохраненный шаблон, в котором сохранен макрос Excel (и, возможно, также выполнено некоторое форматирование; в конце концов, используя DDE, вам не нужно начинать с пустого рабочего листа).

Вы можете либо использовать DDE для заполнения рабочей книги/листа шаблона, а затем «Сохранить как» другой файл, либо вы можете использовать DDE для создания новой рабочей книги и рабочего листа, открытия рабочей книги шаблона, запуска макроса, закрытия шаблона. То, что вы делаете, может зависеть от того, хотите ли вы распространять макрос вместе с вашими результатами.

Это позволяет вам запускать все, никак с ним не взаимодействуя — вам не нужно добавлять к нему новый макрос или что-то еще, поскольку макрос шаблона уже существует. Таким образом, все можно сделать за один проход.

Это показано, например, в документе Шаг за шагом в использовании SAS® DDE для Создайте график Excel на основе N наблюдений из набора данных SAS, а также несколько других документов по этому вопросу.

person Joe    schedule 26.06.2015

Я всегда считал DDE немного неуклюжим, и он расстраивается, если вы прикасаетесь к рабочей книге Excel во время ее работы. В этом примере сценарий VBscript записывается в рабочее пространство sas, а затем выполняется iut. По сути, вы можете получить операторы put для написания кода для всего, что вы хотите, чтобы программа делала, и она может управляться тем, что находится в наборе данных SAS. В этом примере показано, как добавить верхний и нижний колонтитулы к существующей электронной таблице Excel...

%macro xlHeadFoot(WorkBookPath=,Header=FileName,Footer=SheetName,onlySheet=);

  %local _shortpath WorkBook;

  data _null_;
    length header footer $200;
    header=ifc(lowcase("&header.")='filename' or lowcase("&header.")='sheetname',tranwrd(tranwrd(lowcase("&header."),'filename','&F'),'sheetname','&A'),"&header.");
    footer=ifc(lowcase("&footer.")='filename' or lowcase("&footer.")='sheetname',tranwrd(tranwrd(lowcase("&footer."),'filename','&F'),'sheetname','&A'),"&footer.");
    call symput("header",trim(header));
    call symput("footer",trim(footer));
  run;

  %let WorkBook=%scan(&WorkBookPath.,%sysfunc(countw(&WorkBookPath.,\)),\);

    %* ***********************************************;
    %* get the short DOS name for the workspace folder;

    data _null_;
      rc=filename("inpipe",catx('"','for %I in (',"%sysfunc(pathname(work))",') do echo %~sI'),"pipe");
    run;

    data _null_;
      infile inpipe truncover end=last;
      input @1 data $256. ;
      rc=filename("inpipe","");
      if last then call symput('_shortpath',trim(data));
    run;

    %* *******************************;
    %* tidy up any previous executions;

    data _null_;
      if fileexist("&_shortpath\testx.vbs") then do;
        rc=filename("dump","&_shortpath\testx.vbs");
        rc=fdelete('dump');
        msg=sysmsg();
        if msg ne '' then put msg=;
      end;
      if fileexist("&_shortpath\xmlFile.xml") then do;
        rc=filename("dump","");
        rc=filename("dump","&_shortpath\xmlFile.xml");
        rc=fdelete('dump');
        msg=sysmsg();
        if msg ne '' then put msg=;
        rc=filename("dump","");
      end;
    run;


  %if %sysfunc(fileexist("&WorkBookPath."))=1 %then %do;


    data null;
      file "%sysfunc(pathname(work))\testx.vbs";
      put @1 'Set objExcel = CreateObject("Excel.Application")';
      put @1 'objExcel.Application.Visible = True';
      put @1 'objExcel.Workbooks.open  "' "&WorkBookPath." '"' ;
      %if %str(&onlySheet.) ne %str() %then %do;
        put @1 'onlySheetExisits=False';
        put @1 'for each sheet in objExcel.Workbooks("' "&WorkBook." '").sheets';  
        put @1 'if strcomp(sheet.name,"' "&onlySheet." '",1)=0 then onlySheetExisits=True';
        put @1 'if strcomp(sheet.name,"' "&onlySheet." '",1)=0 then sheet.PageSetup.CenterHeader = "' "%str(&Header.)" '"';
        put @1 'if strcomp(sheet.name,"' "&onlySheet." '",1)=0 then sheet.PageSetup.CenterFooter = "' "%str(&Footer.)" '"';
        put @1 'Next';
      %end;
      %else %do;
        put @1 'for each sheet in objExcel.Workbooks("' "&WorkBook." '").sheets';  
        put @1 'sheet.PageSetup.CenterHeader = "' "%str(&Header.)" '"';
        put @1 'sheet.PageSetup.CenterFooter = "' "%str(&Footer.)" '"';
        put @1 'Next'; 
      %end;

      put @1 'objExcel.Workbooks("' "&WorkBook." '").save';
      put @1 'objExcel.Workbooks("' "&WorkBook." '").Close';
      put @1 'objExcel.Application.Quit';
      %if %str(&onlySheet.) ne %str() %then %do;
        put @1 'if onlySheetExisits=False then msgbox "Error! Could not find Worksheet: '"&onlySheet."' in Workbook: "' ' & vbcr & ' '" '"&WorkBookPath." '",16,"SAS: '"&SYSMACRONAME"'"';
      %end;

    run;


    x %sysfunc(quote("&_shortpath.\testx.vbs")); 

  %end;
  %else %put %str(ERR)OR: [&SYSMACRONAME.] Unable to open: &WorkBookPath.  - check it exists!;


%mend;
person Jim E    schedule 05.02.2019

С DDE вы можете установить фильтр в SAS:

data _null_;
    FILE CMDS;
    /* select your worksheet */
    put '[workbook.select("your_sheet")]';
    /* select the column range you want to set the filter */
    put '[select("r1c2:r1c5")]';
    /* set filter */
    put '[filter]';
run;
person zuluk    schedule 14.11.2017