การเขียนโค้ด 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 ไม่สะดวกนัก เนื่องจากจะต้องบันทึกไว้ในเมนู Adds-in ดังนั้น จะดีกว่ามากหากจัดการกระบวนการทั้งหมดในที่เดียว เช่น ภายในโปรแกรมแก้ไข 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 Macro เป็นเวิร์กบุ๊กเทมเพลตคงที่ คุณหมายถึงรูปแบบ XLSB หรือไม่ และคุณหมายถึงว่าฉันแค่บันทึก Macro-code ของฉันลงใน tamplate ใด ๆ และฉันจะคัดลอกและวางทุกครั้งที่ต้องการ?   -  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