Update Textbox after each iteration VB.Net WPF - wpf

I have a For loop which runs through xlsx files in a directory, I need to append the filenames in a TextBlock after each loop and refresh the TextBlock to show the updated text.
The code I have below only displays the filenames after the loop has executed.
Dim lcFileName As String = ""
Dim fileArray() As String = Directory.GetFiles(txtDirectory.Text, "*.xlsx", SearchOption.AllDirectories)
For Each file As String In fileArray
Dim ExcelApp As Excel.Application = New Excel.Application
Dim Workbook As Excel.Workbook = ExcelApp.Workbooks.Open(file)
Dim Worksheet As Excel.Worksheet = Workbook.Sheets(1)
Dim Range As Excel.Range = Worksheet.UsedRange
Dim rowCount As Integer = Range.Rows.Count
Dim colCount As Integer = Range.Columns.Count
Dim tmpOrder(rowCount, colCount) As String
tbResults.Text = tbResults.Text + Environment.NewLine + Path.GetFileName(file) + " imported."
For i = 1 To rowCount
For j = 1 To colCount
'New line
If (i = 1 And j = 1) Then
tmpOrder(i - 1, j - 1) = Range.Cells(i, j).Value
lcFileName = tmpOrder(i - 1, j - 1).ToString()
Else
If (Not String.IsNullOrEmpty(Range.Cells(i, j).Value)) Then
tmpOrder(i - 1, j - 1) = Range.Cells(i, j).Value.ToString()
End If
End If
Next
Next
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(Worksheet)
Worksheet = Nothing
ExcelApp.ActiveWorkbook.Close(True)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(Workbook)
Workbook = Nothing
ExcelApp.Quit()
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(ExcelApp)
ExcelApp = Nothing
'
Next
Any help would be appreciated, VB.Net required.

Finally got it working.
Ok first I created my Method to update the TextBlock with the parameter passed for the filename.
Public Sub UpdateResults(ByVal lcFile As String)
tbResults.Text = tbResults.Text + Environment.NewLine + Path.GetFileName(lcFile) + " imported."
End Sub
In my For Loop i called the method with the following code
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, New ThreadStart(Sub() Me.UpdateResults(lcFile)))
Where UpdateResults(lcFile) is the method and parameter passed.
If you are not passing any parameters then call your method using this, where 'MyMethod' is the name of the method you want to run.
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, New ThreadStart(AddressOf MyMethod))

Something isn't playing nicely and is preventing the form from updating.
You can allow the app to process pending display operations by adding Application.DoEvents() inside one of the loops.
There is some overhead involved, so you probably want it in the outer loop, not the inner loop.

Related

VBA (Excel) - After seemingly functional For Loop, array of worksheets(i) is nothing

