Introduktionskurs i SAS



Relevanta dokument
Introduktion till Jasmine 1.2 ODQL

Objektorienterad programmering i Java I. Uppgifter: 2 Beräknad tid: 5-8 timmar (OBS! Endast ett labbtillfälle) Att läsa: kapitel 5 6

4. Kunna orientera sig mellan de olika fönstren

Statistikens grunder 1 och 2, GN, 15 hp, deltid, kvällskurs

Målet för D1 är att studenterna ska kunna följande: Använda några av de vanligaste PROC:arna. Sammanställa och presentera data i tabeller och grafiskt

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

IDA kursmaterial Informationsblad make. make

Föreläsning 6: Introduktion av listor

Grundläggande datalogi - Övning 1

TDIU01 - Programmering i C++, grundkurs

Föreläsning 10 Datalogi 1 DA2001. Utskrift på skärmen. Syntax. print( Hej ) Hur är det? Hej. print( Hej,end= ) print( Hur är det? ) HejHur är det?

Klassdeklaration. Metoddeklaration. Parameteröverföring

Översikt över Visual Basic

Labb i Datorsystemteknik och programvaruteknik Programmering av kalkylator i Visual Basic

Statistikens grunder 1 och 2, GN, 15 hp, deltid, kvällskurs

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

Introduktion till programmering SMD180. Föreläsning 2: Variabler, uttryck och satser

Laboration 1 Introduktion till Visual Basic 6.0

Använda några av de vanligaste PROC:arna. Sammanställa och presentera data i tabeller och grafiskt

Programmering I Tobias Wrigstad fredag, 2009 augusti 28

Multipel tilldelning. Introduktion till programmering D0009E. Föreläsning 6: Iteration. while-satsen. Kom ihåg. Snurror kontra rekursion

Föreläsning 5: Introduktion av pekare

Användarhandledning Version 1.2

Några inbyggda funktioner (med resultat!) Introduktion till programmering D0009E. Föreläsning 4: Villkor och rekursion. Modulus-operatorn.

Objektorienterad programmering Föreläsning 2

Föreläsning 2 Programmeringsteknik och C DD1316. Programmering. Programspråk

Planering Programmering grundkurs HI1024 HT TIDAA

Att deklarera och att använda variabler. Föreläsning 10. Synlighetsregler (2) Synlighetsregler (1)

F4. programmeringsteknik och Matlab

Programmering i C++ Kompilering från kommandoraden

Introduktionskurs i SAS. Del 1 Datastegsprogrammering

Introduktion till programmering och Python Grundkurs i programmering med Python

KPP053, HT2015 MATLAB, Föreläsning 1. Introduktion till MATLAB Skript Inläsning och utskrift av variabler Ekvationssystem Anonyma funktioner

Introduktion till programmering D0009E. Föreläsning 5: Fruktbara funktioner

Planering Programmering grundkurs HI1024 HT 2014

Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson

KPP053, HT2016 MATLAB, Föreläsning 1. Introduktion till MATLAB Skript Inläsning och utskrift av variabler Ekvationssystem Anonyma funktioner

ITK:P1 Föreläsning 1. Programmering. Programmeringsspråket Java. Stark typning Explicit typning Strukturerat Hög säkerhet

Att skriva till och läsa från terminalfönstret

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

Programmeringsteknik med C och Matlab

Twincat: PLC Control

Föreläsning 2 Programmeringsteknik DD1310. Programmering. Programspråk

Att förstå hur man konstruerar modulära program Att kunna skapa nya funktioner Att förstå hur data skickas mellan funktioner

Command line argumenter. Objektorienterad Programmering (TDDC77) Vad blir resultatet? Nu då? Ahmed Rezine. Hösttermin 2016

Objektorienterad Programmering (TDDC77)

Datorsystem Laboration 2: Minnesmappade bussar

Språket Python - Del 1 Grundkurs i programmering med Python

Övningsuppgifter kapitel 8

Funktionens deklaration

2. Lära sig beskriva en variabel numeriskt med "proc univariate" 4. Lära sig rita diagram med avseende på en annan variabel

Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten Programmering: att instruera en maskin att utföra en uppgift, kräver olika språk:

Tentamen i. TDDA 69 Data och programstrukturer

1 Funktioner och procedurell abstraktion

TUTORIAL: SAMLING & KONSOLL

Programmeringsteknik och Matlab. Dagens program. Viktiga datum. Repetitionsexempel. Repetition av if/else, for, while och Scanner

Programmering för språkteknologer I, VT2012. Rum

Frekvenstabell över tärningskast med C#

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Exempelduggan. Luffarschack. Koda spel

Pascal... Pascal. Pascal... Pascal...

Pascal. reserverade ord fördefinierade funktioner och procedurer egendefinierade funktioner, procedurer och objekt

Uppgift 1 (grundläggande konstruktioner)

Alla filer som bearbetar PHP script ska avslutas med ändelsen.php, exempelvis ska en indexsida till en hemsida heta index.php

Föreläsning 3-4 Innehåll

Planering Programmering grundkurs HI1024 HT data

Platser för att skriva och testa kod online. Workshop om programmering i matematikkurser, version 0.7 senast sparat

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Felsökning. Datatyper. Referenstyper. Metoder / funktioner

