Storing Range attributes as an object?
I am having problems with how I have developed this little report that I am doing. Is it possible to create a variable for Range object in Excel VBA to apply formatting to another range? Here's my example:
I am creating a dictionary from Microsoft Scripting Runtime Library:
Dim d as Scripting.Dictionary
With this, I add labels, values ββand (tries to add) ranges.
Dim rng as Range
rng.Font.Bold = True
d.Add 1, Field("test1", 12345, rng)
rng.Font.Bold = False
d.Add 2, Field("TestTwo", "Testing field", rng)
rng.HorizontalAlignment = xlCenter
d.Add 3, Field("threeeee", 128937912, rng)
Dim key As Variant
For Each key In d.keys
Range("A" & key).value = d(key).Label
Set Range("B" & key).value = d(key).rng
Next key
Here is my Field function:
Private Function Field(Label As String, val As Variant, rng As Range) As cField
Dim f As New cField
f.Label = Label
f.val = val
Set f.rng = rng
Set Field = f
End Function
And here is my cField class:
Option Explicit
Dim mVarValue As Variant
Dim mStrLabel As String
Dim mRng As Range
Property Let val(ByVal val As Variant)
mVarValue = val
End Property
Property Get val() As Variant
val = mVarValue
End Property
Property Let Label(ByVal val As String)
mStrLabel = val
End Property
Property Get Label() As String
Label = mStrLabel
End Property
Property Let rng(ByVal val As Range)
Set mRng = val
End Property
Property Get rng() As Range
Dim a As Range
a.value = mVarValue
Set rng = a
End Property
The idea is that the key in the dictionary will be the string location for the field. Thus, if changes need to be made to the report I am creating, the only thing that needs to be changed is the key to that particular value in the dictionary. I have successfully saved the label for the value and the value itself, but I also want to keep the formatting for that range (bold, alignment, borders, etc.).
I get the error "91": "Object variable" or "Block variable error does not set" on the line immediately after the rng declaration. I am wondering if it is not possible to have a common range that does not have room in the sheet, or if some of my syntax is off.
Any help would be greatly appreciated! :)
source to share
Is it possible to create a variable for a Range object in Excel VBA, for the purpose of applying formatting to a different range?
I am wondering if it is not possible to have a generic Range that does not take place in the sheet ...
The short answer is no.
Quick answer: I suggest creating a format worksheet that can be hidden or very hidden that contains ranges or name ranges with the required formatting. This allows you to select a .Copy
"formatted" range and then use the range .PasteSpecial xlPasteFormats
.
I don't like overwriting the custom clipboard, but it's difficult to programmatically copy the formatting from one range to another. I use this method in numerous solutions because it is flexible, maintainable, reusable, and does not rely on complex code. Moreover, I can visually change the formatting without touching the code.
source to share
Good question! Unfortunately, I don't think you can keep a range that hasn't been initialized with an existing range of cells in your sheet. I can imagine several options:
- Use a hidden sheet to store range information.
- Store range information manually, in multiple member variables
Option 1 may be the easiest, even though it sounds like overkill to have an extra sheet. I present one hidden worksheet defined specifically for this purpose.
Option 2 can be simplified if you only need to keep track of a few properties of a range (such as border and color).
source to share
You're right - it's impossible to have a shared Range object. You must "Set" your range variable to some actual range in order to read and write your properties.
But if you "give" your rng property, then it looks like you already have a range reference. Why do you have a Let rng property if you are not going to use that property in the Get statement.
source to share
How about this solution?
Create a class with
-
range address as text, i.e.
"$A$3:$A$11,$A$18:$A$24,$D$29"
... -
Value
-
Save the formatting of the range as format text.
Then you can create a range Range(RangeAdressAsText)
and use something like the following
Private Sub ApplyFormatting(r As Range, ByVal f As String)
On Error GoTo ErrHandler:
f = UCase$(f)
Dim IterateRange As Range
Dim Formatarray() As String
Formatarray = Split(f, " ")
Dim i As Integer
With r
For i = LBound(Formatarray) To UBound(Formatarray)
Select Case Formatarray(i)
Case "BOLD"
.Font.Bold = True
Case "ITALIC"
.Font.Italic = True
Case "TOP"
.VerticalAlignment = xlTop
Case "BOTTOM"
.VerticalAlignment = xlBottom
Case "UNDERLINE"
.Font.Underline = True
End Select
Next i
End With
Erase Formatarray
Exit Sub
ErrHandler:
LogInformation Format(Now, "yyyy-mm-dd hh:mm:ss") & " - " & ": @ ApplyFormatting in xlPrinter " & " - " & Err.Number & " - " & Err.Description & " - " & Err.Source & " - " & Err.LastDllError
End Sub