How can I be alerted if my recursion decides to start skipping loops? - vb.net

I have a nested For / Next recursion at the heart of a web app I am trying to develop. When I programmed it, I verified its output on an example that nested 3-5 levels and thought all was well.
Lately, I decided to verify an entry in the result set that was nested 12 to 15 levels deep. The resulting percentage was incorrect because some progeny were not recursed.
Because my result set can take so long to run (8-13 hours for the more indepth queries) and I could run the same test on a subset (~150,000 records) of the records in the full database table (~1,200,000 records), I trialled it against the smaller table.
Low and behold it appears to work perfectly. A search that was returning ~56,000 records, returned ~126,000 records (meaning it was previously skipping out a lot of recursions). I verified random sample results to be correct.
Comparing result sets from the same query done on the two database tables, it seems that the missed recursions start to show up with some (not all) of the records that are nested beyond 12 levels deep.
The troubling thing for me is that I need to know when my result set is suspect without having to search the result set for dropped nesting.
Here is the code for the recursive sub:
' lookup table for up to 63 generations '
Dim percentage() As Double = {100, 50, 25, 12.5, 6.25, 3.125, ect. . .}
' DataTable to display results of looping through the db '
Dim t As DataTable
Dim c As DataColumn
Dim r As DataRow
' columns are: id, name, dad, mom, gender, year born, trait, percentage '
Private Sub GetPct(ByRef progeny As List(Of Int32), ByRef gender As List(Of String), ByVal generations As Int16, ByVal count As Int16)
Dim nxtGeneration As Int16 = generations + 1
Dim nxtPercentage As Double = percentage(nxtGeneration)
For i As Int16 = 0 To count
Dim dbConn As New SqlConnection(connString)
Dim j As Int16 = -1
Dim prog As New List(Of Int32)
Dim gndr As New List(Of String)
If gender(i) = "M" Then
Dim dreader As SqlDataReader
Dim dgetComm As New SqlCommand("d_get", dbConn)
dgetComm.CommandType = CommandType.StoredProcedure
dgetComm.Parameters.Add("#id", SqlDbType.Int)
dgetComm.Parameters("#id").Value = prog(i)
Using dbConn
Try
dbConn.Open()
dreader = dgetComm.ExecuteReader()
If dreader.HasRows = True Then
While dreader.Read()
j += 1
Dim updated As DataRow = t.Rows.Find(dreader(0))
If updated Is Nothing Then
t.BeginLoadData()
r = t.NewRow()
r(0) = dreader(0)
r(1) = dreader(1)
r(2) = dreader(2)
r(3) = dreader(3)
r(4) = dreader(4)
r(5) = dreader(5)
r(6) = dreader(6)
r(7) = nxtPercentage
t.Rows.Add(r)
t.EndLoadData()
prg.Add(dreader(0))
gnd.Add(dreader(4))
Else
prg.Add(dreader(0))
gnd.Add(dreader(4))
updated(7) += nxtPercentage
End If
End While
End If
dgetComm.Dispose()
dgetComm = Nothing
dreader.Close()
dreader = Nothing
Catch ex As Exception
' modify when going live '
lblDetails.Text &= "Error loading to table with get of dam" & Err.Description
End Try
End Using
GetPct(prg, gnd, nxtG, j)
Else
Dim sreader As SqlDataReader
Dim sgetComm As New SqlCommand("s_get", dbConn)
sgetComm.CommandType = CommandType.StoredProcedure
sgetComm.Parameters.Add("#id", SqlDbType.Int)
sgetComm.Parameters("#id").Value = prog(i)
Using dbConn
Try
dbConn.Open()
sreader = sgetComm.ExecuteReader()
If sreader.HasRows = True Then
While sreader.Read()
j += 1
Dim updated As DataRow = t.Rows.Find(srdr(0))
If updated Is Nothing Then
t.BeginLoadData()
r = t.NewRow()
r(0) = sreader(0)
r(1) = sreader(1)
r(2) = sreader(2)
r(3) = sreader(3)
r(4) = sreader(4)
r(5) = sreader(5)
r(6) = sreader(6)
r(7) = nxtPercentage
t.Rows.Add(r)
t.EndLoadData()
prg.Add(sreader(0))
gnd.Add(sreader(4))
Else
prg.Add(sreader(0))
gnd.Add(sreader(4))
updated(7) += nxtPercentage
End If
End While
End If
sgetComm.Dispose()
sgetComm = Nothing
sreader.Close()
sreader = Nothing
Catch ex As Exception
' modify when going live'
lblDetails.Text &= "Error loading to table with get of sire" & Err.Description
End Try
End Using
GetPct(prg, gnd, nxtG, j)
End If
Next i
End Sub