Python. Python är, som Scheme, ett interpreterat språk men det finns kompilatorer för Python.

HI1024 Programmering, grundkurs TEN

EDAA20 Programmering och databaser. Mål komprimerat se kursplanen för detaljer. Checklista. Föreläsning 1-2 Innehåll. Programmering.

Design av interaktiv multimedia. Läs i förväg om det som övningarna kommer att beröra. Träna hemma både före och efter övningarna.

Python. Python är, som Scheme, ett interpreterat språk men det finns kompilatorer för Python.

Objektorienterad Programmering (TDDC77)

I Skapa Hej.java och skriv programmet. I Kompilera med javac Hej.java. I Rätta fel och repetera tills du lyckas kompilera ditt program

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

Att använda pekare i. C-kod

Laboration 3 HI1024, Programmering, grundkurs, 8.0 hp

Omgivningar. Omgivningar är viktiga eftersom de avgör vilka namn som är synliga och därmed dessas innebörd och de värden som är förknippade med dem.

Statistikens grunder 1 och 2, GN, 15 hp, deltid, kvällskurs

Introduktion till programmering SMD180. Föreläsning 4: Villkor och rekursion

Dagens föreläsning Programmering i Lisp. - Bindning av variabler (avs 14.6) fria variabler statisk/lexikalisk och dynamisk bindning

Laboration: Whitebox- och blackboxtesting

Laboration 1. "kompilera"-ikonen "exekvera"-ikonen

Föreläsning 2 Programmeringsteknik och C DD1316

Föreläsning 2 Programmeringsteknik DD1310. Programmering. Programspråk

Labora&on 2 Funk&oner, if och loop övningar/uppgi:er

Anteckningar 1: Grundläggande saker

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Muddy. Funktioner / metoder. Punktnotation. Evalueringsordning

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Statistik över heltal

Visual Basic, en snabbgenomgång

Tentamen i. TDDC67 Funktionell programmering och Lisp

TENTAMEN OOP

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design Alex Gerdes, 2016

(Man brukar säga att) Java är... Denna föreläsning. Kompilering av Java. Historik: Java. enkelt. baserat på C/C++ Allmänt om Java

Föreläsning 3: Typomvandling, villkor och val, samt textsträngar

Transkript:

Introduktionskurs i SAS Del 4 Makroprogrammering

Detta material skyddas av upphovsrättslagen och får inte kopieras eller på annat sätt spridas utan upphovsmannens (Knowit Software Solutions AB) skriftliga godkännande. Upphovsmannen har gett sitt godkännande att detta material får fritt användas vid undervisning på Linköpingsuniversitet, IDA. Sidan 2

MAKROPROGRAMMERING, EN INTRODUKTION 4 VARFÖR MAKROPROGRAMMERING?... 4 GRUNDLÄGGANDE BEGREPP...4 MAKROVARIABLER... 5 SKAPA MAKROVARIABLER... 5 MER OM ATT TILLDELA MAKROVARIABLER VÄRDEN... 5 ATT REFERERA MAKROVARIABLER... 7 MAKROVARIABELNS REFERERBARA MILJÖ... 10 AUTOMATISKA MAKROVARIABLER... 12 MAKROFUNKTIONER... 13 SKAPA OCH KÖRA MAKRON... 15 MAKRON OCH DATASTEG... 18 GRÄNSSNITTET MELLAN MAKROVARIABLER OCH DATASTEGET... 20 KOMPILERING OCH EXEKVERING... 22 ATT AUTOMATISKT REFERERA LAGRADE MAKRON... 23 SAS MAKRO OPTIONS OCH DEBUGGING... 24 SAMMANFATTNING... 27 Makrovariabler... 27 Makrofunktioner... 27 Makron... 27 Sidan 3

Makroprogrammering, en introduktion Syftet med detta dokument är att ge en introduktion i SAS -systemets makrospråk, gå igenom vissa makrofunktioner, visa hur makrospråket används för att utöka möjligheterna vid datastegsprogrammering m.m. Texten består av ett antal sektioner som berör olika områden. I texten förekommer rikligt med kodexempel och meningen är att man läser dokumentet på datorn och har SAS igång för att löpande kopiera över kod-exemplen till SAS och provköra och studera resultaten. Dokumentet är uppdelat i följande avsnitt: MAKROVARIABLER MAKROFUNKTIONER MAKRON MAKRON OCH DATASTEG KOMPILERING OCH EXEKVERING MAKRO OPTIONS, DEBUGGING SAMMANFATTNING Kommentar: SAS makromanual är mycket bra och går snabbt att ta sig igenom. Använd den! Varför makroprogrammering? Generalisera koden Göra koden repetitiv Villkora koden Utföra mer komplicerad programmering Förenkla Göra datasteget mer likt vanlig programmering, dynamiskt generera delar av eller hela datasteg Grundläggande begrepp SAS makrofunktionalitet är i princip ett sätt att lagra, generera och skriva text. Eftersom denna text kan skrivas till SAS programbuffert kan man exekvera saskod som genererats i ett makro. Det finns en uppsättning funktioner och kommandon tillgängliga. Dessa anropas genom att skriva ett procenttecken före namnet. Kommandot PUT anropas alltså genom att skriva %PUT. Makrovariabler (gås igenom nedan) löses upp genom att skriva ett &-tecken framför namnet på variabeln. Genom att skriva &mvar kommer makrovariabeln mvar att lösas upp. Makron kompileras genom att exekvera makrokoden. När makrokoden är kompilerad skapas ett makroentry i katalogen WORK.SASMACRO som alltså är temporär. Ett kompilerat makro exekveras på samma sätt som funktioner och kommandon, dvs genom att skriva ett %-tecken framför makronamnet. Sidan 4

