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

The below is the macro that i am writing, can i know where am i missing

options mprint mlogic;
%Macro AVTLF_Num(ID=);

%* Print macro version *;
%Global gvar;
%Local mname mver;
%Let mname = AVTLF_Num;
%Let mver = 001;
%If %Index(&gvar, &mname) = 0 %Then %Do;
    %Let gvar =&gvar &mname;
    %Put AV Macro: &mname : &mver;
    %End;

%* Concatenating the variables tabno, titl1 and creating new variable called t_num*;
%If %Upcase(&id) = "TAB" %Then %Do;

%If %Sysfunc(lengthn(tabno))=0 %Then 
%Do;
%Put ERROR:AVTLF_Num:TABNO variable value missing;
	%Goto exit;
%End;

%If %Sysfunc(prxmatch('/[^A-Z 0-9]/i',tabno)) %Then
    %Do; special=%Sysfunc(prxchange('s/[A-Z 0-9 .]//i',-1,tabno))
%End;
%If special ne '' %Then %Do;
	%Put ERROR:AVTLF_Num: TABNO variable has Invalid characters;
	%Goto exit;
	%End;

 t_num=%Sysfunc(compbl('Table '||tranwrd(tabno,'.0','.')||title1));
 drop title1;
 rename t_num=title1;

%end;

%else %If %Upcase(&id) = "FIG" %Then %Do;

%if %Sysfunc(lengthn(figno))=0 %Then 
%Do;
%Put ERROR:AVTLF_Num:FIGNO variable value missing;
	%Goto exit;
%End;

%If %Sysfunc(prxmatch('/[^A-Z 0-9]/i',figno)) %Then
    %Do; special=%Sysfunc(prxchange('s/[A-Z 0-9 .]//i',-1,figno))
%End;
%If special ne '' %Then %Do;
	%Put ERROR: AVTLF_Num: FIGNO variable has invalid characters;
	%Goto exit;
	%End;

 t_num=%Sysfunc(compbl('Figure '||tranwrd(figno,'.0','.')||title1));
 drop title1;
 rename t_num=title1;
%end;

%exit: 

%Mend;

the below is the error

Spoiler
ERROR: Macro keyword DO appears as text.
ERROR: A dummy macro will be compiled.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword END appears as text.
ERROR: There is no matching %IF statement for the %ELSE.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword MEND appears as text.

any help please

1 ACCEPTED SOLUTION

Accepted Solutions
Quentin
Super User

Thanks for posting the code you want to generate:


if index(upcase(tabno),'X') then delete;
if tabno="" then delete;
tabnox=compbl('Table '||tranwrd(tabno,'.0','.')||title1);
drop title1;
rename tabnox=title1;



if index(upcase(figno),'X') then delete;
fignox=compbl('Figure '||tranwrd(figno,'.0','.')||title1);
drop title1;
rename fignox=title1;

 


When writing a macro, it's always good to start with working SAS code.

 

One way to generate the above code, would be a macro like below (untested):

 

 

%macro VTLF_Num(var=,prefix=) ;

  if index(upcase(&var),'X') then delete;
  if &var="" then delete;
  &var.x=compbl("&prefix"||tranwrd(&var,'.0','.')||title1);
  drop title1;
  rename &var.x=title1;

%mend VTLF_Num ;


 

 

Note that those a IF statements, not %IF statements.  The macro language is about code generation and text substitution.  I took the block of code you posted, put it into a macro, and replaced two parts of the code with macro variables.  You would call the code like:

 

 

data test.tab;
  set tab ;
  %VTLF_Num(var=tabno, prefix=Table)
run;
data test.fig;
  set fig ;
  %VTLF_Num(var=figno, prefix=Figure)
run;

If that looks reasonable to you, I would then go back to the non-macro code and try adding in the DATA step code to create the error messages you want.  After that DATA step code is working, you can add it into the macro. 

 

 

 

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.

View solution in original post

16 REPLIES 16
Kurt_Bremser
Super User

To make something like this work:

%If %Upcase(&id) = "TAB" %Then %Do;

the macro parameter must be supplied with quotes.

%Sysfunc(lengthn(tabno))

will always result in 5, as the word tabno is 5 characters long. To address a macro variable called tabno, use the ampersand. You can NOT use data step variables in macro code, as the macro preprocessor works before any data step variables exist.

 

What should this macro do? If it is about changes to data in dataset(s), supply the dataset(s) and the expected result after the operation.

 

Keep in mind that the macro language is always for creating dynamic code, not for manipulating data.

Ravindra_
Quartz | Level 8
Basically i am trying to manipulate the data within a data, i was asked to do this using a macro by populating the error messages if the text field is having any special character apart from numbers and a period. even i am wondered why they are doing this, but i am helpless with the requirement and bound to do this and trying my best to put this in a macro
Tom
Super User Tom
Super User

@Ravindra_ wrote:
Basically i am trying to manipulate the data within a data, i was asked to do this using a macro by populating the error messages if the text field is having any special character apart from numbers and a period. even i am wondered why they are doing this, but i am helpless with the requirement and bound to do this and trying my best to put this in a macro