Related

Split output result by n and loop

I'm solving an issue where I need to create one PDF form.
That PDF form has 8 sections where I need to put info about and looks like shown on picture (only 4 shown).
The point is that my query will return 0 - n different results. So I need to split by 8 and post on different pages.
I tried like shown below but that seems not to work since I always load a new document. Does anyone have some advice how to make it?
Try
Dim sCommand As OleDb.OleDbCommand
sCommand = New OleDb.OleDbCommand("SELECT a,b,c Query to fetch n results ", _dbCon)
sCommand.CommandTimeout = 0
Dim _dbREADER As OleDb.OleDbDataReader
_dbREADER = sCommand.ExecuteReader
Dim dt As DataTable = New DataTable()
dt.Load(_dbREADER)
Dim totalPages As Integer = dt.Rows.Count / 8
Dim currentPage As Integer = 1
Dim rowCounter As Long = 0
If dt.Rows.Count > 0 Then
For Each row In dt.Rows
rowCounter += 1
If rowCounter = 8 Then
currentPage += 1
rowCounter = 0
End If
_pdfDocumentOutput = System.IO.Path.GetTempPath() & "MailingForm_" & currentPage & ".pdf"
SaveFromResources(_pdfDocument, My.Resources.template)
Using reader As New PdfReader(_pdfDocument)
Using stamper As New PdfStamper(reader, New IO.FileStream(_pdfDocumentOutput, IO.FileMode.Create))
Dim fontName As String = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "SCRIPTIN.ttf")
Dim bf As BaseFont = BaseFont.CreateFont(fontName, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED)
Dim pdfForm As AcroFields = stamper.AcroFields
pdfForm.AddSubstitutionFont(bf)
pdfForm.SetField(rowCounter - 1 & "0", row("Customer")) 'Checks the top radiobutton of the VrPr4 field
pdfForm.SetField(rowCounter - 1 & "1", row("Address"))
pdfForm.SetField(rowCounter - 1 & "2", row("Location"))
stamper.FormFlattening = True
End Using
End Using
Next
End If
Status.Text = "Store info loaded ! "
Catch ex As Exception
Status.Text = ex.Message
End Try
I found the solution by splitting tables
Private Shared Function SplitTable(ByVal originalTable As DataTable, ByVal batchSize As Integer) As List(Of DataTable)
Dim tables As List(Of DataTable) = New List(Of DataTable)()
Dim i As Integer = 0
Dim j As Integer = 1
Dim newDt As DataTable = originalTable.Clone()
newDt.TableName = "Table_" & j
newDt.Clear()
For Each row As DataRow In originalTable.Rows
Dim newRow As DataRow = newDt.NewRow()
newRow.ItemArray = row.ItemArray
newDt.Rows.Add(newRow)
i += 1
If i = batchSize Then
tables.Add(newDt)
j += 1
newDt = originalTable.Clone()
newDt.TableName = "Table_" & j
newDt.Clear()
i = 0
End If
If row.Equals(originalTable.Rows(originalTable.Rows.Count - 1)) Then
tables.Add(newDt)
j += 1
newDt = originalTable.Clone()
newDt.TableName = "Table_" & j
newDt.Clear()
i = 0
End If
Next
Return tables
End Function
And after that loop through each one of table . And put all results to one file
Dim tables = SplitTable(dt, 8)

Performance improvement on vb.net code

