Hi,
I was wondering why the style/merge does not provide the same result when style(calldef) is activated.
Is it a bug or is there another reason behind this result?
proc report data=sashelp.class;* style(calldef)=[foreground=white];
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[background=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style/merge' ,'style=[foreground=red]');
endcomp;
run;
Thanks
ps. as requested I had the picture when * style(calldef)=[foreground=white];
is activated
Hi,
After further investigations, here are my reasoning. Do you agree?
Part 1 - without style(calldef)
Example 1: using 'style'
in the second argument of compute age
block.
proc report data=sashelp.class;
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[foreground=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style' ,'style=[foreground=red]');
endcomp;
run;
To start with foreground=lightblue when gender=M.
Then,
gender='M'
and age=12
then the foreground
is changed to red
(John
is now in red
)gender ne 'M'
and age=12
then the foreground
which was not yet defined is set to red
.
Example 2: using 'style/merge'
in the second argument of the compute age
block.
proc report data=sashelp.class;
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[foreground=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style/merge' ,'style=[foreground=red]');
endcomp;
run;
To start with foreground=lightblue
when gender=M
.
Then,
gender='M'
and age=12
then foreground
remains lightblue
(John
is still in lightblue
)gender ne 'M'
and age=12
then the foreground
which was not yet defined is set to red
.
From these extra two examples, we understand that
- rule 1: for a given cell, the value of a given option is replaced when 'style'
(or 'style/replace'
) is used
- rule 2: for a given cell, the value of the already defined option is not changed when 'style/merge'
is used
These conclusions don't apply to style(calldef)
.
Example 3: using a mix of background=
and foreground=
as well as 'style'
What we didn't see in example 1, was that 'style'
does not just reset the given option, but the whole cell.
proc report data=sashelp.class;
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[background=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style' ,'style=[foreground=red]');
endcomp;
run;
In this example we see that John who had a light blue background to start with has now no background and a red foreground color.
Example 4: using a mix of background=
and foreground=
as well as 'style/merge'
proc report data=sashelp.class;
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[background=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style/merge' ,'style=[foreground=red]');
endcomp;
run;
When using 'style/merge'
, only options which were not set for a given value are added.
For this reason John
keeps his lightblue
background
and get now a red
foreground
.
From these extra two examples, we understand that
- rule 1(updated): for a given cell, the value of all the options is replaced when 'style'
(or 'style/replace'
) is used
- rule 2 (updated): for a given cell, the value of the already defined options is not changed when 'style/merge'
is used
Those conclusions don't apply to style(calldef)
Part 2 - with style(calldef)
Example 5: using style(calldef)
and 'style'
proc report data=sashelp.class style(calldef)=[foreground=white];
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[background=lightblue]');
endcomp;
run;
style(calldef)
only applies to values defined by call define
routines.
For this reason, Alice
is written in black
and not in white
.
Even if 'style'
is used, the white
foreground is kept (not reset to black
).
Example 6: using style(calldef)
proc report data=sashelp.class style(calldef)=[foreground=white];
columns name sex age height weight ;
define name--weight / display;
compute sex;
*if sex='M' then call define ('name' ,'style','style=[foreground=lightblue]');
if sex='M' then call define ('name' ,'style/merge','style=[foreground=lightblue]');
endcomp;
run;
Here foreground is used in both style(calldef)
and call define
routine.
The value given in call define has priority, even if 'style/merge'
is used. That's the tricky part!
Example 7: the original example in this post series
proc report data=sashelp.class style(calldef)=[foreground=white];
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[background=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style/merge' ,'style=[foreground=red]');
endcomp;
run;
Example 5 explains us why we have white
foreground
on lightblue
background
.
A background
and a foreground
is already defined when gender='M'
So, given that 'style/merge'
is used in the compute age
block, only females where age=12
get a red
foreground
.
Note: Ballardw comment on the impact of the variables order in the column
statement is an additional extra point to keep in mind. Here my compute
blocks follow the same order as the one given in the column
statement.
Hi:
That's odd. The code you posted worked for me. I limited the rows to ages 12 and 13 to make for a better screen shot. In my output, all the males have a blue background and the rows where age is 12 have a red foreground color:
Note how the rows for Jane and Louise have a red foreground color, but NOT a blue background color which I expect because they are 12 and they are female. On the other hand, all the rows for males do have a blue background color and the rows for James, John and Robert -- all 12 year old males have a blue background and a red foreground. I added the title to show my version of SAS.
I don't have any other versions of SAS to test with, so you might want to open a track with Tech Support.
Cynthia
Hi Cynthia,
The code works for me too for as long as style(calldef) is not used.
Have you tested it when style(calldef) is activated in proc report statement?
Best Regards
ps.
I strongly suggest that you explicitly state what values are appearing in the manner that you do not expect. By NAME and AGE.
Note that the order of the variables SEX and AGE on the column statement changes the result.
Hi:
I don't understand the purpose of the foreground=white on the CALLDEF override on the PROC REPORT statement. What were you trying to achieve when putting the override in the PROC REPORT statement? When you change the foreground to white, which would cause it to match the background? If you want to change the foreground to white when the background is blue, that would be better to do in the COMPUTE block where you're changing that background. I think you're running into a timing issue with PROC REPORT and the style overrides. I think in the long run you'd be better off NOT using the style override in the PROC REPORT statement and just delaying the compute block as late as possible by doing it on the last variable on the report row -- that way, after all the items are place on the report row, PROC REPORT only has to go back once and fiddle with the style override for the NAME cell. I'll see if I can come up with something that allows you to maintain your original order. I think with a revised IF in a COMPUTE block for WEIGHT, it can work and you won't need to use STYLE/MERGE.
Cynthia
Well, I could make it work with the override in the PROC REPORT statement and still maintain the original order of variables. I prefer the alternative example, because in the long run, I think it will be easier to maintain.
Indeed, changing the order in the column statement affect the result. I didn't notice that.
But do you understand why, given style/merge is used?
Unexpected result
My code before
proc report data=sashelp.class style(calldef)=[foreground=white];
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[background=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style/merge' ,'style=[foreground=red]');
endcomp;
run;
Expected result
Putting age before sex (and just for consistency, putting compute age... style, before compute sex style/merge
proc report data=sashelp.class style(calldef)=[foreground=white];
columns name age sex height weight ;
define name--weight / display;
compute age;
if age=12 then call define ('name' ,'style' ,'style=[foreground=red]');
endcomp;
compute sex;
if sex='M' then call define ('name' ,'style/merge','style=[background=lightblue]');
endcomp;
run;
Using style/merge in both compute statements would not change the result.
proc report data=sashelp.class nowd; columns name age sex height weight ; define name--weight / display; compute sex; if sex='M' then do; call define ('name' ,'style' ,'style=[background=lightblue foreground=white ]'); if age=12 then call define ('name' ,'style','style=[background=lightblue foreground=red]'); end; else if age=12 then call define ('name' ,'style','style=[foreground=red]'); endcomp; run;
Still haven't seen an explicit list of which values are "misbehaving" in terms of what you expect or want.
As a minimum you have two overrides going on, the Style(calldef) and then the compute blocks. Order of application is likely the issue between "conflicting" overrides. I don't know if there is anything in the documentation of which will "win" when there is a conflict. Generally I expect the lowest granularity override to appear, i.e. the compute block version over one set for the procedure. But interactions?? Which is why I have asked for the specific values that you are concerned about. Yes the values change. But which ones do you want to appear how has not been answered.
Hi,
After further investigations, here are my reasoning. Do you agree?
Part 1 - without style(calldef)
Example 1: using 'style'
in the second argument of compute age
block.
proc report data=sashelp.class;
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[foreground=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style' ,'style=[foreground=red]');
endcomp;
run;
To start with foreground=lightblue when gender=M.
Then,
gender='M'
and age=12
then the foreground
is changed to red
(John
is now in red
)gender ne 'M'
and age=12
then the foreground
which was not yet defined is set to red
.
Example 2: using 'style/merge'
in the second argument of the compute age
block.
proc report data=sashelp.class;
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[foreground=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style/merge' ,'style=[foreground=red]');
endcomp;
run;
To start with foreground=lightblue
when gender=M
.
Then,
gender='M'
and age=12
then foreground
remains lightblue
(John
is still in lightblue
)gender ne 'M'
and age=12
then the foreground
which was not yet defined is set to red
.
From these extra two examples, we understand that
- rule 1: for a given cell, the value of a given option is replaced when 'style'
(or 'style/replace'
) is used
- rule 2: for a given cell, the value of the already defined option is not changed when 'style/merge'
is used
These conclusions don't apply to style(calldef)
.
Example 3: using a mix of background=
and foreground=
as well as 'style'
What we didn't see in example 1, was that 'style'
does not just reset the given option, but the whole cell.
proc report data=sashelp.class;
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[background=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style' ,'style=[foreground=red]');
endcomp;
run;
In this example we see that John who had a light blue background to start with has now no background and a red foreground color.
Example 4: using a mix of background=
and foreground=
as well as 'style/merge'
proc report data=sashelp.class;
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[background=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style/merge' ,'style=[foreground=red]');
endcomp;
run;
When using 'style/merge'
, only options which were not set for a given value are added.
For this reason John
keeps his lightblue
background
and get now a red
foreground
.
From these extra two examples, we understand that
- rule 1(updated): for a given cell, the value of all the options is replaced when 'style'
(or 'style/replace'
) is used
- rule 2 (updated): for a given cell, the value of the already defined options is not changed when 'style/merge'
is used
Those conclusions don't apply to style(calldef)
Part 2 - with style(calldef)
Example 5: using style(calldef)
and 'style'
proc report data=sashelp.class style(calldef)=[foreground=white];
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[background=lightblue]');
endcomp;
run;
style(calldef)
only applies to values defined by call define
routines.
For this reason, Alice
is written in black
and not in white
.
Even if 'style'
is used, the white
foreground is kept (not reset to black
).
Example 6: using style(calldef)
proc report data=sashelp.class style(calldef)=[foreground=white];
columns name sex age height weight ;
define name--weight / display;
compute sex;
*if sex='M' then call define ('name' ,'style','style=[foreground=lightblue]');
if sex='M' then call define ('name' ,'style/merge','style=[foreground=lightblue]');
endcomp;
run;
Here foreground is used in both style(calldef)
and call define
routine.
The value given in call define has priority, even if 'style/merge'
is used. That's the tricky part!
Example 7: the original example in this post series
proc report data=sashelp.class style(calldef)=[foreground=white];
columns name sex age height weight ;
define name--weight / display;
compute sex;
if sex='M' then call define ('name' ,'style','style=[background=lightblue]');
endcomp;
compute age;
if age=12 then call define ('name' ,'style/merge' ,'style=[foreground=red]');
endcomp;
run;
Example 5 explains us why we have white
foreground
on lightblue
background
.
A background
and a foreground
is already defined when gender='M'
So, given that 'style/merge'
is used in the compute age
block, only females where age=12
get a red
foreground
.
Note: Ballardw comment on the impact of the variables order in the column
statement is an additional extra point to keep in mind. Here my compute
blocks follow the same order as the one given in the column
statement.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.