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

Hi, I'm trying to import lots of text files and am having problems creating the macro variables which will allow me to do this.

I've been able to assign the file names to variables so when I run;

     %put _user_ ;

I get the following;

     filenm1     text_file_01326

     filenm2     text_file_14568

     filenm3     text_file_08554

     filenm4     text_file_99954

As these files have different schemas, I'm trying to create a second macro variable for each file identifying the schema.

The schema identifier is on the first line of the text file. I've isolated this record and am trying to use call symput to assign a value to a macro variable as such.

The macro loop works and the if then else block works but no macro variable gets assigned.

If I remove the strip function from the call symput, I get an error in the log stating;

     ERROR: Symbolic variable name Filetp           1 must contain only letters, digits, and underscores.

This indicates that the index function is correctly identifying the existance of the text in the var1 string and it's the call symput which is not functioning as I want.

I've read SUGI papers which suggest that the variables can in some instances be created locally but I don't think that this what's happening here.

I've also tried assigning numbers and SAS data set variables as macro values but this also hasn't worked.

Any help with this would be greatly appreciated.

Cheers,

Paul.

1 ACCEPTED SOLUTION

Accepted Solutions
art297
Opal | Level 21

The following worked for me:

data ob_2_1;

  var1='xx DMMT ss';

run;

data ob_2_2;

  var1='xx DDDD ss';

run;

data ob_2_3;

  var1='xx DMLN ss';

run;

%macro ftmac ;

  %do i = 1 %to 3 ;

    data _null_ ;

      set  ob_2_&i ; /*this data set contains only the first record from the text file*/

      if index(var1,'DMMT') ge 1 then do;

        %global %sysfunc(cats(filetp,&i.));

        call symput('filetp'||strip(&i),'DM1') ;

      end;

      else if index(var1,'DMLN') ge 1 then do;

        %global %sysfunc(cats(filetp,&i.));

        call symput('filetp'||strip(&i),'DM2') ;

      end;

    run ;

    %put _user_ ;

  %end ;

%mend ftmac ;

%ftmac

%put &filetp1. ;

View solution in original post

11 REPLIES 11
Astounding
PROC Star

Paul,

One problem lies in the first parameter to CALL SYMPUT.  Within the context of a DATA step, &i is a number where the software is looking for characters.  Change this:

strip(&i)

Instead, while this would be acceptable:

"&i"

It would be easier to just use a first parameter that looks like this (and use double quotes, not single):

"filetp&i"

This streamlines the situation, but doesn't really fix it.

Yes, it is true in your examples that the macro variables created by CALL SYMPUT will be %LOCAL, not %GLOBAL.  If you need to reference them once the macro has finished executing, add this statement as the first statement in the %DO loop:

%global filetp&i;

Good luck.

FatCaptain
Fluorite | Level 6

Hi Astounding,

Thanks for this. I've altered the code as you suggest but still no luck.

My original code generated this note in the SAS log which no longer appears.

   

     NOTE: Numeric values have been converted to character values at the places given by:

     (Line):(Column).

     1:1 1:1 1:1

Astounding
PROC Star

I've edited my answer a couple of times.  Sorry about that.  Please use the latest suggestions, and re-post what your program now looks like.

art297
Opal | Level 21

According to the test code I just ran your macro variables ARE being created, but only locally.  If you need them to be global, why not just add  %global statements creating them as global before you create them?

data ob_2_1;

  var1='xx DMMT ss';

run;

data ob_2_2;

  var1='xx DDDD ss';

run;

data ob_2_3;

  var1='xx DMLN ss';

run;

%macro ftmac ;

  %do i = 1 %to 3 ;

    data _null_ ;

      set  ob_2_&i ; /*this data set contains only the first record from the text file*/

      if index(var1,'DMMT') ge 1 then

       call symput('filetp'||strip(&i),'DM1') ;

      else if index(var1,'DMLN') ge 1 then

       call symput('filetp'||strip(&i),'DM2') ;

    run ;

    %put _user_ ;

  %end ;

%mend ftmac ;

%ftmac

%put &filetp1. ;

Astounding
PROC Star

Art,

OK, here's a headscratcher for you.

As you noticed, the macro variables are %LOCAL if you run the program as is. 

However, try adding this statement before running the macro:

%global i;

You'll find that the macro variables are now all %GLOBAL, including those generated by CALL SYMPUT.  The rules are that CALL SYMPUT will not force the creation of a %LOCAL symbol table.  When &I already exists in the %GLOBAL table, there is no local table needed and CALL SYMPUT is forced to add to the %GLOBAL table.  It's a case where you can look at the macro in its entirety, but can't tell ahead of time whether CALL SYMPUT will use the %GLOBAL or %LOCAL table.

art297
Opal | Level 21

The following worked for me:

data ob_2_1;

  var1='xx DMMT ss';

run;

data ob_2_2;

  var1='xx DDDD ss';

run;

data ob_2_3;

  var1='xx DMLN ss';

run;

%macro ftmac ;

  %do i = 1 %to 3 ;

    data _null_ ;

      set  ob_2_&i ; /*this data set contains only the first record from the text file*/

      if index(var1,'DMMT') ge 1 then do;

        %global %sysfunc(cats(filetp,&i.));

        call symput('filetp'||strip(&i),'DM1') ;

      end;

      else if index(var1,'DMLN') ge 1 then do;

        %global %sysfunc(cats(filetp,&i.));

        call symput('filetp'||strip(&i),'DM2') ;

      end;

    run ;

    %put _user_ ;

  %end ;

%mend ftmac ;

%ftmac

%put &filetp1. ;

FatCaptain
Fluorite | Level 6

Thank you both for your help with this.

Cheers,

Paul.

FriedEgg
SAS Employee

Instead of using %global and call symput you can do call symputx with the 'G' modifier.

Arthur Tabachneck wrote:

    data _null_ ;

      ...

        %global %sysfunc(cats(filetp,&i.));

        call symputx('filetp'||strip(&i),'DM1','G') ;

      ...

ArtC
Rhodochrosite | Level 12

The SYMPUTX routine will also eliminate the numeric to character conversion note as it does not expect the second argument to be character as does SYMPUT.

art297
Opal | Level 21

FriedEgg: Nice addition .. very much appreciated!

art297
Opal | Level 21

Astounding: Agreed, unless you force the issue as I did in my previous post

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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
  • 11 replies
  • 7323 views
  • 0 likes
  • 5 in conversation