BookmarkSubscribeRSS Feed
556
Calcite | Level 5 556
Calcite | Level 5

How can I modify the program to create a macro call cust?

What macro variable should i create?

Requirements:

1. I want to use ID as the dataset name

2. I want to use macro parameter to set the default value

%cust(m_ID=A999999, m_loanamt=2000000, m_loandate=12325, m_int=0.02, m_remainperiod=300, m_period=300)

https://mega.co.nz/#!3JlmjQTZ!Kc8DLXWUOpNAiLXlCfpliVSquXb6L4nsyjbpcXNMQwM

data ID;

  year=period/12;

  sch_pay=((int/12)*loanamt*((1+int/12)**(period)))/((1+int/12)**(period)-1);

  total_int_paid=0;

  balance=loanamt;

  a=remainperiod;

  do i=1 to period;

  payment_date=intnx('month',loandate,i);

  paidint=round(balance*int/12);

  principal=round(sch_pay-paidint);

  balance=balance-principal;

  if balance<0 then balance=0;

  total_int_paid=total_int_paid+paidint;

  remainperiod=period-i;

  if remainperiod<a then output;

  end;

  drop a i;

run;

6 REPLIES 6
Kurt_Bremser
Super User

Define your macro like that:

%macro cust(m_ID,m_loanamt,m_loandate,m_int=,m_remainperiod,m_period);

data &m_ID;

  year=&m_period/12;

  sch_pay=((int/12)*&m_loanamt*((1+int/12)**(&m_period)))/((1+int/12)**(&m_period)-1);

  total_int_paid=0;

  balance=&m_loanamt;

  a=&m_remainperiod;

  do i=1 to &m_period;

  payment_date=intnx('month',&m_loandate,i);

  paidint=round(balance*int/12);

  principal=round(sch_pay-paidint);

  balance=balance-principal;

  if balance<0 then balance=0;

  total_int_paid=total_int_paid+paidint;

  remainperiod=period-i;

  if remainperiod<a then output;

  end;

  drop a i;

run;

%mend;

556
Calcite | Level 5 556
Calcite | Level 5

THANKS!!!!

I just have one more question...

I have a dataset name Customer(https://mega.co.nz/#!bEdT1YDL!ClZbMH870hsNb7PecJRUt9GAlrYVM8EK6YgYQOSVios)

A1.CustomerIDNAMELOANAMTLOANDATEINTPERIOD
REMAINPERIODYEAR
1A2015539CCHAN TAT MAN25682871/18/20110.0236018030
2A2013223HHUNG BA NAM420000005/01/2014....

I want to create another macro call amort

How can I modify the program below to create a new macro call amort and apply the previous macro %cust to generate a report for EACH customer by using %amort only?

data _null_;

  set A1.Customer;

  if int=. then int=0.02;

  if period=. then do;

  year=25;

  remain=year*12;

  period=year*12;

  end;

run;

proc print data=ID label;

  title "Loan amortization for NAME";

  format payment_date date9.;

  label payment_date='Date of payment';

  var payment_date sch_pay total_int_paid balance paidint principal;

run;

Kurt_Bremser
Super User

You will need a where condition based on the macro parameter.

Also, proc print supports by group processing, so you could do everything in one sweep, without wrapping it in a macro.

You may also take a look at proc report for generating complex reports, including by group processing.

If you still feel you need to do it with macro language, consult this:

SAS(R) 9.4 Macro Language: Reference, Third Edition

556
Calcite | Level 5 556
Calcite | Level 5

(This question specifically ask us to create a new macro call amort)

I tried but i cannot solve the problem by myself

%macro amort;

    data _null_;

        set sasuser.Customer end=final;

        if int=. then

            int=0.02;

        if period=. then

            do;

                year=25;

                remainperiod=year*12;

                period=year*12;

            end;

        if final then

            call symputx('m_n', _n_);

        if not final then

            do;

                call symputx('m_ID'!!left(_n_), ID);

                call symputx('m_loanamt'!!left(_n_), loanamt);

                call symputx('m_loandate'!!left(_n_), loandate);

                call symputx('m_int'!!left(_n_), int);

                call symputx('m_remainperiod'!!left(_n_), remainperiod);

                call symputx('m_period'!!left(_n_), period);

                call symputx('m_name'!!left(_n_), name);

            end;

    run;

    %put _user_;

    %do i=1 %to &m_n;

        %cust(&&m_ID&i, &&m_loanamt&i, &&m_loandate&i, &&m_int&i,

            &&m_remainperiod&i, &&m_period&i);

        proc print data=&&m_ID&i label;

            title "Loan amortation for &&m_name&i";

            var payment_date sch_pay total_int_paid balance paidint principal;

            format payment_date date9.;

            label payment_date='Date of payment';

        run;

    %end;

%mend amort;

When I use %amort(), my program stopped here

LOG:

WARNING: Apparent invocation of macro CUST not resolved.

%cust(&&m_ID&i, &&m_loanamt&i, &&m_loandate&i, &&m_int&i, &&m_remainperiod&i, &&m_period&i);

  _

  180

proc print data=&&m_ID&i label; title "Loan amortation for &&m_name&i"; var payment_date

sch_pay

ERROR 180-322: Statement is not valid or it is used out of proper order.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

That error is telling you that the macro code for cust has not been run(or sucessfully).  Can I suggest to read up on macro language if you go down that route, however I agree with KurtBremser, I see no need to use any macro code here, there a basic coding options, e.g. #byval, by group processing etc. 

556
Calcite | Level 5 556
Calcite | Level 5

Solved... Just by restarting SAS software= =

sas-innovate-wordmark-2025-midnight.png

Register Today!

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.


Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 6 replies
  • 1589 views
  • 0 likes
  • 3 in conversation