Create DLL file in VB.NET and use in Excel VBA - vb.net

I have created a DLL file in VB.NET and I want use it in Excel VBA. When I use it like a function it is working perfect but when I use sub with a ByRef variable it does not work and Excel restarts with an error.
The code in VB.NET is:
Public Function distinctArr(ByVal arr As String()) As String()
Return arr.ToList.Distinct.ToArray
End Function
Public Sub sortArr(ByVal arr As String(), ByRef a As String())
Dim tolist As List(Of String) = arr.ToList
tolist.Sort()
a = tolist.ToArray
End Sub
This is the code in VBA:
Dim objMda As Excelcode.mda
Set objMda = New Excelcode.mda
Dim distinc_Item() As String
Dim all_Items() As String
all_Items = rng_to_string(rng_rizmetre)
distinc_Item = objMda.distinctArr(all_Items) '''This line is working perfect
Dim Sorted_Item() As String
objMda.sortArr distinc_Item, Sorted_Item
What is wrong with the code?

Finally i can find my answer.
code in vb.net
Public Class MainClass
Sub sortArr(ByVal arr As String(), ByRef sortedarr As String())
sortedarr = arr
Array.Sort(sortedarr)
End Sub
End Class
and code in excel vba:
Sub aaa()
Dim Mycode As excelcode.MainClass
Set Mycode = New excelcode.MainClass
Dim arr(2) As String
arr(0) = "m"
arr(1) = "a"
arr(2) = "d"
Dim sortedArr() As String
ReDim sortedArr(0)
Mycode.sortArr arr, sortedArr
End Sub
by this code i can pass array byval to vb.net dll then vb.net pass sorted array.

Related

Using dictionary within structures

I have a structure that has a string and 2 dictionary variable. I don't know how to insert data into these dictionaries.
Public Structure librariesWithMedia
Dim strLibraryName As String
Dim dicBooksMedia As SortedDictionary(Of String, String)
Dim dicNonBooksMedia As SortedDictionary(Of String, String)
End Structure
Dim libraryMediaEntry As librariesWithMedia
This is my structure and this is how I'm storing the values.
libraryMediaEntry.dicBooksMedia.Add(key, value)
This gives me a null reference exception error. Can anyone help me understand and how I would have to take the data?
Your Structure MUST initialise/instantiate the dictionaries before you can use them.
Public Structure librariesWithMedia
'
Dim strLibraryName As String
Dim dicBooksMedia As SortedDictionary(Of String, String)
Dim dicNonBooksMedia As SortedDictionary(Of String, String)
'
Sub New(LibName As String)
strLibraryName = LibName
dicBooksMedia = New SortedDictionary(Of String, String)
dicNonBooksMedia = New SortedDictionary(Of String, String)
End Sub
'
End Structure
'
Dim libraryMediaEntry As librariesWithMedia
And then in your code, for example
Sub DoSomethingProcess()
'
libraryMediaEntry = New librariesWithMedia("Featured_Books")
libraryMediaEntry.dicBooksMedia.Add("James A Michener", "Chesapeake")
'
End Sub

Getting Installed Steam Games From Registry

Can someone help me with this error I'm getting? Error14 'Using' operand of type 'System.Collections.Generic.List(Of String)' must implement 'System.IDisposable'
Public Function GetInstalledGames() As Object
Dim enumerator As IEnumerator(Of String) = Nothing
Dim list As List(Of String) = Directory.GetFiles(String.Concat(Me.SteamPath, "\steamapps")).ToList()
Using strs As List(Of String) = New List(Of String)()
enumerator = list.Distinct().GetEnumerator()
While enumerator.MoveNext()
Dim current As String = enumerator.Current
If (current.Contains("appmanifest_") And current.Contains(".acf")) Then
strs.Add(Path.GetFileName(current).Replace("appmanifest_", "").Replace(".acf", ""))
End If
End While
End Using
Return strs
End Function
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
Dim enumerator As IEnumerator(Of String) = Nothing
Me.tbOutput.Text = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Me.SteamPath = Conversions.ToString(Me.GetSteamPath())
Using installedGames As List(Of String) = DirectCast(Me.GetInstalledGames(), List(Of String))
enumerator = installedGames.Distinct().GetEnumerator()
While enumerator.MoveNext()
Dim current As String = enumerator.Current
Me.lbGames.Items.Add(current)
End While
End Using
End Sub
Stop writing explicit enumerator loops for no reason
Make your functions return types that make sense instead of Object
Don’t sprinkle Using into code without knowing what it does
Pass data between functions through arguments, not class fields
Private Shared Function GetInstalledGames(steamPath As String) As IEnumerable(Of String)
Dim result As New List(Of String)
For Each name In Directory.GetFiles(Path.Combine(steamPath, "steamapps"))
If name.Contains("appmanifest_") AndAlso name.Contains(".acf") Then
result.Add(Path.GetFileNameWithoutExtension(name).Replace("appmanifest_", ""))
End If
Next
Return result
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs)
Me.tbOutput.Text = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Dim steamPath As String = Me.GetSteamPath()
For Each current In GetInstalledGames(steamPath).Distinct()
Me.lbGames.Items.Add(current)
Next
End Sub

"Object reference not set to an instance of an object" trying to extract embedded resources. (Visual Basic)

I have a part of my code that's supposed to extract an embedded source to a temp folder.
Sub Main()
Dim temp As String
temp = Path.GetTempPath()
Console.WriteLine(temp)
ExtractResourceToDisk("FileExtract.file.exe", temp & "file.exe")
Process.Start(temp & "file.exe")
End Sub
Public Function ExtractResourceToDisk(ByVal ResourceName As String, ByVal FileToExtractTo As String) As Boolean
Dim s As System.IO.Stream = System.Reflection.Assembly.GetExecutingAssembly.GetManifestResourceStream(ResourceName)
Dim ResourceFile As New System.IO.FileStream(FileToExtractTo, IO.FileMode.Create)
Console.WriteLine(s.Length)
Dim b(s.Length) As Byte
s.Read(b, 0, s.Length)
ResourceFile.Write(b, 0, b.Length - 1)
ResourceFile.Flush()
ResourceFile.Close()
ResourceFile = Nothing
End Function
However, I'm getting an "Object reference not set to an instance of an object" error on the line "Dim b(s.Length) As Byte" when I try to run.
Because Dim b(s.Length) As Byte throws the null reference exception it follows that s is null, and thus that:
System.Reflection.Assembly.GetExecutingAssembly.GetManifestResourceStream(ResourceName)
returns null (Nothing).
Double check the value of ResourceName and take a look at the accepted answer to:
GetManifestResourceStream returns NULL
Public Function ExtractResourceToDisk(ByVal ResourceName As String, ByVal FileToExtractTo As String) As Boolean
'New keyword is needed for creating instance
Dim s As New System.IO.Stream = System.Reflection.Assembly.GetExecutingAssembly.GetManifestResourceStream(ResourceName)
Dim ResourceFile As New System.IO.FileStream(FileToExtractTo, IO.FileMode.Create)
Console.WriteLine(s.Length)
Dim b(s.Length) As Byte
s.Length is return Null so the error occurs.
FYI as i attached tested snippets
Dim Str As String // if initilize Str variable it not shows the error
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim Test(Str.Length) As Byte
Test(0) = 123
End Sub

Sharing a List of(String) between Private Sub

In my code I basically read a textbox and put each line into a list (Of String) Dim "testblock" in code below
From there I create another list (of string) and split each line whenever a space is found. Dim "block" in code below
Now I want to be able to access that list from anywhere in the project.
How do I go about sharing a List of(String) between Private Sub such as form buttons?
Private Sub PhaseCodeBTN_Click(sender As Object, e As EventArgs) Handles PhaseCodeBTN.Click
Dim testblock As New List(Of String)
Dim lines As String() = TextBox1.Text.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
Dim block As New List(Of String)
For Each l As String In lines
testblock.Add(l)
Dim words As String() = BlockCodeBox.Text.Split(" ")
For Each splitword As String In words
block.Add(splitword)
Next
Next
BlockCodeBox.Text = testblock(BlockNumBox.Text)
WordCmdBox.Text = block(WordNumBox.Text)
End Sub
Private Sub PhaseBlackBTN_Click(sender As Object, e As EventArgs) Handles PhaseBlackBTN.Click
WordCmdBox.Text = block(WordNumBox.Text)
End Sub
Create a Public Shared Class with your List(Of String) there to use it anywhere in the project:
Public Shared Class DataHolder
Private _block As New List(Of String)
Public Property Block As List(Of String)
Get
Return _block
End Get
Set
_block = value
End Set
End Property
End Class
Example:
Either simply use DataHolder.Block.Add(splitword) OR following steps:
Declare a class variable block to use it in entire class:
Private block As List(Of String)
Initialize it in some suitable function / event-handler like Form_Load:
block = DataHolder.Block
Do the operation:
block.Add(splitword)

Array to combo box?

I have this structure, with an array of the structure type.
Structure CustomerAccountsRec
Dim strFirstName As String
Dim strLastName As String
Dim intAge As Integer
Dim strAddress As String
Dim strTown As String
Dim strPostcode As String
Dim strCusNum As String
End Structure
Public strCusArray() As CustomerAccountsRec
I want to be able to take the strCusNum of the array and populate a combobox with it but can't figure out how. Any help?
You can also override the ToString Method in your Structure as mentioned. I also created a List(Of CustomerAccountsRec) that makes it a bit easier to add values and then I bound the list to the ComboBox's DataSource
Public Class Form1
Structure CustomerAccountsRec
Dim strFirstName As String
Dim strLastName As String
Dim intAge As Integer
Dim strAddress As String
Dim strTown As String
Dim strPostcode As String
Dim strCusNum As String
Public Overrides Function ToString() As String
Return strCusNum
End Function
End Structure
Public strCusArray As List(Of CustomerAccountsRec) = New List(Of CustomerAccountsRec)
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Dim carec As CustomerAccountsRec = New CustomerAccountsRec
carec.strFirstName = "Hello"
carec.strLastName = "World"
carec.strCusNum = "Hello World"
carec.strTown = "AnyTown"
carec.strAddress = "AnyStreet"
carec.strCusNum = "12345678"
strCusArray.Add(carec)
ComboBox1.DataSource = strCusArray
End Sub
End Class
You can add the items using the ComboBox.Items.Add method, and for the structure to be properly displayed, you have to override it's ToString method.
See:
ComboBox: Adding Text and Value to an Item (no Binding Source)
how to add value to combobox item
You can use LINQ to get an array containing the items you want to display, and then bind that array to the ComboBox.
Dim combo as New ComboBox
combo.DataSource = strCusArray.Select(Function(f) f.strCusNum).ToArray()
If I understand your question.
The actual result of Public strCusArray() As CustomerAccountsRec is null, so we can't use this to add the all items from CustomerAccountsRec to ComboBox
To List all the item from your Structure we need to use the System.Reflection Namespace
Structure CustomerAccountsRec
Dim strFirstName As String
Dim strLastName As String
Dim intAge As Integer
Dim strAddress As String
Dim strTown As String
Dim strPostcode As String
Dim strCusNum As String
End Structure
Dim fi As FieldInfo() = GetType(CustomerAccountsRec).GetFields(BindingFlags.[Public] Or BindingFlags.Instance)
For Each info As FieldInfo In fi
ComboBox2.Items.Add(info.Name)
Next
Source: C# version