I am trying to loop through all open workbooks, add the book(.Name as of now) to an array if it contains a specific string, and then add the first sheet of that workbook to an array of worksheets that I can later loop through. Even though my loop appears to work in debugger, the array of sheets is nothing and later code breaks with 'variable not set'. I'm a total noob so I'm likely not understanding or missing something (maybe dim/redim/preserve?) Warning this code is pretty messy with other things ive tried and duct-tapey garbage, problem is with ma_SourceSheets. I included everything just in case, and debug at the end.
Dim mwb_Active As Workbook
Dim mws_Active As Worksheet
Dim mi_NextInputRow As Integer
Dim ma_SourceBooks() As String
Dim ma_SourceSheets() As Worksheet
Dim mi_NumberOfSheets As Integer
Sub PopulateSPCData()
'Get and set active workbook
Set mwb_Active = Workbooks("2022-02-04 SPC Report Template.xlsm")
mwb_Active.Activate
Set mws_Active = mwb_Active.Sheets("Raw Data")
mws_Active.Activate
'Find the next blank cell in template colA
For Each cell In mws_Active.Columns(1).Cells
'Set variable to the row number of the blank cell
If IsEmpty(cell) = True Then mi_NextInputRow = cell.Row: Exit For
Next cell
'The next line number is the blank row (- 1 for header)
mws_Active.Cells(mi_NextInputRow, 1).Value = mi_NextInputRow - 1
Debug.Print mi_NextInputRow
'Set up cells using custom
Dim xCBDACell As New DataCell
xCBDACell.SetSearchData = "CBDA"
xCBDACell.SetDestinationCell = mws_Active.Cells(mi_NextInputRow, 2)
Debug.Print xCBDACell.DestinationCell.Address
Dim xCBDCell As New DataCell
xCBDACell.SetSearchData = "CBD"
xCBDACell.SetDestinationCell = mws_Active.Cells(mi_NextInputRow, 3)
Dim xD9THCCell As New DataCell
xCBDACell.SetSearchData = "d9-THC"
xCBDACell.SetDestinationCell = mws_Active.Cells(mi_NextInputRow, 4)
Dim xD9THCACell As New DataCell
xCBDACell.SetSearchData = "d9-THCA"
xCBDACell.SetDestinationCell = mws_Active.Cells(mi_NextInputRow, 5)
'Get names of open workbooks
mi_NumberOfSheets = 0
i = 1
For i = 1 To Windows.Count
'If the book name includes this string
If Workbooks(i).Name Like "*SYSSU*" Then
Debug.Print Workbooks(i).Name
ReDim ma_SourceBooks(i)
ma_SourceBooks(i) = Workbooks(i).Name
ReDim ma_SourceSheets(i)
Set ma_SourceSheets(i) = Workbooks(ma_SourceBooks(i)).Sheets("Page 1") 'if this doesnt work
mi_NumberOfSheets = mi_NumberOfSheets + 1 'why does this work?
End If
Next i
If ma_SourceSheets(1) Is Nothing Then 'tried all numbers, all nothing
Debug.Print "No Source Sheet"
Else: Debug.Print mi_NumberOfSheets
End If
Dim xSumResString As String
Dim xSumResRow As Integer
xSumResString = "Summary Results:"
xSumResRow = 0
i = 1
For i = 1 To mi_NumberOfSheets
For Each cell In ma_SourceSheets(i).Columns(2).Cells
If cell.Value = xSumResString Then xSumResRow = cell.Row: Exit For
Next cell
Next i
Debug.Print xSumResRow
Debug.Print 'xResultsCol
'Set xCBDAAvgLoc = ma_SourceSheets(i).Range(xResultsRow, xResultsCol)
'Debug.Print xCBDAAvgLoc.Address
'Debug.Print ma_SourceSheets(i).Cells(xCBDAAvgLoc).Value
'mws_Active.Cells(xCBDACell).Value = ma_SourceSheets(i).Cells(xCBDAAvgLoc).Value
End Sub
In debug log (everything is what i want until No Source):
42 $B$42 2022-02-03 - SEQ-442 SYSSU.xlsx testcopy(2022-02-03 -
SEQ-442 SYSSU).xlsx No Source Sheets
Thanks, let me know if i did anything wrong/need more info

Extract subarray from jagged array and use as 1d array