Before attempting to use a macro to generate the SAS code to check the data start by making an actual SAS data step that can check the data.  Then you can decide which parts of that data step need to be changed.  Is it just the dataset name?  Just the variable name? Both?

Kurt_Bremser
Super User
Asked by whom?
Your idiot boss?
A clueless colleague?
Your university instructor who sees this as a challenge?
Anyway, start by defining the task. Show the data you have, and the expected result.
Ravindra_
Quartz | Level 8

Its my boss, I was not able to convince my boss in saying No.

Coming to the macro the below is the requirement which is very simple without a macro and i did that in 2 simple steps, but using macro they has some requirements. I had attached two different datasets, the macro must be applied on both datasets in a two individual data steps and the condition for these must be applied within the macro itself.

***Basically the core requirement is very simple the tabno in both these datasets need to be concatenated with title1 variable, if the dataset is tab then we need to concatenate along with a text "Table" or "Figure" as "Table"||tabno||title1 or "Figure"||figno||title1 respectively for tab and fig datasets.

But the requirement starts here as below

1) This should not be applied directly on the dataset itself it should be developed as a macro.

2) Within the macro we need to have a version added

3) We need to add a error message within the macro if there is a special character other than '.' in the variable tabno or figno

4) We need to add a warning message if there is a text called "Table" or "Figure" already in the title1 variable.

5) The final result variable is created for reference and the variable name is present within the Tab dataset as tabnox. My plan drop the original tilte1 and rename this tabnox to title1 at the end.

 

Finally the macro should resolve within a datastep.

 

Hope i had provided the required info.

 

 

Tom
Super User Tom
Super User

That is NOT a very reasonable description of a macro or for that matter anything at all.

 

What is the INPUT?

What do you want to do? 

Does it generate any code?  What code?

What do the datasets you provided have to to with the requirements?

Is the requirement to compare the two datasets?

Is the requirement to actually produces the figures and tables listed in those datasets? How would you do that?

Ravindra_
Quartz | Level 8

What is the INPUT?--- Input is having two datasets that were attached

What do you want to do?--- It is a simple modification of a variable title1, where the we need to concatenate (tabno from TAB dataset to title1 variable in TAB dataset) and also (figno from FIG dataset to title1 variable in FIG dataset), and this need to be done in two different datasteps, but we need to have a same macro for this to resolve.

Does it generate any code?  What code? the below is the code that was done within a datatep, but we need to do that by resolving the same within a macro. The actual logic that i am trying to do is creating the variable tabnox and fignox in two different datasteps and that's all, but the requirement is to do that using a macro by adding version date and also adding the warning message if there is any other special characters in tabno or figno variable apart from '.'.

data test.tab;
set tab;
if index(upcase(tabno),'X') then delete;
if tabno="" then delete;
tabnox=compbl('Table '||tranwrd(tabno,'.0','.')||title1);
drop title1;
rename tabnox=title1;
run;

data test.fig;
set fig;
if index(upcase(figno),'X') then delete;
fignox=compbl('Figure '||tranwrd(figno,'.0','.')||title1);
drop title1;
rename fignox=title1;
run;

 

What do the datasets you provided have to to with the requirements? The datasets were the raw datasets where we need to work

Is the requirement to compare the two datasets? Its not comparison, its a modification of a variable title1 variable in both the datasets TAB and FIG, the logic is given above, but we need the above as a macro with few other additions like warning message for invalid special characters.

Is the requirement to actually produces the figures and tables listed in those datasets? How would you do that? The datasets are used to produce tables and figures and we have got many other macros that work on these two datasets to produce tables and listings.

Quentin
Super User

Thanks for posting the code you want to generate:


if index(upcase(tabno),'X') then delete;
if tabno="" then delete;
tabnox=compbl('Table '||tranwrd(tabno,'.0','.')||title1);
drop title1;
rename tabnox=title1;



if index(upcase(figno),'X') then delete;
fignox=compbl('Figure '||tranwrd(figno,'.0','.')||title1);
drop title1;
rename fignox=title1;

 


When writing a macro, it's always good to start with working SAS code.

 

One way to generate the above code, would be a macro like below (untested):

 

 

%macro VTLF_Num(var=,prefix=) ;

  if index(upcase(&var),'X') then delete;
  if &var="" then delete;
  &var.x=compbl("&prefix"||tranwrd(&var,'.0','.')||title1);
  drop title1;
  rename &var.x=title1;

%mend VTLF_Num ;


 

 

Note that those a IF statements, not %IF statements.  The macro language is about code generation and text substitution.  I took the block of code you posted, put it into a macro, and replaced two parts of the code with macro variables.  You would call the code like:

 

 

data test.tab;
  set tab ;
  %VTLF_Num(var=tabno, prefix=Table)
run;
data test.fig;
  set fig ;
  %VTLF_Num(var=figno, prefix=Figure)
run;