I need to write 50 million records with 72 columns into text file, the file size is growing as 9.7gb .
I need to check each and every column length need to format as according to the length as defined in XML file.
Reading records from oracle one by one and checking the format and writing into text file.
To write 5 crores records it is taking more than 24 hours. how to increase the performance in the below code.
Dim valString As String = Nothing
Dim valName As String = Nothing
Dim valLength As String = Nothing
Dim valDataType As String = Nothing
Dim validationsArray As ArrayList = GetValidations(Directory.GetCurrentDirectory() + "\ReportFormat.xml")
Console.WriteLine("passed xml")
Dim k As Integer = 1
Try
Console.WriteLine(System.DateTime.Now())
Dim selectSql As String = "select * from table where
" record_date >= To_Date('01-01-2014','DD-MM-YYYY') and record_date <= To_Date('31-12-2014','DD-MM-YYYY')"
Dim dataTable As New DataTable
Dim oracleAccess As New OracleConnection(System.Configuration.ConfigurationManager.AppSettings("OracleConnection"))
Dim cmd As New OracleCommand()
cmd.Connection = oracleAccess
cmd.CommandType = CommandType.Text
cmd.CommandText = selectSql
oracleAccess.Open()
Dim Tablecolumns As New DataTable()
Using oracleAccess
Using writer = New StreamWriter(Directory.GetCurrentDirectory() + "\FileName.txt")
Using odr As OracleDataReader = cmd.ExecuteReader()
Dim sbHeaderData As New StringBuilder
For i As Integer = 0 To odr.FieldCount - 1
sbHeaderData.Append(odr.GetName(i))
sbHeaderData.Append("|")
Next
writer.WriteLine(sbHeaderData)
While odr.Read()
Dim sbColumnData As New StringBuilder
Dim values(odr.FieldCount - 1) As Object
Dim fieldCount As Integer = odr.GetValues(values)
For i As Integer = 0 To fieldCount - 1
Dim vals As Array = validationsArray(i).ToString.ToUpper.Split("|")
valName = vals(0).trim
valDataType = vals(1).trim
valLength = vals(2).trim
Select Case valDataType
Case "VARCHAR2"
If values(i).ToString().Length = valLength Then
sbColumnData.Append(values(i).ToString())
'sbColumnData.Append("|")
ElseIf values(i).ToString().Length > valLength Then
sbColumnData.Append(values(i).ToString().Substring(0, valLength))
'sbColumnData.Append("|")
Else
sbColumnData.Append(values(i).ToString().PadRight(valLength))
'sbColumnData.Append("|")
End If
Case "NUMERIC"
valLength = valLength.Substring(0, valLength.IndexOf(","))
If values(i).ToString().Length = valLength Then
sbColumnData.Append(values(i).ToString())
'sbColumnData.Append("|")
Else
sbColumnData.Append(values(i).ToString().PadLeft(valLength, "0"c))
'sbColumnData.Append("|")
End If
'sbColumnData.Append((values(i).ToString()))
End Select
Next
writer.WriteLine(sbColumnData)
k = k + 1
Console.WriteLine(k)
End While
End Using
writer.WriteLine(System.DateTime.Now())
End Using
End Using
Console.WriteLine(System.DateTime.Now())
'Dim Adpt As New OracleDataAdapter(selectSql, oracleAccess)
'Adpt.Fill(dataTable)
Return Tablecolumns
Catch ex As Exception
Console.WriteLine(System.DateTime.Now())
Console.WriteLine("Error: " & ex.Message)
Console.ReadLine()
Return Nothing
End Try

Fast Export of Large Datatable to Excel Spreadsheet in VB.Net