I'm trying to reduce redundancy in my macros but I'm struggling with getting an element from a jagged array and using it elsewhere.
The premise is a single workbook with many sheets being split by groups of sheet names into new documents that I can then send to the process owners so they only get their own data.
Previously I was selecting sheet names listed explicitly and pasting to a new document that was named explicitly, but I had to run 10 separate almost identical macros to do that and I have heard of select being a bad choice in many instances as well.
Below is my latest attempt, the first issue is at the printOut line I get a Type Mismatch.
Sub CopyOut()
Dim printOut, groupNames, Group1, groupArray() As Variant
Dim n, j As Long
Dim reNamed, fileName As String
Dim ws As Worksheet
Dim wb1, wb2 As Workbook
groupNames = Array("Group 1", "Group 2", "Group 3", "Group 4") 'other arrays left off for length
Group1 = Array("FA_1A Report", "FA_1A", "FA_2ACS Report", "FA_2ACS", "FA_2BCS Report", "FA_2BCS", "FANUCMED Report", "FANUCMED", "FA_RRTP1 Report", "FA_RRPT1")
groupArray = Array(groupNames, Group1)
For n = 1 To UBound(groupArray)
fileName = "CS Data Sheet" & " " & Format(Date, "mmmyy") & "-" & groupArray(n - n)(n - 1) & ".xlsm" 'concat file name string. this is not just tacked on the end of reName because i use it on it's own later
reNamed = "C:\Users\xx\Desktop\" & fileName 'concat save location string
Set wb1 = ThisWorkbook
Set wb2 = Workbooks.Add 'create a new workbook, wb2
wb2.SaveAs fileName:=reNamed, FileFormat:=xlOpenXMLWorkbookMacroEnabled 'save with that name and location
printOut = Join(Application.Index(groupArray, n, 0), ",")
wb1.Sheets(printOut).Copy Before:=Workbooks(fileName).Sheets(1) 'copy the sheets for the group and paste into the newly created document
Next
End Sub
If I nix printOut altogether and put in a specific worksheet name instead it does work for just that one sheet (of course) but I need it to copy multiple to each new document.
I have also tried:
For n = 1 To UBound(groupArray)
...
for j= LBound(groupArray(n)) To UBound(groupArray(n))
wb1.Sheets(groupArray(n)(j)).Copy Before:=Workbooks(fileName).Sheets(1)
next
next
to iterate through the subarray and copy a sheet at a time, but it gives subscript out of range. With this version I tried various methods of making the groupArray(n)(j) value into a string or into a "worksheet" type to set as a variable and use the variable in the sheets().copy, to no avail.
Any idea where I could be going wrong?
thanks so much
EDIT:
I got my above code working by wrapping it in split (was trying to use printOut as an array when it was only a string) and fixing the arguments of Index as below, however the resulting code still needs work, since if a sheet is missing it won't run.
printOut = Split(Join(Application.Index(groupArray(n), 1, 0), ","), ",")
In my experience, if you find yourself hard-coding values like sheet names, group names, and other data directly in your code it tends to become difficult to maintain. Adding more groups, or re-shuffling the sheets in each group becomes problematic. My recommendation is to create a (possibly hidden) worksheet that maps your worksheet names into groups. Then you have a small set of code that operates directly on that.
My example data is set up like this:
Next, in its own code module, I created a few methods to work directly with this group map data. The main idea here is to move the group map data into a memory-based array. While in general I rarely use module-level global variables, I have one in this example to illustrate how to work with the data by only reading it into the array once every time the macro is executed.
(These are Subs and Functions. For my own code, I likely would have created a VBA class to handle the data in an object-oriented way.)
So there is a Private Sub to get the data:
Option Explicit
Private groupData As Variant
Private Sub GetGroupData()
Const GROUP_WS_NAME As String = "GroupMap"
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(GROUP_WS_NAME)
Dim lastRow As Long
Dim lastCol As Long
With ws
'--- how many columns of groups?
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
lastRow = .UsedRange.Find("*", , , , xlByRows, xlPrevious).Row
groupData = .Range("A1").Resize(lastRow, lastCol).Value
End With
End Sub
Now it's easy to figure out how many groups there are:
Public Function NumberOfGroups() As Long
If IsEmpty(groupData) Then GetGroupData
NumberOfGroups = UBound(groupData, 2)
End Function
And how many items in a particular group:
Public Function NumberInGroup(ByVal groupNumber As Long)
If IsEmpty(groupData) Then GetGroupData
'--- count the number of array values that have data
Dim i As Long
For i = LBound(groupData, 1) To UBound(groupData, 1)
If groupData(i, groupNumber) = vbNullString Then
'--- we found the first empty cell in this array, we're done
Exit For
Else
NumberInGroup = NumberInGroup + 1
End If
Next i
'--- subtract one to discount the header value
NumberInGroup = NumberInGroup - 1
End Function
The easiest of all is getting the value of any group:
Public Function GetGroupValue(ByVal groupNumber As Long, _
ByVal groupIndex As Long) As Variant
If IsEmpty(groupData) Then GetGroupData
'--- always add one to the index to account for the header value
GetGroupValue = groupData(groupIndex + 1, groupNumber)
End Function
Notice the check for If IsEmpty(groupData) Then GetGroupData at the beginning of each method. This makes sure the groupData array is always loaded if necessary.
This example gives it a quick test (in a different code module):
Option Explicit
Sub test()
Dim totalGroups As Long
totalGroups = NumberOfGroups()
Dim i As Long
Dim j As Long
For i = 1 To totalGroups
Dim totalInGroup As Long
totalInGroup = NumberInGroup(i)
For j = 1 To totalInGroup
Debug.Print "group " & i & " = " & GetGroupValue(i, j)
Next j
Next i
End Sub
Here's the whole group data code module in a single block:
Option Explicit
Private groupData As Variant
Private Sub GetGroupData()
Const GROUP_WS_NAME As String = "GroupMap"
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(GROUP_WS_NAME)
Dim lastRow As Long
Dim lastCol As Long
With ws
'--- how many columns of groups?
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
lastRow = .UsedRange.Find("*", , , , xlByRows, xlPrevious).Row
groupData = .Range("A1").Resize(lastRow, lastCol).Value
End With
End Sub
Public Function NumberOfGroups() As Long
If IsEmpty(groupData) Then GetGroupData
NumberOfGroups = UBound(groupData, 2)
End Function
Public Function NumberInGroup(ByVal groupNumber As Long)
If IsEmpty(groupData) Then GetGroupData
'--- count the number of array values that have data
Dim i As Long
For i = LBound(groupData, 1) To UBound(groupData, 1)
If groupData(i, groupNumber) = vbNullString Then
'--- we found the first empty cell in this array, we're done
Exit For
Else
NumberInGroup = NumberInGroup + 1
End If
Next i
'--- subtract one to discount the header value
NumberInGroup = NumberInGroup - 1
End Function
Public Function GetGroupValue(ByVal groupNumber As Long, ByVal groupIndex As Long) As Variant
If IsEmpty(groupData) Then GetGroupData
'--- always add one to the index to account for the header value
GetGroupValue = groupData(groupIndex + 1, groupNumber)
End Function
If I got this right, you have one master workbook with n sheets and you want to group some of them, then create a new workbook for each group and paste in its assigned sheets.
I think an approach where you keep a "config" file in your master workbook for setting up groups and sheets, is more suitable rather than editing into code. Example:
The below code will create a file using the names from column A and copy all the sheets defined on their respective row.
Option Explicit
Sub CopyOut()
Dim groupArr() As Variant
Dim wb2 As Workbook
Dim lastRow As Long, lastCol As Long, highestNumOfSheets As Long, i As Long, j As Long, arrColumns As Long
Dim reNamed As String, fileName As String, configSheet As String
Dim removedSheet1 As Boolean
' Modify the sheet name here
configSheet = "config"
' Build an array from sheet defined groups
With ThisWorkbook.Worksheets(configSheet)
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 2 To lastRow
lastCol = .Cells(i, .Columns.Count).End(xlToLeft).Column
If lastCol > highestNumOfSheets Then highestNumOfSheets = lastCol
Next i
groupArr = .Range(.Cells(2, 1), .Cells(lastRow, highestNumOfSheets)).Value2
End With
Application.ScreenUpdating = False
For i = LBound(groupArr) To UBound(groupArr)
fileName = "CS Data Sheet " & Format(Date, "mmmyy") & "-" & groupArr(i, 1) & ".xlsm"
reNamed = Environ("UserProfile") & "\Desktop\" & fileName
removedSheet1 = False ' Reset this on each new workbook created
Set wb2 = Workbooks.Add
' Pick all the sheet names for the current group
For j = 2 To UBound(groupArr, 2)
' Skip empty values from array (if it's the case) and skip missing sheets
If Trim(groupArr(i, j)) <> vbNullString And SheetExists(groupArr(i, j)) Then
ThisWorkbook.Worksheets(groupArr(i, j)).Copy Before:=wb2.Worksheets(1)
' Remove Sheet1 from the new Workbook
If removedSheet1 = False Then
With Application
.DisplayAlerts = False
wb2.Worksheets("Sheet1").Delete
removedSheet1 = True
.DisplayAlerts = True
End With
End If
End If
Next j
' Here you might need an error handler if you think you're going to run the macro multiple times in the same day
' If the file exists already this will throw an error
' A quick lazy way is to add time (including seconds) when you define the file name above
wb2.SaveAs fileName:=reNamed, FileFormat:=xlOpenXMLWorkbookMacroEnabled
wb2.Close
If Not wb2 Is Nothing Then Set wb2 = Nothing
Next i
Application.ScreenUpdating = True
End Sub
Function SheetExists(ByVal sheetName As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = ThisWorkbook.Worksheets(sheetName)
On Error GoTo 0
If Not ws Is Nothing Then
SheetExists = True
Set ws = Nothing
End If
End Function
Of course it can be tweaked around, with error handling and other checks (depending on what you want to achieve entirely) but it should give you an alternative view of your code.
EDIT: Added a function to check if sheet exists.

VBA Worksheet Loops

I'm currently working with a workbook containing 34 different tabs.
I'm trying to extract Monthly Data from each of the tabs and Transpose it into daily figures for each specific city.
I have put all the dates within the year 2019 as columns in order to present it as daily figures. (See example in img below)
Each tab contains data for each specific city.
I always want to extract the data present on row 20 from column 4 to 15 in each tab for each specific city. ( see 2nd image below highlighted in yellow)
Public Sub CreateArray()
Dim myArrayOfMonths(11) As Double
Dim currentWorkbook As Workbook
Dim currentSheet As Worksheet
Dim otherSheet As Worksheet
Dim i As Integer
Dim r As Integer
Dim c As Integer
Dim j As Integer
Set currentWorkbook = ActiveWorkbook
Set otherSheet = currentWorkbook.Worksheets("Output")
i = 1
For Each currentSheet In currentWorkbook.Worksheets
r = 20
j = 0
For c = 4 To 15
myArrayOfMonths(j) = ActiveSheet.Cells(r, c)
j = j + 1
Next c
Debug.Print myArrayOfMonths(0)
i = i + 1
Next currentSheet
Set currentSheet = Nothing
Set currentWorkbook = Nothing
End Sub
In my code I'm trying to run through all of the tabs with a loop
and with a 2nd loop check the date (row 16, column 4 to 15) and extract it on my template (Similiar to a vlookup) Unfortunately, it never passes through the first tab as i=0 always for some reason.
Could you please advise?
Would you be able to do something like this?
Option Explicit
Public Sub PopulateOutput()
Dim outputSheet As Worksheet
Dim i As Integer
Set outputSheet = ActiveWorkbook.Worksheets("Output")
' starting at index 2 since output sheet looks like index 1
For i = 2 To ActiveWorkbook.Worksheets.Count
With ActiveWorkbook.Worksheets(i)
outputSheet.Range("B" & i & ":M" & i).Value = .Range("D20:O20").Value
End With
Next
End Sub
Does this suit your needs?
Public Sub CreateArray()
Dim myArrayOfMonths(11) As Double
Dim currentWorkbook As Workbook
Dim currentSheet As Worksheet
Dim otherSheet As Worksheet
Dim r As Integer
Dim c As Integer
Set currentWorkbook = ActiveWorkbook
Set otherSheet = currentWorkbook.Worksheets("Output")
For Each currentSheet In currentWorkbook.Worksheets
r = 20
For c = 4 To 15
myArrayOfMonths(c - 4) = myArrayOfMonths(c - 4) + currentSheet.Cells(r, c)
Next c
Next currentSheet
otherSheet.Range("B1:M1").Value = myArrayOfMonths
Set currentSheet = Nothing
Set currentWorkbook = Nothing
End Sub
Use currentSheet.Cells(r,c) instead of ActiveSheet
or use currentSheet.Activate and then myArrayOfMonths(j) = ActiveSheet.Cells(r, c), but try to avoid ActiveSheet.

VB.NET For Each Loop exits prematurely / Code returns to caller before finishing

I have two forms:
Editor
Tables
On the "Editor" form I have a "KeyDown" event which opens the "Tables" form when the F5 key is down.
Private Sub DataGridView_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DataGridView.KeyDown
Select Case e.KeyCode
Case Keys.Delete
For Each Row As DataGridViewRow In DataGridView.Rows
If Row.IsNewRow Then
DataGridView.Rows.Remove(Row)
End If
Next
Case Keys.F5
Tabels.Show()
End Select
End Sub
On the "Tables" form I have some code which get's a List(Of String) and loops through it, adding rows to a datagridview on the form.
Dim Tables As List(Of String)
Tables = NAV2013BLOBReader.ReturnXML("SELECT [Metadata] FROM dbo.[Object Metadata] WHERE [Object Type] = 1")
'Sæt egenskaber på datagridview
DataGridView.AutoGenerateColumns = False
Dim Row As DataGridViewRow = DataGridView.Rows(0).Clone()
For Each Line As String In Tables
If Line.Contains("MetaTable") Then
Dim LanguageStartIndex As Integer = Line.IndexOf("CaptionML=""") + 15
Dim LanguageEndIndex As Integer = Line.IndexOf(";", LanguageStartIndex)
Dim IdStartIndex As Integer = Line.IndexOf("ID=""") + 4
Dim IdEndIndex As Integer = Line.IndexOf(""" CaptionML") - IdStartIndex
Dim NameStartIndex As Integer = Line.IndexOf("Name=""") + 6
Dim NameEndIndex As Integer = Line.IndexOf(""" LookupFormID") - NameStartIndex
'Tildel cellerne værdier
Row.Cells(0).Value = Line.Substring(IdStartIndex, IdEndIndex)
Row.Cells(1).Value = Line.Substring(NameStartIndex, NameEndIndex)
Row.Cells(2).Value = Line.Substring(LanguageStartIndex, LanguageEndIndex - LanguageStartIndex)
DataGridView.Rows.Add(Row)
DataGridView.Refresh()
End If
Next
DataGridView.AllowUserToAddRows = False
The problem is that when the loop has iterated twice, the flow will exit the loop and go back to the KeyDown event, which then finishes.
If I empty out the code in the If Line.Contains statement, and insert a MessageBox, everything iterates just fine.
I hope someone knows the answer.
Thanks and best regards!
EDIT: I can see that DataGridView.Rows.Add(Row) is at fault, I have no idea why though.
EDIT: I fixed it by changing the "For Each" loop to a "For" loop, and cloning the latest added row.
For i = 0 To Tables.Count - 1
Dim Row As DataGridViewRow = DataGridView.Rows(i).Clone()
If Tables(i).Contains("MetaTable") Then
Dim LanguageStartIndex As Integer = Tables(i).IndexOf("CaptionML=""") + 15
Dim LanguageEndIndex As Integer = Tables(i).IndexOf(";", LanguageStartIndex)
Dim IdStartIndex As Integer = Tables(i).IndexOf("ID=""") + 4
Dim IdEndIndex As Integer = Tables(i).IndexOf(""" CaptionML") - IdStartIndex
Dim NameStartIndex As Integer = Tables(i).IndexOf("Name=""") + 6
Dim NameEndIndex As Integer = Tables(i).IndexOf("""", Tables(i).IndexOf("Name=""") + 6) - NameStartIndex
'Tildel cellerne værdier
Row.Cells(0).Value = Tables(i).Substring(IdStartIndex, IdEndIndex)
Row.Cells(1).Value = Tables(i).Substring(NameStartIndex, NameEndIndex)
Row.Cells(2).Value = Tables(i).Substring(LanguageStartIndex, LanguageEndIndex - LanguageStartIndex)
'Tilføj række til DataGridView og opfrisk kontrollen, så at de nye rækker bliver vist med det samme
DataGridView.Rows.Add(Row)
DataGridView.Refresh()
End If
Next
EDIT: I fixed it by changing the "For Each" loop to a "For" loop, and cloning the latest added row.
For i = 0 To Tables.Count - 1
Dim Row As DataGridViewRow = DataGridView.Rows(i).Clone()
If Tables(i).Contains("MetaTable") Then
Dim LanguageStartIndex As Integer = Tables(i).IndexOf("CaptionML=""") + 15
Dim LanguageEndIndex As Integer = Tables(i).IndexOf(";", LanguageStartIndex)
Dim IdStartIndex As Integer = Tables(i).IndexOf("ID=""") + 4
Dim IdEndIndex As Integer = Tables(i).IndexOf(""" CaptionML") - IdStartIndex
Dim NameStartIndex As Integer = Tables(i).IndexOf("Name=""") + 6
Dim NameEndIndex As Integer = Tables(i).IndexOf("""", Tables(i).IndexOf("Name=""") + 6) - NameStartIndex
'Tildel cellerne værdier
Row.Cells(0).Value = Tables(i).Substring(IdStartIndex, IdEndIndex)
Row.Cells(1).Value = Tables(i).Substring(NameStartIndex, NameEndIndex)
Row.Cells(2).Value = Tables(i).Substring(LanguageStartIndex, LanguageEndIndex - LanguageStartIndex)
'Tilføj række til DataGridView og opfrisk kontrollen, så at de nye rækker bliver vist med det samme
DataGridView.Rows.Add(Row)
DataGridView.Refresh()
End If
Next

