Join Now

Juletip #14: Opret egne helligdags-funktioner med juletip #13

by SAS Employee OleSteen on ‎12-12-2014 10:41 PM (239 Views)

I går viste jeg et SAS program som beregner et års helligdage, og Georg kom med en opfordring til at bruge denne kode til at oprette min egen SAS-funktion - så her er den + en enkelt mere.

Jeg har tidligere skrevet om brugerdefinerede funktioner, men møder stadig mange som ikke kender til eksistensen, så jeg tænkte at et ekstra weekend-juletip jo ikke skader.

SAS-funktioner kan oprettes i SAS version 9, og gemmes i en lidt speciel SAS-tabel.

Fordelen ved at gemme funktionalitet i en brugerdefineret funktion, er dels at sikre samme funktionalitet for alle der bruger funktionen, samt det at bruge funktioner er velkendt for de fleste.

For at anvende brugerdefinerede funktioner skal optionen CMPLIB sættes til at pege på den tabel hvori funktionerne er gemt. Normalt sættes denne i brugerens CONFIG- eller AUTOEXEC-fil, men i nedenstående eksempler har jeg gemt funktionerne i WORK, og du kan altså teste dem uden at ændre din opsætning.

PROC FCMP skal kun køres én gang, og funktionskaldet sker på helt samme vis som du kalder øvrige SAS funktioner.

Sådan kunne koden til en funktion HELLIGDAG se ud:

/*******************************************************************/

/* Dette program opretter funktionen Helligdag                     */

/* Funktionen har et input-argument, en numerisk SAS-dato          */

/* Der returneres en tekststreng med typen af helligdag eller      */

/* en tom streng.                                                  */

/*******************************************************************/

/* Denne option gør at du kan anvende brugerdefinerede funktioner  */

option cmplib=work.function;

/* Normalt gemmes funktioner permanent i et andet library end work */

/* og skal dermed kun køres såfremt der sker ændringer i funktion- */

/* aliteten. Option CMPLIB sættes normalt i Config eller Autoexec  */

proc fcmp outlib=work.function.funcs;

  function Helligdag(Dato) $25;

  length retur $25;

  aar = year(Dato);

  if weekday(Dato) = 7 then retur = "Lørdag";

    else if weekday(Dato) = 1 then retur = "Søndag";

    else if Dato = mdy(06,05,aar) then retur = "Grundlovsdag";

    else if Dato = mdy(12,24,aar) then retur = "Juleaftensdag";

    else if Dato = mdy(12,25,aar) then retur = "Juledag";

    else if Dato = mdy(12,26,aar) then retur = "2. juledag";

    else if Dato = mdy(01,01,aar) then retur = "Nytårsdag";

    else do;

      paaske = holiday('easter',aar);

      if Dato = paaske-3 then retur = "Skærtorsdag";

      else if Dato = paaske-2 then retur = "Langfredag";

      else if Dato = paaske+1 then retur = "2.Påskedag";

      else if Dato = paaske+26 then retur = "Store bededag";

      else if Dato = paaske+39 then retur = "Kr. himmelfart";

      /*Ikke helligdag for alle */   

      else if Dato = paaske+40 then retur = "Dag efter Kr. himmelfart";

      else if Dato = paaske+50 then retur = "2. pinsedag";

      else retur = "";

    end;

    return(retur);

  endsub;

run;

quit;

Og for at se om det virker, kan dette lille datastep anvendes:

DATA Dage;

  FORMAT Dato DDMMYYp10.;

  DO Dato = '01JAN2015'D TO '31DEC2015'D;

     Helligdag = HELLIGDAG(Dato);

     OUTPUT;

  END;

RUN;

En afart af ovenstående funktionalitet kan f.eks. anvendes til at finde antal arbejdsdage mellem 2 datoer.

SAS-kode som opretter funktionen ARBDAGE:

/*******************************************************************/

/* Dette program opretter funktionen ArbDage                       */

/* Funktionen har 2 input-argumenter: fra- og til-dato             */

/* Der returneres en numerisk værdi, som angiver antallet af       */

/* arbejdsdage mellem de 2 datoer.                                 */

/*******************************************************************/

/* Denne option gør at du kan anvende brugerdefinerede funktioner  */

option cmplib=work.function;

/* Normalt gemmes funktioner permanent i et andet library end work */

/* og skal dermed kun køres såfremt der sker ændringer i funktion- */

/* aliteten. Option CMPLIB sættes normalt i Config eller Autoexec  */

proc fcmp outlib=work.function.funcs;

  function ArbDage(FDato, TDato);

  if Fdato > TDato then do;

    put "ERROR: Value from > value to";

    retur = .;

  end;

  else do;

    length retur 8;

    do i = FDato to TDato;

      paaske = holiday('easter',year(i));

      if weekday(i) = 7 then retur + 0;

      else if weekday(i) = 1 then retur + 0;

      else if i = mdy(06,05,year(i)) then retur + 0;

      else if i = mdy(12,24,year(i)) then retur + 0;

      else if i = mdy(12,25,year(i)) then retur + 0;

      else if i = mdy(12,26,year(i)) then retur + 0;

      else if i = mdy(01,01,year(i)) then retur + 0;

      else do;

        if i = paaske then retur + 0;

        else if i = paaske-3 then retur + 0;

        else if i = paaske-2 then retur + 0;

        else if i = paaske+1 then retur + 0;

        else if i = paaske+26 then retur + 0;

        else if i = paaske+39 then retur + 0;

        /* Ikke helligdag for alle */

        else if i = paaske+40 then retur + 0;

        else if i = paaske+50 then retur + 0;

        else retur + 1;

      end;

    end;

  end;

  return(retur);

  endsub;

run;

quit;

Og her et lille program som kan anvendes til test:

   

DATA TestFunktioner;

  FORMAT FraDato TilDato DDMMYYP10.;

  DO FraDato='01jan2015'D to '31dec2015'D;

     Uge = WEEK(FraDato,'V');

     TilDato = INTNX('WEEK.2',FraDato,0,'E');

     ArbejdsDage=ARBDAGE(FraDato,TilDato);

     OUTPUT;

  END;

RUN;

At oprette egne funktioner i SAS er faktisk ret sjovt, og go' gammeldags kode.

God jul.

PS! Den 14. har siden jeg var barn været en af mine yndlingsdatoer - så skal jeg nemlig kun bruge 2 hænder til at tælle ned til jul Smiley HappySmiley HappySmiley Happy

/Ole Steen