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

Hello-

 

I'm creating a set of macro variables that will sweep across a line of text and increment new values for "Start" and "End" fields based on the position of the pointer for the last value + 1. As the pointer sweeps across the line, it is searching for a specific character using the findc() function. Each time it finds that character, it uses that as the "End" value for the last field and the "Start" value for the next field plus 1:

 

Here's a sample of a line of text:

 

         ƒƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆ

 

So, we know that the text begins in column 9 and the specific character that the findc() function is seeking is the 'ˆ'. This means that for the first field, we can set the start value to 9 and the end value to 18 since the 'ˆ' is the 18th character in the text. For each successive field, based on the position of the 'ˆ', the start and end values look like this:

 

Field   Start   End

  1         9       18

  2        19      28

and so on

 

The thing that makes this challenging is that the the End position can fluctuate, based on the line of text being processed. 

 

To assign the End values to a set of macro variables, I'm using the findc() function.

 

x=findc(text,'ˆ',start+1);

 

 I can't use "call symput" to assign a macro variable with the value of x because that will only resolve once the data step is completed. Similarly, the %let End=x; or %let End=%eval(x); don't work. 

 

How do I assign the value of "x" into a macro variable and use it in the same data step?

 

Thank you.

 

1 ACCEPTED SOLUTION

Accepted Solutions
Quentin
Super User

I'm very confused.  Here is something like what @Astounding described.  But personally, I've never had a situation where I had a DATA step in which I wanted to create macro variable from a data step variable and also use that macro variable within the same step.  Which is to say, it's possible I've never used SYMGET in real life.  So I'm guessing the below isn't really what you want.  I think maybe you need to describe more of the big picture.

 

The below code parses a text string, makes an array of macro varaibles using CALL SYMPUTX that store the location of each delimiter, and also uses those macro variables in a trivial assignment statement via SYMGET:

265  data a;
266    text="0000*000*00*";
267    start=findc(text,'*');
268    do i=1 to countc(text,'*')-1;
269      end  =findc(text,'*',start+1);
270      call symputx(cats("MacStart",i),start);
271      start=findc(text,'*',start+1);
272    end;
273    Start1=symget("MacStart1");
274    Start2=symget("MacStart2");
275
276    put (Text Start1 Start2)(=);
277  run;

text=0000*000*00* Start1=5 Start2=9
NOTE: The data set WORK.A has 1 observations and 6 variables.

278
279  %put &MacStart1 &MacStart2;
5 9
BASUG is hosting free webinars Next up: Jane Eslinger presenting PROC REPORT and the ODS EXCEL destination on Mar 27 at noon ET. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.

View solution in original post

12 REPLIES 12
LinusH
Tourmaline | Level 20
I have no clue of what you ate trying to do. But for you final question - it's sounds like an unnecessary round robin to create a macro variable that you wish to use in the same data step. Why not use a data step variable?
Data never sleeps
xtc283x
Quartz | Level 8

That won't work because I want to carry the values forward within the macro.

Astounding
PROC Star

The usual way (although legitimate applications are rare) to use a macro variable in the same DATA step is to retrieve it using SYMGET.

 

I suspect that this won't be sufficient here.  It appears that you really need a set of macro variables, not just one.  Consider naming macro variables START1, START2, etc. where the numeric suffix just increments each time you are moving on to the next segment of the text.

 

I would first look at the idea of creating DATA step variables.  You can always output their (multiple) values to a separate data set, within the same DATA step.  That would make them available later in the program.

xtc283x
Quartz | Level 8

Thank you.

 

In the interests of trying to keep my question simple, I didn't mention that there is an iterative string of macro variables that changes with the size of the text line.

 

And I am trying to do all of this within one data step. 

 

So, the question remains, how do I assign a scalar value to a macro variable if "call symput" and "%let" assignments don't work?

Astounding
PROC Star

You could create a single macro variable containing all the values:

 

  • Create a long character variable in the DATA step
  • Append to that character variable every time you find a new START value, leaving a single blank before appending
  • At the end of the DATA step, CALL SYMPUT takes a long string and copies it to a macro variable

You'll need to go through each number within the macro variable in later processing.  It might look like the equivalent of:

 

%let starts = 11 18 27 35 42 98;

 

 

Quentin
Super User

