0
votes

I'm still stucked with SAS special characters treatment.

 %macro mFormat();
    %do i=1 %to &numVar. ;
        proc format library = work ;
            invalue $ inf&&nomVar&i..s
            %do j=1 %to &&numMod&i.;
                "%superq(tb&i.mod&j.)" = &j.
            %end;
            ;
        run;
        proc format library = work ;
            value f&&nomVar&i..s
            %do k=1 %to &&numMod&i.;
                &k. = "%superq(tb&i.mod&k.)"
            %end;
            ;
        run;
    %end;
%mend mFormat;
%mFormat();

As you can see, the program supposes to create the format and the informats for each variable. My only problem is when the variable name resolves to Brand which contains

GOTAN-GOTAN
FRANCES-FRANCES
+&DECO-+DECO&
etc ...

These names leads me to this error

“ERROR: This range is repeated, or values overlap:”

I hope I can force SAS to read those names. Or perhaps, this is not the best approach to generate FORMATS and INFORMATS for variables that contain these characters( &, %, -, ', ").

2
Actually I don't see any wrong in dealing with special characters here. double quote is enough. I stripped down your code a little bit to test (pastebin.com/vXsE8KWw). In the result, number 8 is correctly translated to 'GOTAN-GOTAN'. And there is no error during processing. One thing which is confusing me that you use a do loop inside proc format. I don't know whether it is valid. Acutually value statements of proc format can be generated by macro. Please correct me if I understand in a wrong way.Robbie Liu

2 Answers

1
votes

Because your macro is using so many global macro variables, it's hard to see the problem. That error message indicates that your macro is genenerating duplicate ranges to PROC FORMAT. The complete error message should tell you which range is in error; if that is all you see, my guess is that more than more of your macro variables resolves to a blank.

There is no restriction on using hypens when defining PROC FORMAT ranges. I made up this little example to illustrate:

proc format library = work ;
   invalue infs
     'GOTAN-GOTAN'     = 1
     'FRANCES-FRANCES' = 2
     '+&DECO-+DECO&'   = 3;
   value fs
     1 = 'GOTAN-GOTAN'
     2 = 'FRANCES-FRANCES'
     3 = '+&DECO-+DECO&';
run;
data a;
   test = 'FRANCES-FRANCES';
   in_test = input(test,infs.);
   put test= in_test= in_test= fs.;
run;

Although you may find some trick to solve your macro problem, I'd suggest you toss that out and use the CNTLIN option of PROC FORMAT to use a data set to create your custom formats and informats. That would certainly make things easier to maintain and might also help create some useful metadata for your project. Here is a simple example to create the same format and informat as above:

data fmt_defs;
   length fmtname start label $32 type $1;

   fmtname = 'INFS';
   type = 'I';
   start = 'GOTAN-GOTAN';     label = '1'; output;
   start = 'FRANCES-FRANCES'; label = '2'; output;
   start = '+&DECO-+DECO&';   label = '3'; output;

   fmtname = 'FS';
   type = 'N';
   start = '1';  label='GOTAN-GOTAN';     output;
   start = '2';  label='FRANCES-FRANCES'; output;
   start = '3';  label='+&DECO-+DECO&';   output;
run;
proc format library = work cntLin=fmt_defs;
run;

You can find much more information about PROC FORMAT in the online documentation.

Good luck, Bob

1
votes

I think the hypen is the problem for the samples you provided. Maybe you could use a character replacement function to TRANSLATE the hyphen (or other problem characters) to something else like a space or underscore.

%Let Test=One-Two;
 %Put &test;
%Let Test=%sysfunc(translate(&test,%str(_),%str(-)));
 %Put &test;