Its a very common requirement to scale Font Size of the text whenever the shape is resized.

In many articles (see
DMVS 2002,
VisGuy,
Visio Insights) the solution offered to automatically scale Font Size (and sometimes Line Weight) when a shape is resized is based on the assumption that the user will not need to change the Font Size or Line Weight after the formulas are written.
Usually, the solution is:
LineWeight = 1 pt * Width / 2 inChar.Size = 12 pt * Width / 2 inproblem: User can mistakenly make changes to Font Size or Line Weight in the GUI and the formulas will be overwritten by single values.
some other solutions suggest:
LineWeight = GUARD(1 pt * Width / 2 in)Char.Size = GUARD(12 pt * Width / 2 in)Although, the scale behavior is correct; but the user is handcuffed. No changes allowed in the GUI for Font Size or Line Weight.
A better solution:
LineWeight = SETATREFEXPR(1 pt) * Width / 2 inChar.Size = SETATREFEXPR(12 pt) * Width / 2 inScale behavior is correct. User can make changes in GUI, however, if the change happen when
Width / 2 in does not equal to 1, then the User will see different result than desired.
The problem happens because of the
2 in value. It should not be a fixed value.
It should be semi-fixed!
The proper solution:create two User rows:
User.Width_LineWeight = 2 inUser.Width_CharSize = 2 inUse the following correct formulas:
LineWeight = SETATREFEXPR(1 pt) * Width / SETATREF(User.Width_LineWeight, SETATREFEVAL(Width))Char.Size = SETATREFEXPR(12 pt) * Width / SETATREF(User.Width_CharSize, SETATREFEVAL(Width))The trick lies in the time when
SETATREF(User.Width_LineWeight, SETATREFEVAL(Width)) get executed.
User.Width_LineWeight will get updated ONLY when the user makes changes to Line Weight in the GUI. Only then, our SETATREF() will set
User.Width_LineWeight to Width which means
Width / SETATREF(User.Width_LineWeight, SETATREFEVAL(Width)) will equal to 1.
When the user resizes the shape, the whole formula
SETATREFEXPR(1 pt) * Width / SETATREF(User.Width_LineWeight, SETATREFEVAL(Width)) will be evaluated WITHOUT setting new Width value to
User.Width_LineWeight!
It looks like SETATREF(cell_ref, set_expr) function executes set_expr and pass it to cell_ref when the change initiated from the same cell that this function is part of. In the event the change initiated from other cells, SETATREF(cell_ref, set_expr) will merely fetch the result from cell_ref without setting set_expr to cell_ref.
I am not sure if this is the correct explanation but this is how I find it behaving.
Attached is a working example.
Regards,
Yousuf.