I'm very confused.  Here is something like what @Astounding described.  But personally, I've never had a situation where I had a DATA step in which I wanted to create macro variable from a data step variable and also use that macro variable within the same step.  Which is to say, it's possible I've never used SYMGET in real life.  So I'm guessing the below isn't really what you want.  I think maybe you need to describe more of the big picture.

 

The below code parses a text string, makes an array of macro varaibles using CALL SYMPUTX that store the location of each delimiter, and also uses those macro variables in a trivial assignment statement via SYMGET:

265  data a;
266    text="0000*000*00*";
267    start=findc(text,'*');
268    do i=1 to countc(text,'*')-1;
269      end  =findc(text,'*',start+1);
270      call symputx(cats("MacStart",i),start);
271      start=findc(text,'*',start+1);
272    end;
273    Start1=symget("MacStart1");
274    Start2=symget("MacStart2");
275
276    put (Text Start1 Start2)(=);
277  run;

text=0000*000*00* Start1=5 Start2=9
NOTE: The data set WORK.A has 1 observations and 6 variables.

278
279  %put &MacStart1 &MacStart2;
5 9
BASUG is hosting free webinars Next up: Jane Eslinger presenting PROC REPORT and the ODS EXCEL destination on Mar 27 at noon ET. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.
LinusH
Tourmaline | Level 20
Ok. If understand correctly you are defining the boundaries for "words" in a line of "text".
You have several lines of text, right?
For me being able to help further I think knowing about the requirement would help. What are you going to do with the macro variables? What will be the end product of this processing (show a sample for this as well).
Data never sleeps
xtc283x
Quartz | Level 8

Thanks to everyone for their helpful comments. Quentin, I've adapted your code into something like what I need for the challenge I'm facing. To your point, as of right now the symget function for "numx" isn't resolving.

 


options nomacrogen nomlogic nosymbolgen nomprint;
options macrogen mlogic symbolgen mprint;

%macro loops;

data a;
text=" ƒƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆ";

start=findc(text,'ˆ');

do i=1 to countc(text,'ˆ');
end =findc(text,'ˆ',start+1);
call symputx(cats("MacStart",i),start);
start=findc(text,'ˆ',start+1);
end;
j=i-1;
call symputx('Num',put(j,3.));

Numx=symget("&&num");
put numx=;
/*
array startx Macstartx1 - Macstartx&&numx;
%do a=1 %to &&numx;
Startx=symget("MacStart&&a");
%end;

%put &num %do a=1 %to &&numx; &MacStart&&a %end;;
*/

run;

%put &num &numx;

%do a=1 %to &# &&&&MacStart&&a %end;;

%mend;
%loops

 

The part that's commented out presumes that &&numx resolves correctly.

 

Thanks again.

Quentin
Super User
I think @LinusH is right. People could help better if you described the full problem and desired result. It's not clear if the macro language will be helpful.

That said, when you code:
call symputx('Num',put(j,3.));
Numx=symget("&&num");
The first line makes a macro variable named Num. If you want to use SYMGET to read the value of that macro var, it would be Numx=symget("Num"). No ampersands. As written it will try to resolve macro reference &&Num when the step compiles. Which won't work.

That said, in the commented out code you are trying to use &&Numx on an array statement. There is no NUMX macro var created anywhere. Even if it were created during the execution of this data step, it could not be used to define an array in the same step, because the array statement works at compile time.

I think if you describe the desired output you want from your input text string (or perhaps 2 or 3 text strings), people will be able to help better.

(Apologies for formatting, I'm on my phone)
BASUG is hosting free webinars Next up: Jane Eslinger presenting PROC REPORT and the ODS EXCEL destination on Mar 27 at noon ET. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.
xtc283x
Quartz | Level 8

I'm struggling to keep this question manageable. Obviously, it's challenging enough as it is. I'm not opposed to describing what I'm trying to accomplish but am reluctant to do so. Doing so is no guarantee that the confusion will be resolved. It could well only add fuel to the fire.

 

That said, it sounds like correcting the ampersands for symget() won't work as hoped in the given data step. So, I'm back to the drawing board.

 

Thanks to everyone for their helpful suggestions.

Reeza
Super User
If the collective experience above look at your code and say its too convoluted, it likely is. It's mostly a matter of do you want to get your way working or do you want an efficient solution.
xtc283x
Quartz | Level 8

Fortunately, no one has seen my code! That said, I'm sure it's not efficient but the suggestions that have been made have helped me get to a new, workable solution.

 

Thanks to all!

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
  • 12 replies
  • 2567 views
  • 1 like
  • 5 in conversation