I isolated the do-loop/scan, and got it to work:
34 %let dim_cd = CPRIC COST SALE FCST VEHPE FCSTE PRICE INV;
35 %macro generate_fact_csv;
36 %do j = 1 %to %sysfunc(countw(&dim_cd));
37 %let val = %scan(&dim_cd, &j);
38 %put &val.;
39 %end;
40 %mend generate_fact_csv;
41 %generate_fact_csv;
CPRIC
COST
SALE
FCST
VEHPE
FCSTE
PRICE
INV
Suggest that you either try to use macro debugging options like symbolgen, mprint mlogic, or reducing the macro until this part works.
@Aexor wrote:
This is working , but as I said inside this do loop I have other do loops where I am checking for date_sk.. that portion should iterate also as this Value do loop.
So, which specific loop is not working as expected?
What specifically is it not doing as expected?
What exactly is expected.
Are you sure you are talking about a %do loop (which is quite different from a Do loop) or a %do /%end block? You have multiple %do and it is not at all clear which is the problem. We do not have any of your data so can't actually run this code. (Hint)
Also you have macro variables such as &planning_lib that we have no idea where/when that is set.
You have multiple select into macro variables that you then iterate over values. If any of the values of the variables placed into those macro variables include any of the %scan delimiters then 1) the Countw over them will be incorrect and 2) values extracted to use one at a time are likely NOT to be valid where you use them. Again, we don't have any of your data to confirm if that might be problem.
Set OPTIONS MPRINT MLOGIC;
Run your macro.
Share the log from running with all the generated code and messages. Copy the log text and paste into a text box on the forum opened using the </> icon above the message window. (Should do the same with CODE as the forum reformats pasted text and code we see may not actually be what you submit)
That is a lot of code, and without data, it's hard to guess where the problem could be. But if you're focused on this part:
%do i = 1 %to %sysfunc(countw(&tab));
%let value = %scan(&tab, &i);
I would add some %PUT statements to show the value of the macro vars. Something like:
%put Before do loop: &=tab;
%do i = 1 %to %sysfunc(countw(&tab));
%let value = %scan(&tab, &i);
%put inside do loop: &=i &=value &=tab;
My guess is that will show that the macro variable TAB does not have the value you expect. It's also possible that there are characters in the value that are being treated as delimiters by %SCAN which you are not expecting.
You have there:
%do i = 1 %to %sysfunc(countw(&tab));
in line 76
and then you have:
%do i = 1 %to %sysfunc(countw(&date_sk_dis));
in line 123.
They share the index variable "i".
In your code, where is the %END statement for that first loop in your coed? And where is %END statement for the second?
Let's walk through the code and look for issues.
First thing I see is this INPUT() function call.
on input(t1.parameter_val, best12.) = t2.hierarchy_id
BEST is the name of a FORMAT. So what you are actually running is:
on input(t1.parameter_val, 12.) = t2.hierarchy_id
Which will only use the first 12 bytes of PARAMETER_VAL when converting it to a number. A more robust version would use the maximum width that the informat supports and also remove any leading spaces from the string.
on input(left(t1.parameter_val), 32.) = t2.hierarchy_id
The next issue is this list of dimension codes you are putting into a macro variable.
select dimension_cd into :dim_cd separated by ' '
From the way you later use the value you tease back out of the list in DIM_CD it looks like this is a CHARACTER variable.
%let val = %scan(&dim_cd, &j);
...
where dimension_cd = "&val"
What characters can be in the values of DIMENSION_CD? Could they include spaces? Or delimiters that %SCAN() would use? In which case you probably would want to place the quotes into the macro variable and take a little more care when teasing out an individual value from the list.
proc sql noprint;
select quote(trim(dimension_cd),"'") into :dim_cd separated by ' '
from dim_type_id_details;
%let n_dim_cd =&sqlobs;
quit;
...
%do j=1 %to &n_dim_cd ;
%let val = %scan(&dim_cd, &j, %str( ), q);
...
where dimension_cd = &val
The reason your %DO loops are stopping early is because you are changing the values of the iteration variable in the middle of the loop. If you write code like:
do i=1 to 10;
i=11;
end;
the loop will only run once and not 10 times
You have at least one place where you have nested a %DO I inside of another %DO I loop.
/* loooping throgh Fact table name */
%do i = 1 %to %sysfunc(countw(&tab));
...
%do i = 1 %to %sysfunc(countw(&date_sk_dis));
Use more descriptive loops.
Also can you explain what you are doing with all of this code? Is there not some way you could just keep the data in datasets an skip the whole process of putting it into macro variables and pulling it back out of macro variables?
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.
Ready to level-up your skills? Choose your own adventure.