I have an interesting conundrum here, how do I quickly (under 1 minute) export a large datatable (filled from SQL, 35,000 rows) into an Excel spreadsheet for users. I have code in place that can handle the export, and while nothing is "wrong" with the code per se, it is infuriatingly slow taking 4 minutes to export the entire file (sometimes longer if a user has less RAM or is running more on their system). Sadly, this is an improvement over the 10+ minutes it used to take using our old method. Simply put, can this be made any faster, without using 3rd party components? If so, how? My code is as follows, the slow down occurs between messageboxes 6 and 7 where each row is written. Thank you all for taking the time to take a look at this:
Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnJeffTest.Click
Test(MySPtoExport)
End Sub
Private Sub Test(ByVal SQL As String)
'Declare variables used to execute the VUE Export stored procedure
MsgBox("start stop watch")
Dim ConnectionString As New SqlConnection(CType(ConfigurationManager.AppSettings("ConnString"), String))
Dim cmdSP As New SqlClient.SqlCommand
Dim MyParam As New SqlClient.SqlParameter
Dim MyDataAdapter As New SqlClient.SqlDataAdapter
Dim ExportDataSet As New DataTable
Dim FilePath As String
MsgBox("stop 1 - end of declare")
Try
' open the connection
ConnectionString.Open()
' Use the connection for this sql command
cmdSP.Connection = ConnectionString
'set this command as a stored procedure command
cmdSP.CommandType = CommandType.StoredProcedure
'get the stored procedure name and plug it in
cmdSP.CommandText = SQL
'Add the Start Date parameter if required
Select Case StDt
Case Nothing
' there's no parameter to add
Case Is = 0
' there's no parameter to add
Case Else
'add the parameter name, it's direction and its value
MyParam = cmdSP.Parameters.Add("#StartDate", SqlDbType.VarChar)
MyParam.Direction = ParameterDirection.Input
MyParam.Value = Me.txtStartDate.Text
End Select
MsgBox("stop 2 - sql ready")
'Add the End Date parameter if required
Select Case EdDt
Case Nothing
' there's no parameter to add
Case Is = 0
' there's no parameter to add
Case Else
'add the parameter name, it's direction and its value
MyParam = cmdSP.Parameters.Add("#EndDate", SqlDbType.VarChar)
MyParam.Direction = ParameterDirection.Input
MyParam.Value = Me.txtEndDate.Text
End Select
'Add the single parameter 1 parameter if required
Select Case SPar1
Case Is = Nothing
' there's no parameter to add
Case Is = ""
' there's no parameter to add
Case Else
'add the parameter name, it's direction and its value
MyParam = cmdSP.Parameters.Add(SPar1, SqlDbType.VarChar)
MyParam.Direction = ParameterDirection.Input
MyParam.Value = Me.txtSingleReportCrt1.Text
End Select
'Add the single parameter 2 parameter if required
Select Case Spar2
Case Is = Nothing
' there's no parameter to add
Case Is = ""
' there's no parameter to add
Case Else
'add the parameter name, it's direction and its value
MyParam = cmdSP.Parameters.Add(Spar2, SqlDbType.VarChar)
MyParam.Direction = ParameterDirection.Input
MyParam.Value = Me.txtSingleReportCrt2.Text
End Select
MsgBox("stop 3 - params ready")
'Prepare the data adapter with the selected command
MyDataAdapter.SelectCommand = cmdSP
' Set the accept changes during fill to false for the NYPDA export
MyDataAdapter.AcceptChangesDuringFill = False
'Fill the Dataset tables (Table 0 = Exam Eligibilities, Table 1 = Candidates Demographics)
MyDataAdapter.Fill(ExportDataSet)
'Close the connection
ConnectionString.Close()
'refresh the destination path in case they changed it
SPDestination = txtPDFDestination.Text
MsgBox("stop 4 - procedure ran, datatable filled")
Select Case ExcelFile
Case True
FilePath = SPDestination & lblReportName.Text & ".xls"
Dim _excel As New Microsoft.Office.Interop.Excel.Application
Dim wBook As Microsoft.Office.Interop.Excel.Workbook
Dim wSheet As Microsoft.Office.Interop.Excel.Worksheet
wBook = _excel.Workbooks.Add()
wSheet = wBook.ActiveSheet()
Dim dt As System.Data.DataTable = ExportDataSet
Dim dc As System.Data.DataColumn
Dim dr As System.Data.DataRow
Dim colIndex As Integer = 0
Dim rowIndex As Integer = 0
MsgBox("stop 5 - excel stuff declared")
For Each dc In dt.Columns
colIndex = colIndex + 1
_excel.Cells(1, colIndex) = dc.ColumnName
Next
MsgBox("stop 6 - Header written")
For Each dr In dt.Rows
rowIndex = rowIndex + 1
colIndex = 0
For Each dc In dt.Columns
colIndex = colIndex + 1
_excel.Cells(rowIndex + 1, colIndex) = dr(dc.ColumnName)
Next
Next
MsgBox("stop 7 - rows written")
wSheet.Columns.AutoFit()
MsgBox("stop 8 - autofit complete")
Dim strFileName = SPDestination & lblReportName.Text & ".xls"
If System.IO.File.Exists(strFileName) Then
System.IO.File.Delete(strFileName)
End If
MsgBox("stop 9 - file checked")
wBook.SaveAs(strFileName)
wBook.Close()
_excel.Quit()
End Select
MsgBox("File " & lblReportName.Text & " Exported Successfully!")
'Dispose of unneeded objects
MyDataAdapter.Dispose()
ExportDataSet.Dispose()
StDt = Nothing
EdDt = Nothing
SPar1 = Nothing
Spar2 = Nothing
MyParam = Nothing
cmdSP.Dispose()
cmdSP = Nothing
MyDataAdapter = Nothing
ExportDataSet = Nothing
Catch ex As Exception
' Something went terribly wrong. Warn user.
MessageBox.Show("Error: " & ex.Message, "Stored Procedure Running Process ", _
MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally
'close the connection in case is still open
If Not ConnectionString.State = ConnectionState.Closed Then
ConnectionString.Close()
ConnectionString = Nothing
End If
' reset the fields
ResetFields()
End Try
End Sub
Even though the question was asked several years ago, I thought I would add my solution since the question was posed in VB and the "best answer" is in C#. This solution writes 22,000+ rows (1.9MB) in 4 seconds on an i7 System w/ 16GB RAM.
Imports Excel = Microsoft.Office.Interop.Excel
Public Class Main
Private Sub btnExportToExcel(sender As Object, e As EventArgs) Handles btnExpToExcel.Click
'Needed for the Excel Workbook/WorkSheet(s)
Dim app As New Excel.Application
Dim wb As Excel.Workbook = app.Workbooks.Add()
Dim ws As Excel.Worksheet
Dim strFN as String = "MyFileName.xlsx" 'must have ".xlsx" extension
'Standard code for filling a DataTable from SQL Server
Dim strSQL As String = "My SQL Statement for the DataTable"
Dim conn As New SqlConnection With {.ConnectionString = "My Connection"}
Dim MyTable As New DataTable
Dim cmd As New SqlCommand(strSQL, conn)
Dim da As New SqlDataAdapter(cmd)
da.Fill(MyTable)
'Add a sheet to the workbook and fill it with data from MyTable
'You could create multiple tables and add additional sheets in a loop
ws = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count))
DataTableToExcel(MyTable, ws, strSym)
wb.SaveAs(strFN) 'save and close the WorkBook
wb.Close()
MsgBox("Export complete.")
End Sub
Private Sub DataTableToExcel(dt As DataTable, ws As Excel.Worksheet, TabName As String)
Dim arr(dt.Rows.Count, dt.Columns.Count) As Object
Dim r As Int32, c As Int32
'copy the datatable to an array
For r = 0 To dt.Rows.Count - 1
For c = 0 To dt.Columns.Count - 1
arr(r, c) = dt.Rows(r).Item(c)
Next
Next
ws.Name = TabName 'name the worksheet
'add the column headers starting in A1
c = 0
For Each column As DataColumn In dt.Columns
ws.Cells(1, c + 1) = column.ColumnName
c += 1
Next
'add the data starting in cell A2
ws.Range(ws.Cells(2, 1), ws.Cells(dt.Rows.Count, dt.Columns.Count)).Value = arr
End Sub
End Class
Hope it helps.
As when using VBA to automate Excel, you can assign an array directly to the value of a Range object: this is done as a single operation, so you remove the overhead associated with making multiple calls across the process boundaries between your .Net code and the Excel instance.
Eg, see the accepted answer here: Write Array to Excel Range
The answer from CPRouse worked for me except that it left off the last row of data. In the Private Sub DataTableToExcel function, I added 1 to the rows.count on this line and it wrote all the records. ws.Range(ws.Cells(2, 1), ws.Cells(dt.Rows.Count + 1, dt.Columns.Count)).Value = arr
Here is a piece of my own code that performs a very fast export of data from a DataTable to an Excel sheet (use the "Stopwatch" object to compare the speed and let me a comment):
Dim _excel As New Excel.Application
Dim wBook As Excel.Workbook
Dim wSheet As Excel.Worksheet
wBook = _excel.Workbooks.Add()
wSheet = wBook.ActiveSheet()
Dim dc As System.Data.DataColumn
Dim colIndex As Integer = 0
Dim rowIndex As Integer = 0
'Nombre de mesures
Dim Nbligne As Integer = DtMesures.Rows.Count
'Ecriture des entêtes de colonne et des mesures
'(Write column headers and data)
For Each dc In DtMesures.Columns
colIndex = colIndex + 1
'Entête de colonnes (column headers)
wSheet.Cells(1, colIndex) = dc.ColumnName
'Données(data)
'You can use CDbl instead of Cobj If your data is of type Double
wSheet.Cells(2, colIndex).Resize(Nbligne, ).Value = _excel.Application.transpose(DtMesures.Rows.OfType(Of DataRow)().[Select](Function(k) CObj(k(dc.ColumnName))).ToArray())
Next
We had a VB.NET app that did exactly this, and took even longer for our users who were on slow PC's... sometimes 15 minutes.
The app is now an ASP/VB.NET app which simply builds an HTML table and outputs the result as an .xls extension... excel is able to read the HTML table and parse it into a grid format. You can still pass in XML for formatting and options, horizontal pane locking, etc.
If you don't have the option of using ASP.NET... try looking into a way to build an HTML table string and have excel parse & populate for you... much faster! I'm sure excel can parse other types as well.... XML, Arrays, HTML, etc... all would be quicker than manually building each row through VB.NET objects.

