BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
David_Billa
Rhodochrosite | Level 12

I would like to understand how to tackle the multilple conditions in do, if and else if. Any help to arrange the do blocks from below profram in right way? I guess first three do blocks are not in right way. 

 

In the below program, if the flag value is 1, then I want target="&nl_path"||"/"||filename; but after executing the program it produces target="&lh_path"||"/"||filename;. It looks last else statement had statisfied instead of second if. Flag value is correctly appearing it as 1. So I want target="&nl_path"||"/"||filename;

 

data files ;
  length id 8 msg filename source target $256 ;
  did=dopen("source");
  if did<=0 then do;
      msg=sysmsg(); 
      put msg; 
      stop;
  end;
  do id=1 to dnum(did);
    filename=dread(did,id);

    if scan(lowcase(filename),-1,'.')='csv' then do;
      source="&inpath" ||"/"|| filename;
      flag = 0;

    do i = 1 to countw("&nl_rb.",",");
     if indexw(filename,scan("&nl_rb.",i,","),"_") then do;
     flag = 1;
     target="&nl_path"||"/"||filename;
   end;
   end;

     if indexw(filename,'_copied') and  "&function" EQ 'LH' then do;
        target="&lh_path"||"/"||transtrn(filename,'_copied',trimn(' '));
        end;

     else if indexw(filename,'_copied') and  "&function" EQ 'NL' then do;
        target="&nl_path"||"/"||transtrn(filename,'_copied',trimn(' '));
      end;

      else target="&lh_path"||"/"||filename;
    end;
    output;
  end;
  did=dclose(did);
  drop did msg;
run;

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Kurt_Bremser
Super User

MAXIM 34.

MAXIM 34.

MAXIM 34.

WORK

IN

STEPS

!!!

 

Test your conditions separately on an example string in a simple data step, so you can make sure they work BEFORE you use them in a larger piece of code where they are harder to debug.

 

Separate the directory read out into its own data step, so you get a dataset with all filenames to inspect first.

 

And make it a habit to use consistent indentation, so you can visually identify the blocks:

data files ;
length
  id 8
  msg filename source target $256
;
did = dopen("source");
if did <= 0
then do;
  msg = sysmsg(); 
  put msg; 
  stop;
end;
do id=1 to dnum(did);
  filename = dread(did,id);
  if scan(lowcase(filename),-1,'.') = 'csv'
  then do;
    source = "&inpath" ||"/"|| filename;
    flag = 0;
    do i = 1 to countw("&nl_rb.",",");
      if indexw(filename,scan("&nl_rb.",i,","),"_")
      then do;
        flag = 1;
        target = "&nl_path"||"/"||filename;
      end;
    end;
    if indexw(filename,'_copied') and "&function" eq 'LH'
    then do;
      target = "&lh_path"||"/"||transtrn(filename,'_copied',trimn(' '));
    end;
    else if indexw(filename,'_copied') and "&function" eq 'NL'
    then do;
      target="&nl_path"||"/"||transtrn(filename,'_copied',trimn(' '));
    end;
    else target = "&lh_path"||"/"||filename;
    /* this most likely causes your problems;
    if _copied is not present, this statement will override anything else */
  end;
  output;
end;
did = dclose(did);
drop did msg;
run;

See my comment remark. Making your code readable (Maxim 12) quickly let me see where the issue might be.

Your final block should be simplified to this:

    if indexw(filename,'_copied')
    then do;
      if "&function" eq 'LH'
      then target = "&lh_path"||"/"||transtrn(filename,'_copied',trimn(' '));
      else if "&function" eq 'NL'
      then target="&nl_path"||"/"||transtrn(filename,'_copied',trimn(' '));
    end;

You might want to add a check for values of &function not in (LH,NL).

View solution in original post

7 REPLIES 7
andreas_lds
Jade | Level 19

You may want to add some text explaining what the program should do and what it is doing wrong.

David_Billa
Rhodochrosite | Level 12

updated my initial post.

David_Billa
Rhodochrosite | Level 12

@Kurt_Bremser In the filename there is no string called '_copied' is available. So this condition 

indexw(filename,'_copied')

 should not statisfy. 

Shmuel
Garnet | Level 18

@David_Billa wrote:

@Kurt_Bremser In the filename there is no string called '_copied' is available. So this condition 

indexw(filename,'_copied')

 should not statisfy. 


If there is no '_copied' substring in the filename it explains the output you get, as the last ELSE is

else target="&lh_path"||"/"||filename;

 

Shmuel
Garnet | Level 18

You can shorten the next code:

  if indexw(filename,'_copied') and  "&function" EQ 'LH' then do;
        target="&lh_path"||"/"||transtrn(filename,'_copied',trimn(' '));
        end;

     else if indexw(filename,'_copied') and  "&function" EQ 'NL' then do;
        target="&nl_path"||"/"||transtrn(filename,'_copied',trimn(' '));
      end;

      else target="&lh_path"||"/"||filename;

 

 

by replacing it to:

  if indexw(filename,'_copied') then do;
    if  "&function" EQ 'LH' then 
        target="&lh_path"||"/"||transtrn(filename,'_copied',trimn(' '));
    else if "&function" EQ 'NL' then 
        target="&nl_path"||"/"||transtrn(filename,'_copied',trimn(' '));
  end;
  else target="&lh_path"||"/"||filename;
Kurt_Bremser
Super User

MAXIM 34.

MAXIM 34.

MAXIM 34.

WORK

IN

STEPS

!!!

 

Test your conditions separately on an example string in a simple data step, so you can make sure they work BEFORE you use them in a larger piece of code where they are harder to debug.

 

Separate the directory read out into its own data step, so you get a dataset with all filenames to inspect first.

 

And make it a habit to use consistent indentation, so you can visually identify the blocks:

data files ;
length
  id 8
  msg filename source target $256
;
did = dopen("source");
if did <= 0
then do;
  msg = sysmsg(); 
  put msg; 
  stop;
end;
do id=1 to dnum(did);
  filename = dread(did,id);
  if scan(lowcase(filename),-1,'.') = 'csv'
  then do;
    source = "&inpath" ||"/"|| filename;
    flag = 0;
    do i = 1 to countw("&nl_rb.",",");
      if indexw(filename,scan("&nl_rb.",i,","),"_")
      then do;
        flag = 1;
        target = "&nl_path"||"/"||filename;
      end;
    end;
    if indexw(filename,'_copied') and "&function" eq 'LH'
    then do;
      target = "&lh_path"||"/"||transtrn(filename,'_copied',trimn(' '));
    end;
    else if indexw(filename,'_copied') and "&function" eq 'NL'
    then do;
      target="&nl_path"||"/"||transtrn(filename,'_copied',trimn(' '));
    end;
    else target = "&lh_path"||"/"||filename;
    /* this most likely causes your problems;
    if _copied is not present, this statement will override anything else */
  end;
  output;
end;
did = dclose(did);
drop did msg;
run;

See my comment remark. Making your code readable (Maxim 12) quickly let me see where the issue might be.

Your final block should be simplified to this:

    if indexw(filename,'_copied')
    then do;
      if "&function" eq 'LH'
      then target = "&lh_path"||"/"||transtrn(filename,'_copied',trimn(' '));
      else if "&function" eq 'NL'
      then target="&nl_path"||"/"||transtrn(filename,'_copied',trimn(' '));
    end;

You might want to add a check for values of &function not in (LH,NL).

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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
  • 7 replies
  • 644 views
  • 4 likes
  • 4 in conversation