Output & counters are inconsistent

dd8

Member
Joined
Jun 26, 2019
Messages
12
Programming Experience
10+
Ive inherited the following code

Summary
WinForms displays a list of users that have attended a course
Students either passed (X) or failed (Y) a course.
It prints a document list of all students that completed the course
It prints certificates for students that passed the course.

The issue is
With printing certificates it doesn’t print the last student certificate

It appears the counters are out, and drops / ignores the last student when printing certificates.
The same code (and counters) are used to print the list students completed the course and prints the certificates.

However when I debug the results are inconsistent
Sometimes when I debug, the certificate for the last student doesn’t print
Othertimes, when I debug, its accurate and prints all certificates for all users that passed

Any ideas
TIA



Data
Course location Completed Date Course Name Student Name Result Passed(X) or Failed (Y )
Location 1 24/05/2019 CourseXYZ Student1 X
Location 1 24/05/2019 CourseXYZ Student2 X
Location 1 24/05/2019 CourseXYZ Student3 X
Location 1 24/05/2019 CourseXYZ Student4 Y


code


VB.NET:
                    Invoke(New DelProgressUpdate(AddressOf ProgressUpdate), "Spooling process...", 0, 0)

                    Dim objDTList As New List(Of DataTable)

                    For i As Integer = 0 To dgImportedData.Rows.Count - 1
                        If dgImportedData.Rows(i).Visible = True Then
                            Dim boolFound As Boolean = False

                            For ii As Integer = 0 To objDTList.Count - 1
                                ' if course DataTableList CompletedDate is the same as DataGridList CompletedDate
                                ' AND  if course DataTableList CourseName is the same as DataGridList CourseName
                                If (objDTList(ii).Rows(0).Item("CompletedDate").ToString = dgImportedData.Item("dgCompletedDate", i).Value) And (objDTList(ii).Rows(0).Item("CourseName").ToString = dgImportedData.Item("dgCourseName", i).Value) = True Then
                                    boolFound = True
                                    
                                    Exit For
                                End If
                            Next

                            If boolFound = False Then
                                Dim objDT As New DataTable

                                objDT.Columns.Add("CompletedDate")
                                objDT.Columns.Add("CourseName")
                                objDT.Rows.Add(dgImportedData.Item("dgCompletedDate", i).Value, dgImportedData.Item("dgCourseName", i).Value)
                                objDTList.Add(objDT)
                                objDT.Dispose()
                            End If
                        End If
                    Next

                    ' write the list completed the course
                    For i As Integer = 0 To objDTList.Count - 1
                        Invoke(New DelProgressUpdate(AddressOf ProgressUpdate), "Processing completion list - " & (i + 1) & " of " & objDTList.Count, objDTList.Count, (i + 1))

                        Dim objDoc As Microsoft.Office.Interop.Word.Document = objWordApp.Documents.Open(Application.StartupPath & "\Templates\Course Completion.docx", Nothing, True)

                        objDoc = objWordApp.ActiveDocument

                        For ii As Integer = 0 To dgImportedData.Rows.Count - 1
                            If dgImportedData.Rows(ii).Visible = True Then
                                If (objDTList(i).Rows(0).Item("CompletedDate").ToString = dgImportedData.Item("dgCompletedDate", ii).Value) And (objDTList(i).Rows(0).Item("CourseName").ToString = dgImportedData.Item("dgCourseName", ii).Value) = True Then
                                    ' if student passed the course add to the list
                                    If dgImportedData.Item("dgResult", ii).Value.ToString.ToUpper = "X" Then
                                        objDoc.Content.Find.Execute(FindText:="%INSTRUCTOR%", ReplaceWith:="" & objDTTrainingInstructors.Rows(Params(1)).Item("FullName") & " " & objDTTrainingInstructors.Rows(Params(1)).Item("Rank") & " " & objDTTrainingInstructors.Rows(Params(1)).Item("RegisteredNo") & "", Replace:=Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll)
                                        objDoc.Content.Find.Execute(FindText:="%COURSENAME%", ReplaceWith:="" & objDTList(i).Rows(0).Item("CourseName").ToString & "", Replace:=Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll)
                                        objDoc.Content.Find.Execute(FindText:="%DATECOMPLETED%", ReplaceWith:="" & Format(CDate(objDTList(i).Rows(0).Item("CompletedDate").ToString), "dd/MM/yyyy") & "", Replace:=Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll)
                                        objDoc.Content.Find.Execute(FindText:="%LOCATION%", ReplaceWith:="" & Params(3) & "", Replace:=Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll)
                                        objDoc.Tables(objDoc.Tables.Count).Rows.Add()
                                        objDoc.Tables(objDoc.Tables.Count).Rows(objDoc.Tables(objDoc.Tables.Count).Rows.Count).Range.Font.Bold = False
                                        objDoc.Tables(objDoc.Tables.Count).Cell(objDoc.Tables(objDoc.Tables.Count).Rows.Count, 1).Range.Text = dgImportedData.Item("dgName", ii).Value
                                    End If
                                End If
                            End If
                        Next

                        objDoc.PrintOut(Copies:=objPrintDialog.PrinterSettings.Copies, Background:=True)
                        objDoc.Saved = True
                        objDoc.Close(Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges)
                        objDoc = Nothing
                    Next i

                    Invoke(New DelProgressUpdate(AddressOf ProgressUpdate), "", 0, 0)

                    ' write the course certificate
                    For i As Integer = 0 To dgImportedData.Rows.Count - 1
                        Invoke(New DelProgressUpdate(AddressOf ProgressUpdate), "Processing certificate - " & (i + 1) & " of " & dgImportedData.Rows.Count, dgImportedData.Rows.Count, (i + 1))

                        If dgImportedData.Rows(i).Visible = True Then
                            ' if student passed the course write the certificate
                            If dgImportedData.Item("dgResult", i).Value.ToString.ToUpper = "X" Then
                                Dim objDoc As Microsoft.Office.Interop.Word.Document = objWordApp.Documents.Open(Application.StartupPath & "\Templates\Certificate.docx", Nothing, True)

                                objDoc = objWordApp.ActiveDocument
                                objDoc.Content.Find.Execute(FindText:="%NAME%", ReplaceWith:="" & dgImportedData.Item("dgName", i).Value.ToString.ToUpper & "", Replace:=Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll)
                                objDoc.Content.Find.Execute(FindText:="%COURSENAME%", ReplaceWith:="" & dgImportedData.Item("dgCourseName", i).Value & "", Replace:=Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll)
                                objDoc.Content.Find.Execute(FindText:="%ENDDATE%", ReplaceWith:="" & Format(CDate(dgImportedData.Item("dgCompletedDate", i).Value.ToString), "d MMMM yyyy") & "", Replace:=Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll)
                                objDoc.Content.Find.Execute(FindText:="%AUTHORISINGOFFICER%", ReplaceWith:="" & objDTAuthorisingOfficers.Rows(Params(2)).Item("FullName") & " " & objDTAuthorisingOfficers.Rows(Params(2)).Item("RegisteredNo"), Replace:=Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll)
                                objDoc.PrintOut(Copies:=objPrintDialog.PrinterSettings.Copies, Background:=True)
                                objDoc.Saved = True
                                objDoc.Close(Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges)
                                objDoc = Nothing
                            End If
                        End If
                    Next

                    objDTList = Nothing
 