Suggestions for speeding up vb.net Access query to populate an array

Dim Builders As New System.Data.OleDb.OleDbConnectionStringBuilder
Builders("Provider") = "Microsoft.Jet.OLEDB.4.0"
Builders("Data Source") = "C:\Users\John\Documents\Visual Studio 2008\Projects\SimpleSQLTest\SimpleSQLTest\dictionary.mdb"
' Dim sSQL1 As String = "Select Words, synonym from [Word List];"
Dim sSQL1 As String = "SELECT lemma, def from [def look-up];"
Dim i As Integer = 0
Dim z As Integer
Using Connection As New OleDbConnection(Builders.ToString)
Dim command As New OleDbCommand(sSQL1, Connection)
Connection.Open()
Dim reader As OleDbDataReader = command.ExecuteReader
'reader.Read()
While reader.Read
i = i + 1
ReDim Preserve Word(i)
ReDim Preserve DeforSyn(i)
Word(i) = reader(0).ToString
DeforSyn(i) = reader(1).ToString
'Form1.TextBox1.Text = reader(0).ToString()
Form1.TextBox1.Text = reader(0).ToString & " " & reader(1).ToString
End While
End Using
MsgBox(i)
So trying to speed up the query. The read of the last item is just to see how long it takes. I do a different method in VB6 and it loads very quickly. Trying to load a dictionary that is over 200,000 rows. Thank you for the suggestions.
Redim might be an expensive operation. Have you tried to start with:
select count(*) from [def look-up]
And create arrays of the right size before you start retrieving data?