Makrovariabler SKAPA MAKROVARIABLER För att skapa en makrovariabel fristående (dvs. utanför ett makro) används kommandot %LET och visas i loggen med %PUT. %LET gnu=hej; %PUT &gnu; För att skapa en makrovariabel i ett datasteg används funktionen SYMPUT: skapa först ett testdataset: data tst; txt= Hej ; do i=1 to 5; output; end; lägg ut värdet i nobs (antal observationer) på sista posten i makrovariabeln gnu och variabeln txt i makrovariabeln gnu2, visa dem i loggen: data _null_; set tst nobs=nobs; if _n_=nobs then do; call symput('gnu',put(nobs,2.)); call symput( gnu2,txt); end; %PUT &gnu; Kommentar: eftersom makrovariabler alltid bara lagrar text, inte numeriska värden, måste den numeriska variabeln nobs formatteras som text, vilket görs med funktionen PUT(). Om en textvariabel, som txt, ska läggas ut i en makrovariabel, skriver man bara variabelnamnet. MER OM ATT TILLDELA MAKROVARIABLER VÄRDEN Makrovariabler tilldelas värden som visas ovan, med %LET eller SYMPUT. För att inledande eller avslutande blanka positioner ska lagras i en makrovariabel måste man uttryckligen ange detta genom att använda funktionen %STR() som returnerar argumentet som en teckensträng: %LET gnu= Hej; %LET hepp= Hej ; Sidan 5

%LET hupp=%str( )Hej; %PUT &gnu; %PUT &hepp X; %PUT &hupp; resulterar i att följande skrivs till loggen: Hej Hej X Hej Makrovariabler hanteras normalt som strängar men kan användas i aritmetiska operationer i vissa speciella fall. Följande exempel resulterar bara i att strängen 2+5 läggs i makrovariabeln hepp: %LET hepp=2+5; %PUT &hepp; 2+5 För att lagra resultatet av additionen krävs att man använder makrofunktionen %EVAL: %LET hepp=%eval(5+2); %PUT &hepp; 7 Tänk på att %EVAL endast hanterar heltal, följande operation resulterar i sas-error: %LET hepp=%eval(5+2.5); ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 5+2.5 och följande division returnerar endast heltalsdelen: %LET hepp=%eval(5/2); %PUT &hepp; 2 För att klara av denna operation finns en ny makrofunktion %SYSEVALF (SAS 6.12+) som klarar av detta, men glöm inte att resultatet förblir en textsträng. %LET hepp=%sysevalf(5/2); %PUT &hepp; 2.5 Eftersom man kan lagra upp till 65 534 tecken i en makrovariabel går det att lagra hela SAS statements i macro variabler. Detta är mycket användbart. Man kan på detta sätt enkelt och dynamiskt generera upp sas-satser och exekvera bara genom att lösa upp variabeln: %LET hepp=%str( data tst; var2= Hej ; do var1=1 to 10; Sidan 6

output; end; &hepp; proc print data=tst; var var1 var2; ); Kommentarer: Här måste funktionen %STR användas eftersom sas annars skulle tolka första semikolonet i strängen som att satsen avslutades, dvs att bara det som står innan första semikolonet skulle läggas i variabeln. Om man ger en macro variabel värdet null tolkar SAS dess referens som ingenting och den ignoreras därmed. %LET hepp1=var1; %LET hepp2=; proc print data=tst; var var2 &hepp1 &hepp2 var3; Resultatet av dessa två fall blir följande var-statement: var var2 var1 var3; ATT REFERERA MAKROVARIABLER Makrovariabler refereras/löses upp genom att skriva ett &-tecken framför namnet på variabeln. Makrovariabler löses inte upp inom fnuttar( ) men inom dubbel-fnuttar( ): %LET hepp=hej; %PUT &hepp; Hej %PUT '&hepp'; '&hepp' %PUT "&hepp"; "Hej" När makroprocessorn stöter på en makroreferens (&) så antar den att variabelns namn är alla påföljande tecken tills dess den hittar ett tecken som inte kan vara del av ett SAS-namn t.ex. &, %, BLANK. Makroprocessorn använder en punkt (.) som explicit avgränsare för variabelnamn. Detta används för att indikera att ett macrovariabelnamn slutar, om det ej är självklart. Sidan 7