Last edited by a moderator:

dd8

Member
Joined
Jun 26, 2019
Messages
12
Programming Experience
10+
Note Ive attached doc with code posted in above thread, f it makes it easier to read

...also
if theres an easier way to write the code, as the original code including counters is hard to read
TIA
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,349
Location
Sydney, Australia
Programming Experience
10+
Code is easiest to read when you copy it without all the leading whitespace, which you do in VS by holding down the Alt key while selecting just the block of text you want to copy, and then using the formatting tools provided by the editor in this site.
 

dd8

Member
Joined
Jun 26, 2019
Messages
12
Programming Experience
10+
Why wouild the counters not being consistant,
When I run the code one time, it prints all except the last record
If I re-run the code again, the results are prints all records correctly ie including the last record
 
Last edited:

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,349
Location
Sydney, Australia
Programming Experience
10+
I would suggest that you debug the code, i.e. set a breakpoint and step through it line by while examining the state at each step. That way, you can compare the actual behaviour at each line of code with the behaviour you expect and see exactly where and how the two differ. Reading code of any complexity is rarely enough to work out where an issue is, often because the contents of variables at the time of execution is unknown. Executing the code and examining the application during that execution is essential, which is why VS has an integrated debugger. Even if debugging doesn't enable you to solve the issue yourself, at least you can provide us with more relevant information that may well allow us to zero in on the actual issue.
 

dd8

Member
Joined
Jun 26, 2019
Messages
12
Programming Experience
10+
Thanks jmcilhinney
I get inconsistant behaviour if I debug & step through the code
or if I run the application
 

dd8

Member
Joined
Jun 26, 2019
Messages
12
Programming Experience
10+
on line

The total Data.RowCount is actually 9 records

For i As Integer = 0 To dgImportedData.Rows.Count - 1


with the code dgImportedData.Rows.Count - 1

The total Data.RowCount is now 8 records.

Im not sure why the previous developer did the minus - 1

If I change the code to dgImportedData.Rows.Count
it breaks the following counters & i

...looks like some rewrite is required to get it working
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,349
Location
Sydney, Australia
Programming Experience
10+
I get inconsistant behaviour if I debug & step through the code
or if I run the application
That's not so unusual with multi-threaded applications because the multiple threads will execute at different times relative to each other on different occasions. It makes debugging multi-threaded applications difficult but it makes determining the issue simply by reading code all but impossible. If breaking and stepping is difficult then you can add logging code that outputs wherever is convenient and tells you what's happening on each thread at any time and you can compare that to what you expected. It's distinctly possible that your threads are interfering with each other, which is always a danger in multi-threaded applications. You might need to spend some time analysing exactly what data each thread needs, what of that is common to multiple threads and at what stages one thread depends on another. The common data and the dependency points are where you need to provide explicit thread synchronisation.
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,349
Location
Sydney, Australia
Programming Experience
10+
on line

The total Data.RowCount is actually 9 records

For i As Integer = 0 To dgImportedData.Rows.Count - 1


with the code dgImportedData.Rows.Count - 1

The total Data.RowCount is now 8 records.

Im not sure why the previous developer did the minus - 1

If I change the code to dgImportedData.Rows.Count
it breaks the following counters & i

...looks like some rewrite is required to get it working
That's very basic and a bit of a worry that you don't know. .NET lists and collections are zero-based (except the few that are hold-overs from VB6) and so, for a list with N items, the items have indexes in the range 0 to (N-1). A For loop where the loop counter is used as an index into a list will always start at 0 and go to 1 less than the number of items in that list.
 

dd8

Member
Joined
Jun 26, 2019
Messages
12
Programming Experience
10+
thanks, yes I know that lists and collections and indexes are zero based...

I'm wondering why the original developer would get a (total count then minus 1)
and later in the code add one to the count

the developer left, so Ive inherited the codes and unknown reasons of the code

thanks again
 
Top Bottom