How to move to next row in dataset and display in hyperlink

I'm writing an email application that will be used to send HTML news articles to clients.
I'm using a dataset to return the headlines to display to the client. When I loop through the dataset the the latest record is returned but latest headline link is not displayed. So the outputted HTML is the same headline everytime, which is the first record in the dataset. How do I move to the next record in the data set and get the outputted HTML to display the next/correct headline?
Here is a sample of my code:
'Code to populate dataset
Public Function GetHeadline(ByVal ArticleID As Integer) As DataSet
Try
Dim objConn As SqlConnection = New SqlConnection()
objConn.ConnectionString = myConnectionString
objConn.Open()
ds = New DataSet
ds.Clear()
Dim sqlCommand As String = "SomeSql"
Dim objCmd As SqlCommand = New SqlCommand(sqlCommand, objConn)
Dim dataAdapter As SqlDataAdapter = New SqlDataAdapter(objCmd)
dataAdapter.Fill(ds)
Catch ex As Exception
MsgBox(ex.ToString)
GetHeadline = Nothing
End Try
Return ds
End Function
'Code to populate link
If GroupID = 4 Then
iLocation1 = HTMLbody.IndexOf("{!HeadlineID")
While iLocation1 > 0
iLocation2 = HTMLbody.IndexOf("}", iLocation1)
sHeadLineTag = HTMLbody.Substring(iLocation1 + 1, iLocation2 - iLocation1 - 1)
dtReport = clsGlobal.globalReportCatalog.GetHeadline2()
clsGlobal.globalReportCatalog.SetHeadlinePropertiesFromRow(dtReport.Rows(0))
With clsGlobal.globalReportCatalog
For i As Integer = 0 To dtReport.Rows.Count
If i < dtReport.Rows.Count - 1 Then
i = i + 1
End If
Dim ID As Integer = dtReport.Rows(i)("ArticleID")
sHyperTag = "" & .HeadlineReportName & " - " & .HeadlineTitle & ""
sHeadlineDescription = .HeadlineDescription
HTMLbody = HTMLbody.Replace("{!Report.Description}", sHeadlineDescription)
Next
End With
I don't see why you need
For i As Integer = 0 To dtReport.Rows.Count
If i < dtReport.Rows.Count - 1 Then
i = i + 1
End If
Can't you use
Dim ID As Integer = dtReport.Rows(dtReport.Rows.Count - 1)("ArticleID")
or was there supposed to be a row movenext in the loop you forgot?