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-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

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