If that looks reasonable to you, I would then go back to the non-macro code and try adding in the DATA step code to create the error messages you want.  After that DATA step code is working, you can add it into the macro. 

 

 

 

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
Ravindra_
Quartz | Level 8
thank you, this worked for me, so i was doing %IF instead of IF and that caused the issue.
PaigeMiller
Diamond | Level 26

When there are errors in a macro, please turn on the macro debugging tools by running this command.

 

options mprint symbolgen;

 

Then run the macro again and show us the ENTIRE log for this macro. Please copy the ENTIRE log as text and paste it into the window that appears when you click on the </> icon.

PaigeMiller_0-1663012019648.png

--
Paige Miller
Ravindra_
Quartz | Level 8
ERROR: Macro keyword DO appears as text.
ERROR: A dummy macro will be compiled.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword END appears as text.
ERROR: There is no matching %IF statement for the %ELSE.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword MEND appears as text.

The above is the error message after trying to resolve this macro

PaigeMiller
Diamond | Level 26

I did ask for the ENTIRE log. I made the word ENTIRE red twice to emphasize this point. Partial logs are of no use to us.

--
Paige Miller
Ravindra_
Quartz | Level 8
 ;*';*";*/;quit;run;
2          OPTIONS PAGENO=MIN;
3          %LET _CLIENTTASKLABEL='NO98072A_D10_Reference_data_v1_0.sas';
4          %LET _CLIENTPROCESSFLOWNAME='Standalone Not In Project';
5          %LET _CLIENTPROJECTPATH='';
6          %LET _CLIENTPROJECTPATHHOST='';
7          %LET _CLIENTPROJECTNAME='';
8          %LET _SASPROGRAMFILE='C:\Users\ravindra.babu\OneDrive - OneWorkplace\Projs\NO8072A - RP
8        ! PRO\Datasets\NO98072A_D10_Reference_data_v1_0.sas';
9          %LET _SASPROGRAMFILEHOST='GB3ADEW0212355L';
10         
11         ODS _ALL_ CLOSE;
12         OPTIONS DEV=SVG;
13         GOPTIONS XPIXELS=0 YPIXELS=0;
14         %macro HTML5AccessibleGraphSupported;
15             %if %_SAS_VERCOMP_FV(9,4,4, 0,0,0) >= 0 %then ACCESSIBLE_GRAPH;
16         %mend;
17         FILENAME EGHTML TEMP;
18         ODS HTML5(ID=EGHTML) FILE=EGHTML
19             OPTIONS(BITMAP_MODE='INLINE')
20             %HTML5AccessibleGraphSupported
21             ENCODING='utf-8'
22             STYLE=HtmlBlue
23             NOGTITLE
24             NOGFOOTNOTE
25             GPATH=&sasworklocation
26         ;
NOTE: Writing HTML5(EGHTML) Body file: EGHTML
27         
28         data anat.defn_tab;
29          %AVTab_Setup(ds=structure, cols=16);
30          %AVTLF_Num(ID=Tabno);
ERROR: Macro keyword DO appears as text.
ERROR: A dummy macro will be compiled.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword END appears as text.
ERROR: There is no matching %IF statement for the %ELSE.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword IF appears as text.
ERROR: Macro keyword PUT appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword END appears as text.
ERROR: Macro keyword MEND appears as text.
31          set defn.tab;
2                                                          The SAS System                              18:45 Friday, October 7, 2022

32          if index(upcase(tabno),'X') then delete;
33          if tabno="" then delete;
34         
35         /*tabnox=compbl('Table'||tranwrd(tabno,'.0','.')||title1);*/
36         /*drop title1;*/
37         /*rename tabnox=title1;*/
38         
39         run;
40         
41         %LET _CLIENTTASKLABEL=;
42         %LET _CLIENTPROCESSFLOWNAME=;
43         %LET _CLIENTPROJECTPATH=;
44         %LET _CLIENTPROJECTPATHHOST=;
45         %LET _CLIENTPROJECTNAME=;
46         %LET _SASPROGRAMFILE=;
47         %LET _SASPROGRAMFILEHOST=;
48         
49         ;*';*";*/;quit;run;
50         ODS _ALL_ CLOSE;
51         
52         
53         QUIT; RUN;
54         

The above is the total log that was generated

PaigeMiller
Diamond | Level 26

The above is the total log that was generated

 

Hello @Ravindra_ , I gave complete instructions for how to deliver the log so that it will be useful to us. Its not good if you only follow part of the instructions and don't follow the rest of the instructions, and yet I have to keep asking for you to follow the instructions. The part in blue was not done, and so the log provided is not useful. Here's what I said, please perform the part in blue as well as following the rest of the instructions:

 

When there are errors in a macro, please turn on the macro debugging tools by running this command.

 

options mprint symbolgen;

 

Then run the macro again and show us the ENTIRE log for this macro. Please copy the ENTIRE log as text and paste it into the window that appears when you click on the </> icon.

--
Paige Miller

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
  • 16 replies
  • 3230 views
  • 2 likes
  • 5 in conversation