Nedan finns ett exempel där man har en gemensam del av variabelnamnen i en makrovariabel, vilket är mycket användbart om man refererar variablerna på många ställen i ett program. Om variablerna byter namn från var1-varn till x1-xn behöver man bara uppdatera programmet på ett ställe. Målet är alltså att var1 etc. ska skrivas till programbufferten. Felaktigt exempel: %LET hepp=var; proc print data=temp; var &hepp1 &hepp2; - 200 WARNING: Apparent symbolic reference HEPP1 not resolved. ERROR: Variable HEPP1 not found. ERROR 200-322: The symbol is not recognized. NOTE: The SAS System stopped processing this step because of errors. Kommentar: Eftersom 1 och 2 är godkända tecken i ett sas-namn antar makroprocessorn att den ska lösa upp en variabel vid namn hepp1 och en vid namn hepp2 och några sådana variabler existerar inte här. Man måste explicit berätta för SAS att variabelnamnet slutar innan siffran genom att lägga till en punkt: proc print data=temp; var &hepp.1; Kommentar: punkten skrivs alltså inte ut. I ovanstående exempel kommer SAS skriva var1, som önskat. Makroprocessorn använder sig av s.k. forward scan och löser upp varje makroreferens den stöter på i tur och ordning. Därför kan man behöva tvinga makroprocessorn att scanna en referens flera gånger genom att använda flera &-tecken: I nedanstående exempel vill man slutligen lösa upp variablerna v1 och v2, men variabelnamnet ska först komponeras genom att använda en annan makrovariabel som innehåller siffran: Först ett felaktigt exempel: %LET v1=var1; %LET v2=var2; %LET i=1; proc print data=tst; var &v&i; %LET i=2; proc print data=tst; var &v&i; -vilket resulterar i error: Sidan 8

WARNING: Apparent symbolic reference V not resolved. 107 &v&i; - 200 ERROR: Variable V1 not found. ERROR 200-322: The symbol is not recognized. NOTE: The SAS System stopped processing this step because of errors. NOTE: The PROCEDURE PRINT used 0.02 seconds. Kommentar: Eftersom makroprocessorn antar att alla tecken efter &-tecknet är namnet på variabeln den ska lösa upp, kommer den bara till nästa &-tecken och antar att den ska lösa upp variabeln v som inte finns (se sas-varningen). Därmed lämnar makrogeneratorn denna och försöker lösa upp nästa variabel. Detta går bra eftersom variabeln i existerar och innehåller 1. SAS kommer därmed skriva &v1 till programbufferten. & kan inte tolkas och SAS ger ett felmeddelande och fortsätter med resten, dvs v1 vilket är OK syntaxmässigt, men variabeln existerar inte i datasetet, och SAS ger ytterligare ett felmeddelande. För att makrogeneratorn först ska lösa upp i till 1 och sen lösa upp variabeln v1 krävs att man får SAS att scanna två gånger. En gång för att lösa upp i och en för att sedan lösa upp v1. För att åstadkomma detta inleds satsen med två &-tecken: %LET i=1; proc print data=tst; var &&v&i; %LET i=2; proc print data=tst; var &&v&i; Sidan 9

