I'm working with MiniExcel, trying to save values into a template--not really relevant except to explain why I need to use these specific types (Dictionary/Object). This is my VB.net conversion of some of the MiniExcel sample C# code, which works great:
Dim value As New Dictionary(Of String, Object)()
value("rows") = New Object() {
New With {.name = "Jack", .department = "HR"},
New With {.name = "Lisa", .department = "HR"}
}
MiniExcel.SaveAsByTemplate(path, templatepath, value)
What I need to do is loop through some data and add to value("rows")
dynamically instead of typing out static values like this, but I don't know the right words to search to figure out how to add to an Object this way.
In this case, the ()
at the end of the Object()
expression is part of the type name rather than a constructor method call and indicates you have an array.
In .NET, we have real arrays rather than the pseudo-array collections you get on many other platforms (.NET has those, too, but calls them what they are). This means .NET arrays have a fixed size. Therefore, to add to the array you have to allocate a whole new array and copy the data (this is what ReDim Preserve
does behind the scenes).
That's crazy-inefficient. Instead, I recommend converting this to a List
(which also tends to allocate new buffers and copy behind the scenes as you add items, but does it less often and gives you a better API for the process):
value("rows") = New List(Of Object) From {
New With {.name = "Jack", .department = "HR"},
New With {.name = "Lisa", .department = "HR"}
}
Now you can append with code like this:
Dim rows As List(Of Object) = DirectCast(value("rows"), List(Of Object) )
rows.Add(New With {.name = "New Name", .department = "New Dept" } )
But it's very strange in .NET to rely on the Object
type like this in the first place. You should mentally wince in discomfort every time you need to type Object
into your code and should really have Option Strict
or Option Infer
turned on (leaving it off is really only for compatibility when porting forward legacy vb6-era code) and define actual types for this data... especially the contents of the rows
collection. This helps avoid things like the ugly DirectCast()
call in the code above. If every entry will have a name
and department
property, you can make things waaaaaay easier on yourself by defining a short class for this:
Public Class Employee
Public Property Name As String = ""
Public Property Department As String = ""
Public Sub New(Name As String, Department As String)
Me.Name = Name
Me.Department = Department
End Sub
End Class
And then use it like this:
Dim value As New Dictionary(Of String, Object)()
value("rows") = New List(Of Employee) From {
New Employee("Jack", "HR"),
New Employee("Lisa", "HR")
}
The constructor is optional; you could still use an object initializer here if you wanted instead, but I'm old-school that way.
Even better if you can use a real type instead of the Dictionary, but I understand you may be at the mercy of the MiniExcel library.