Why does VB.NET show a (0,0) element in my array after I've filled it with data from Excel?

The following code will result in an x(,) matrix containing array elements transferred from Excel, that when looked at using QuickWatch, will indicate a zero-based array. However, the array will be one-based and the (0,0) element shown in QuickWatch will not be accessible.
I believe this behavior to be a bug, since QuickWatch shows that a (0,0) element exists, which truly does not -- since it is not accessible.
The following code will spawn the x(,) array that is in question, and when viewed with QuickWatch will show a (0,0) element.
To implement the code, add an OperFileDialog1 to your form, and paste the following code into e.g. a button. You will need to ensure there are valid string or numerical values cells A1, A2, B1, B2 in the Excel that is opened. At run-time, for some reason, the element x(0,0) is unreadable, even though there will be data shown in the x(0,0) element when viewed with QuickWatch:
Dim i, j As Integer
Dim filename As String
Dim x(,) As Object
Dim myx(,) As Object
With OpenFileDialog1
.FileName = "*.*"
.CheckFileExists = True
.ShowReadOnly = True
.Filter = "Excel 2010 *.xlxs|*.xlxs|Excel 2003-2007 *.xls|*.xls"
If .ShowDialog = Windows.Forms.DialogResult.OK Then
'Load file
filename = .FileName
End If
End With
' Create new Application.
Dim rXL As New Excel.Application
Dim rWB As Excel.Workbook
Dim rSheet As Excel.Worksheet
Dim rRng As Excel.Range
rWB = rXL.Workbooks.Open(filename)
For i = 1 To 1 ' rWB.Sheets.Count To 1 Step -1
Dim sheet As Excel.Worksheet = rWB.Sheets(i)
Dim r As Excel.Range = sheet.UsedRange
If r.Rows.Count = 0 Then Exit For
Dim eCellArray As System.Array = r.Value
ReDim x(r.Rows.Count, r.Columns.Count)
x = r.Value
rRng = Nothing
Next
ReDim myx(x.GetLength(0) + 1, x.GetLength(1) + 1)
For i = 0 To x.GetLength(0)
For j = 0 To x.GetLength(1)
myx(i + 1, j + 1) = x(i, j)
Next
Next
This works in vb.net 2008:
Dim x(100, 100) As Object
x(0, 0) = "asdf"
MsgBox(x(0, 0))
You may be assigning the string to the wrong array element or you may be assigning the correct array element something other than a single string, such as a string array.

Resources