MAKROVARIABELNS REFERERBARA MILJÖ När ett makro exekveras som skapar makrovariabler utan att dessa explicit deklareras som lokala eller globala försöker makroprocessorn att ändra värdet på en existerande makrovariabel hellre än att skapa en ny variabel, oavsett vilken miljö man befinner sig i. För att explicit deklarera variabler lokala eller globala används makrosatserna %GLOBAL och %LOCAL. När ett makro skapar en makrovariabel och det inte finns någon variabel med det namnet i någon miljö så skapas variabeln i pågående miljön vilket innebär i det aktuella makrot och i alla submakron som anropas från det lokala. %GLOBAL skapar en makrovariabel i den globala miljön oavsett vilken miljö man befinner sig i. %LOCAL skapar en makrovariabel i den pågående miljön, oavsett om det finns någon med samma namn i någon annan miljö. För att vara säker på att inte av misstag uppdatera en makrovariabel i någon överliggande miljö bör man ha för vana att explicit deklarera alla lokala makrovariabler med %LOCAL. SYMPUT rutinen är ett specialfall som skapar makrovariabeln i den första icke-tomma miljön den träffar på (dvs en miljö som innehåller åtminstone en annan makrovariabel. Följande figurer illustrerar detta. I exemplet uppdateras den globala variabeln HEPP i makrot GNU. Följande programexempel visar samma sak: %LET hepp=hej; %PUT &hepp; %MACRO GNU; %let hepp=då; *hepp skapas i den globala miljön och sätts till Hej; *skapa makrot gnu som uppdaterar hepp och skapar hupp*; Sidan 10

%LET hupp=tjosan; %PUT &hepp &hupp; %MEND; %gnu; %PUT &hepp; *slut på makrot*; *kör makrot GNU; I detta exempel definieras hepp explicit som lokal i makrot GNU. Detta förhindrar att den globala hepp-variabeln uppdateras. Hupp definieras explicit som global och går därför att referera även efter att makrot körts: %LET hepp=hej; %PUT &hepp; %MACRO GNU; %LOCAL hepp; %GLOBAL hupp; %LET hepp=då; %LET hupp=tjosan; %PUT &hepp &hupp; %MEND; %gnu; %PUT &hepp &hupp; *hepp skapas i den globala miljön och sätts till Hej; *skapa makrot gnu som uppdaterar hepp och skapar hupp; *slut på makrot; *kör makrot GNU; Makrovariabler skapade i en miljö kan refereras i alla underliggande miljöer men inte i överliggande. %LET hepp=hej; %MACRO gnu; %MACRO zebra; %PUT &hepp; *zebra löser upp hepp; Sidan 11

%MEND zebra; %LOCAL hepp; %LET hepp=då; %zebra; %MEND gnu; %gnu; Då %PUT &hepp; Hej *hepp deklareras som lokal i gnu och sätts till Då; *kör zebra; *kör gnu; AUTOMATISKA MAKROVARIABLER SAS har ett antal automatiska makrovariabler som uppdateras av systemet och enkelt refereras som en vanlig makrovariabel, dvs &namn. Ett urval av automatiska makrovariabler: &SYSDATE datum då sessionen startade &SYSTIME tid så sessionen startade &SYSDAY veckodag &SYSERR returkod från SAS procedurer (0=OK, 1&2=proc avbruten av anv, 4=Varning, >4=error) &SYSINFO mer utförlig returkod som ges av vissa procedurer. Värden, se resp proc dokumentation &SYSRC returkod från operativsystemkomandon &SYSVER SAS version &SYSLAST levererar referensen till datasetet _LAST_ Sidan 12

Makrofunktioner Det finns ett antal makrofunktioner i SAS. Eftersom makrofunktionen främst är ett verktyg för att generera textsträngar handlar de flesta funktionerna om stränghantering. Här kommer kortfattade beskrivningar av några funktioner. %STR(argument): används när man vill hantera en sträng som innehåller tecken som inte går att skriva i öppen kod. %LET myvar=%str(put;put;put;); %PUT &myvar; skriver följande till loggen. put;put;put; prova gärna följande variant som visar vilket problem %STR löser: %LET myvar=put;put;put; ; %PUT &myvar; %SUBSTR(argument,startpos,längd): returnerar tecknen fr.o.m. startpos. och längd positioner framåt från argument. %LET x=12345678; %LET myvar=%substr(&x,4,3); %PUT &myvar; skriver följande till loggen: 456 %SCAN(argument,ord nr, avgränsande tecken): returnerar ord enligt ord nr från argument där ord definieras som strängar avgränsade av avgränsande tecken. %LET x=en liten mening med en massa ord; %LET myvar=%scan(&x,4,%str( ) ); %PUT &myvar; skriver följande till loggen: med %INDEX(argument, delsträng): returnerar första positionen där delsträng förekommer i argument. Hittas inte delsträngen returneras 0. %LET x=ännu en mening med en massa ord; %LET myvar=%index(&x,me); %PUT &myvar; Sidan 13

skriver följande till loggen: 9 %EVAL(heltalsoperation): returnerar resultatet av heltalsoperation. Observera att den bara hanterar heltal och bara returnerar heltalsdelen av operationen om den resulterar i ett decimaltal! Se sidan %SYSEVALF(räkneoperation): returnerar resultatet av en räkneoperation. Denna funktion klarar av decimalresultat. Finns i SAS 6.12+. Vidare finns ett flertal funktioner för att utföra en rad olika quotings av strängar. Dessa gås ej igenom här, se SAS online hjälp under main menu/sas language/macro facility eller makromanualen. Sidan 14

Skapa och köra makron Ett makro inleds med %MACRO NAMN och avslutas med %MEND NAMN. Makrot körs sedan med satsen %NAMN. Makrot kompileras när programmet körs (submittas i SAS) första gången och kan sen användas hur många gånger som helst under sessionen. (Ett semikolon efter makronamnet går också bra när man skall köra det men i vissa fall kan det vara betydelsefullt att det egentligen inte behövs.) %MACRO test; %PUT Idag är det &SYSDAY; %MEND test; %test; Idag är det Sunday %test; Idag är det Sunday Makros kan definieras med parametrar som kan ha ett förvalt (default) värde. Parametrarna kan anges positionsvis eller namnvis med sk. positional eller keyword parameterar. Positional parametrar måste alltid komma före keyword-parametrar i en parameter lista. I makrot PARM finns två positionella parametrar pos1 och pos2. Att de är positionella visas av att de ej följs av ett =. Två keyword parametrar finns också, keyw1 och keyw2 %MACRO parm(pos1,pos2,keyw1=,keyw2=5); %DO i=1 %TO &keyw2; %IF &keyw1<&keyw2 %THEN %DO; %PUT &pos1 &pos2; %ELSE %DO; %PUT &pos2 &pos1; %MEND parm; %PARM(Hej,Då,keyw1=3); Hej Då Hej Då Hej Då Hej Då Hej Då %parm(hej,då,keyw2=2,keyw1=3); Då Hej Då Hej Sidan 15

Makroprocessorn genererar text som beroende på hur texten ser ut vidarebefordras till SASkompilatorn och detta gör att friheten vad som tillåts att skriva i ett makro är ganska stor. Man behöver t.ex. inte alltid skriva fullständiga programsatser som avslutas med semikolon. Man kan låta ett makro bara generera ett antal ord. %MACRO test(x); %DO i=1 %TO &x; var&i %IF &x>2 and &i=&x %THEN %DO; ; by sort %MEND test; proc print data=temp; var %test(3); /* Dvs. var1 var2; om x<3 */ /* och var1 var2... ; by sort; om x >= 3. */ Beroende på sitt sätt att arbeta kan makroprocessorn låta ett makro fungera som inte bara en skapare av text eller datastegskod utan som program block som har karaktären av en procedur eller en funktion i traditionell programmering. Hur makrot fungerar är bara en fråga om hur det skrivs. Exempel på ett makro som fungerar som en generell procedur som skapar ett dataset temp om det inte är en torsdag. %MACRO prosce; %IF &SYSDAY=Thursday %THEN %DO; data temp; set tst; var4=var1+var3; %ELSE %PUT Today is &SYSDAY; %MEND prosce; %prosce; proc print; quit; Exempel på ett makro som fungerar som en funktion med en parameter (positionell). Makrot skriver 10 eller 100 till programbufferten beroende på vilken veckodag det är. %MACRO funk(day); %IF &DAY=Sunday %THEN %DO; 10 %ELSE %DO; 100 %MEND funk; Sidan 16

data temp; set temp; var4=var1+%funk(&sysday); proc print; Sidan 17

Makron och datasteg Makrofunktionen i SAS är ett verktyg som möjliggör för användaren att kunna vara repetitiv över hela datasteget och inte bara över delar av datasteget som blir fallet om man bara använder datastegsprogrammering. Makrofunktionen ger också möjlighet att villkora hela datasteget. Därmed kan man via makrofunktionen skapa hela applikationer. Ett makro som sorterar dataseten temp1-temp3 eller skriver ut datasetet temp. Dessutom ges ett felmeddelande till loggen om ett felaktigt parametervärde ges. %MACRO repet(parm); %IF &parm eq SORT %THEN %DO; %DO i=1 %TO 3; proc sort data=temp out=temp&i; by var&i; %ELSE %DO; %IF &parm eq PRINT %THEN %DO; proc print data=temp; %ELSE %DO; %PUT Note: Makrot hanterar inte parametervärdet &parm; %MEND repet; %repet; %repet(sort); NOTE: The data set WORK.TEMP1 has 5 observations and 4 variables. NOTE: The data set WORK.TEMP2 has 5 observations and 4 variables. NOTE: The data set WORK.TEMP3 has 5 observations and 4 variables. 2992 %repet(print); 2993 %repet(hej); Note: Makrot hanterar inte parametervärdet HEJ Inne i ett makro är dessutom friheten avsevärd vad gäller att blanda makrosatser och datastegsatser. Vad som går är nästan bara att prova sig fram till. Generellt kan man dock säga att det går bra att utföra en viss datastegsats beroende på utfallet av en makrosats men det går inte att utföra en viss makrosats beroende på utfallet av en viss datastegsats. Följande makro är ett exempel på hur man kan låta ett makro generera upp DELAR av ett datasteg dynamiskt beroende på en eller flera inparametrar. %MACRO namn(namn); data namn; do i=1 to 10; %IF &namn eq KALLE %THEN %DO; fnamn="&namn"; Sidan 18

enamn='anka'; %ELSE %DO; fnamn='musse'; enamn='pigg'; output; end; %MEND namn; %namn(kalle); NOTE: The data set WORK.NAMN has 10 observations and 3 variables. 27 %namn(musse); NOTE: The data set WORK.NAMN has 10 observations and 3 variables. Detta makro är ett exempel på hur ett makro dynamiskt genererar upp delar av ett datasteg beroende på värden på globala makrovariabler (i stället för parametrar som skickas med till makrot) %LET k=100; %LET l=1000; %LET i=7; %MACRO n; data gfriend; set namn; length summa 8; %IF &i=7 %THEN %DO; summa=%eval(&k+&l); girl='mimmi'; %MEND n; %n; NOTE: The data set WORK.GFRIEND has 1 observations and 2 variables. NOTE: The DATA statement used 0.1 seconds. Ett exempel på hur man kan använda ett makro för att villkora DELAR av enskilda satser i ett datasteg. %MACRO dec(yesno); data dec&yesno; format dectal %IF &yesno eq YES %THEN %DO; 6.2 %ELSE %DO; 6. ; do i=1 to 10; dectal=i/2; output; end; %MEND dec; %dec(yes); NOTE: The data set WORK.DECYES has 10 observations and 2 variables. %dec(no); NOTE: The data set WORK.DECNO has 10 observations and 2 variables. Sidan 19

GRÄNSSNITTET MELLAN MAKROVARIABLER OCH DATASTEGET Även om man generellt inte kan låta en viss makrosats utföras beroende på utfallet från en datastegsats så kan man så att säga öppna ett fönster mellan datasteget och makroprocessorn med hjälp av SYMPUT och SYMGET funktionerna. Med dessa kan man hämta in värden från makrovariabler till datasteget med SYMGET och placera värden från datasteget i makrovariabler. Med andra ord kan man låta ett datasteg uppdatera en makrovariabel och sedan låta denna makrovariabel styra exekveringen i ett eller flera makron. På så sätt kan man i viss utsträckning alltså även styra makron från datasteg. Exempel på hur man hämtar in makrovariabler till ett datasteg med hjälp av funktionen symget: %LET x1=kalle; %LET x2=anka; %MACRO smgt; data twofig; set namn; if mod(_n_,2)=0 then do; fnamn=symget('x1'); enamn=symget('x2'); end; %MEND smgt; %smgt; NOTE: The data set WORK.TWOFIG has 10 observations and 3 variables. Ett exempel på hur ett datasteg uppdaterar makrovariabler med SYMPUT. %MACRO smpt; data twofig; set namn; if fnamn='musse' then call symput('x1','mimmi'); else call symput('x2','kajsa'); %PUT &x1 &x2; %MEND smpt; *-Kör makrot -*; %smpt; Man kan till och med symputta ut ett variabelvärde för att sedan hämta in det i en annan sats. %LET x1=knatte; %LET x2=fnatte; %MACRO smptgt; data twofig2; set twofig; if fnamn='musse' then call symput('x1','mimmi'); else call symput('x2','kajsa'); if fnamn='musse' then girl=symget('x1'); Sidan 20

else girl=symget('x2'); %MEND smptgt; *-Kör makrot -*; %smptgt; Sidan 21

Kompilering och exekvering Ett makro kompileras genom att SUBMITTA koden. Efter kompilering sparas det kompilerade makrot som en katalog medlem i SAS-katalogen SASMACR i WORK biblioteket. Därifrån är makrot sedan tillgängligt under sessionen och exekveras genom att man ger dess namn som ett makrokommando (%NAMN). Detta innebär vidare att man också kan ta bort makrot från WORK om man vill städa efter sig. Detta görs genom att använda PROC CATALOG. Vidare möjliggör det också att distribuera enbart kompilerade makron till användare (så att källkoden skyddas). *- Ta bort makrot SMPTGT från sasmacr katalogen -*; proc catalog catalog=work.sasmacr entrytype=macro; delete smptgt; quit; När ett makro exekveras sker ett återkommande samspel mellan makroprocessorn och SAS systemet. När word-scannern stöter på en makroreferens el. dyl. lämnas kontrollen över till makroprocessorn som exekverar makrosatser. Den SAS-text makrosatserna genererar läggs till i input stacken som därefter exekveras av SAS systemet. Detta samspel förklarar vad SAS kommer att se när ett makro körs. I bilderna nedan visas vad SAS ser i den högra stacken och vad makroprocessorn hanterar i den vänstra. Exemplet är trivialt, men illustrerar samspelet mellan kompilatorn och makroprocessorn. Sidan 22

ATT AUTOMATISKT REFERERA LAGRADE MAKRON Eftersom SASMACR katalogen förvalt ligger i WORK är den temporär och måste skapas för varje ny SAS-session. Det finns fler metoder för att slippa att manuellt kompilera upp makron inför varje session. Frågan är om man vill att SAS automatiskt ska kompilera upp befintliga makron som antingen ligger lagrade i textfiler eller som SOURCE-medlemmar i en katalog, eller om man vill att SAS ska referera redan kompilerade makros som ligger som MACRO-medlemmar i en katalog. Den senare metoden innebär att man kan leverera en uppsättning kompilerade makron i ett system så att källkoden till dessa är skyddade. De två alternativen implementeras som följer: För att SAS automatiskt ska kompilera ett makro (källkod) när det refereras används följande options: options MAUTOSOURCE SASAUTOS=(libname1 eller sökväg1...) För att SAS ska referera redan kompilerade makron i en SASMACR katalog i ett permanent SAS bibliotek används följande options: options MSTORED SASMSTORE=libname Om ett makro sedan anropas med %makronamn kommer SAS först kontrollera om makrot finns i WORK.SASMACR, sedan i libname.sasmacr och köra den första versionen som hittas. Sidan 23

SAS makro options och debugging För att debugga ett makro finns ett antal användbara options som man kan sätta i SAS. Samtliga options stängs av genom att skriva options Nooptionnamn; Option MPRINT gör att SAS skriver de SAS-satser ett macro producerar till loggen. Detta är mycket användbart eftersom det ibland kan bli rätt svårt att genomskåda vilka SAS-satser ett makro verkligen har genererat. options mprint; %MACRO test; %IF &SYSDAY=Thursday %THEN %DO; %DO i=1 %TO 2; proc summary data=temp; var var&i; output out=temp&i mean=mvar&i; %MEND test; *-Kör makrot-*; %test; FÖLJANDE TEXT SKRIVS TILL LOGGEN (Om det råkar vara torsdag, annars genererar makrot ingenting i exemplet ovan): MPRINT(TEST): MPRINT(TEST): MPRINT(TEST): MPRINT(TEST): PROC SUMMARY DATA=TEMP; VAR VAR1; OUTPUT OUT=TEMP1 MEAN=MVAR1; RUN; NOTE: The data set WORK.TEMP1 has 1 observations and 3 variables. NOTE: The PROCEDURE SUMMARY used 0.22 seconds. MPRINT(TEST): MPRINT(TEST): MPRINT(TEST): MPRINT(TEST): PROC SUMMARY DATA=TEMP; VAR VAR2; OUTPUT OUT=TEMP2 MEAN=MVAR2; RUN; NOTE: The data set WORK.TEMP2 has 1 observations and 3 variables. NOTE: The PROCEDURE SUMMARY used 0.22 seconds. Kommentar: Förutom att man på detta sätt kan läsa i klartext vad makrogeneratorn genererat till SAS, kan det ibland vara praktiskt att kunna testa stegvis vad ett makro har genererat för att se vart det gick fel. Genom att använda option MPRINT och helt enkelt kopiera in delar av loggen till programeditorn och ta bort MPRINT( ) på varje rad kan man köra de steg som makrot genererat. Ibland mycket användbart. SASoption MLOGIC skriver i loggen vilka macrosatser som utförs, hur loopar itererar och hur villkor faller ut (sant/falskt). Sidan 24

*-Stäng av MPRINT, sätt på MLOGIC-*; options nomprint mlogic; *-Kör samma makro som ovan-*; %test; FÖLJANDE TEXT SKRIVS TILL LOGGEN (Om det är torsdag): MLOGIC(TEST): Beginning execution. MLOGIC(TEST): %IF condition &sysday=thursday is TRUE MLOGIC(TEST): %DO loop beginning; index variable I; start value is 1; stop value is 2; by value is 1. NOTE: The data set WORK.TEMP1 has 1 observations and 3 variables. NOTE: The PROCEDURE SUMMARY used 0.22 seconds. MLOGIC(TEST): %DO loop index variable I is now 2; loop will iterate again. NOTE: The data set WORK.TEMP2 has 1 observations and 3 variables. NOTE: The PROCEDURE SUMMARY used 0.27 seconds. MLOGIC(TEST): %DO loop index variable I is now 3; loop will not iterate again. MLOGIC(TEST): Ending execution. SASoption SYMBOLGEN visar vilket värde en makrovariabel löser upp till när den används. options nomlogic symbolgen; %test; SYMBOLGEN: Macro variable SYSDAY resolves to Thursday SYMBOLGEN: Macro variable I resolves to 1 SYMBOLGEN: Macro variable I resolves to 1 SYMBOLGEN: Macro variable I resolves to 1 NOTE: The data set WORK.TEMP1 has 1 observations and 3 variables. NOTE: The PROCEDURE SUMMARY used 0.22 seconds. SYMBOLGEN: Macro variable I resolves to 2 SYMBOLGEN: Macro variable I resolves to 2 SYMBOLGEN: Macro variable I resolves to 2 NOTE: The data set WORK.TEMP2 has 1 observations and 3 variables. NOTE: The PROCEDURE SUMMARY used 0.33 seconds. Kommentar för MLOGIC och SYMBOLGEN: Dessa options genererar vanligtvis rätt stora loggar eftersom det är mycket text som ska skrivas ut. Ofta vet man ungefär vart i makrot det går snett och vilken/vilka makrovariabler man vill se för att kunna reda ut problemet. I dessa fall kan det vara bättre att själv manuellt lägga in %PUT-satser i makrot på lämpliga ställen. Loggen blir betydligt mer lättläst på detta sätt. Ett litet exempel på ett lite krångligare och mer svårgenomskådligt exempel nedan: %MACRO test(inparm); %LET x=%eval(%substr(&systime,4,2)/10); %PUT ******* X-variabeln innan loopen: &x ******; Sidan 25

%DO i=1 %TO 10; %IF &inparm=3 and &x>0 %THEN %LET i=10; %LET x=%eval(&inparm/%substr(&sysdate,1,1)); %PUT ******* X-variabeln efter loopen: &x ******; %MEND test; MAKROT TESTKÖRS SEDAN MED LITE OLIKA INPARAMETERVÄRDEN FÖR ATT SE HUR DET BETER SIG OCH FÖLJANDE SKRIVS TILL LOGGEN: %test(3); ******* X-variabeln innan loopen: 3 ****** ******* X-variabeln efter loopen: 1 ****** 31 %test(2); ******* X-variabeln innan loopen: 3 ****** ******* X-variabeln efter loopen: 1 ****** 32 %test(34); ******* X-variabeln innan loopen: 3 ****** ******* X-variabeln efter loopen: 17 ****** Debugging tips Om makrot inte gör något alls leta efter uteblivna %END. Använd %PUT för att se vad macro variabler är. Glöm inte att skilja på %PUT (makrokod) och PUT (i datasteg). Om makrot inte vill kompileras ordentligt leta efter uteblivna %. Sidan 26

Sammanfattning Makrovariabler innehåller textsträngar och kan användas för att infoga text i SAS-kod kan användas i heltalsberäkningar med hjälp av funktionen %EVAL kan vara lokala eller globala. Förvalda som globala om dom skapas utanför ett makro, förvalda som lokala om de skapas i ett makro (och de inte redan finns som globala). SAS ger en rad automatiska makrovariabler Makrofunktioner SAS har en rad makrofunktioner, de flesta rör stränghantering funktionen %EVAL används för att beräkna ett uttryck, men hanterar bara heltal och returnerar bara heltalsdelen av uttrycket Makron kan användas för att villkora utseendet på datasteg och proceduranrop inför ett visst mått av traditionell programmering i datasteget Använd options MPRINT, MLOGIC, SYMBOLGEN samt egna %PUT-satser för debugging kompileras genom submit och sparas sedan som ett entry i katalogen WORK.SASMACR kan kompileras automatiskt genom att använda options SASAUTOS/MAUTOSOURCE= kan sparas som kompilerad MACRO medlemmar i en katalog för att sedan automatiskt refereras med hjälp av options MSTORED SASMSTORE Sidan 27