admin管理员组

文章数量:1125578

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 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.

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.

Share Improve this question edited 2 days ago Joel Coehoorn 415k114 gold badges577 silver badges813 bronze badges asked 2 days ago Kit CKit C 257 bronze badges 2
  • This question is similar to: Converting DataTable to Dictionary using LINQ in VB.NET. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. – Filburt Commented 2 days ago
  • As a general pointer, look for LINQ, but the related duplicate should already give you an idea. – Filburt Commented 2 days ago
Add a comment  | 

1 Answer 1

Reset to default 3

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.

本文标签: Dynamically adding to a VBnet ObjectStack Overflow