Only return the latest 'x' files - vb.net

I have the following code
Public Function ListDirLatest(ByVal Dir As String, ByVal Amount As Integer) As DataTable
Dim dt As DataTable = ListDir(Dir)
If (dt Is Nothing) Then
Return Nothing
Else
Return dt ' This is where i would like to implement the latest x-files logic
End If
End Function
Private Function ListDir(ByVal Dir As String) As DataTable
If Directory.Exists(Dir) Then
Dim dt As DataTable = GetDT()
Dim dirinfo As New DirectoryInfo(Dir)
For Each fsi As FileSystemInfo In dirinfo.GetFileSystemInfos(".txt")
Dim dr As DataRow = dt.NewRow()
dr("FileName") = fsi.Name()
dr("FileDate") = fsi.CreationTime()
Next
Return dt
Else
Return Nothing
End If
End Function
Private Function GetDT() As DataTable
'Create DataTable to hold results
Dim dt As New DataTable("DirList")
Dim st As System.Type = System.Type.GetType("System.String")
dt.Columns.Add("FileName", st)
dt.Columns.Add("FileDate", st)
Return dt
End Function
At the moment the ListDirLatest Function will return all the files the in the directory.
How do I change the code so that it only returns the latest 'x' files, as specified by the Amount argument.
To Clarify I want to return the LATEST 'x' files in the directory.

You can solve your problem with a little of Linq and a the reference to System.Data.DataSetExtensions
( http://msdn.microsoft.com/en-us/library/system.data.datatableextensions(v=vs.100).aspx )
Public Function ListDirLatest(ByVal Dir As String, ByVal Amount As Integer) As DataTable
Dim dt As DataTable = ListDir(Dir)
If (dt Is Nothing) Then
Return Nothing
Else
Dim r = from myRow in dt.AsEnumerable()
Order By("FileDate DESC")
Take(Amount)
dt = r.CopyToDataTable()
return dt
End If
End Function
Also, the ListDir function has a couple of errors
Add the row information to the DataTable returned
Use a correct pattern for GetFileSystemInfos
Function ListDir(ByVal Dir As String) As DataTable
If Directory.Exists(Dir) Then
Dim dt As DataTable = GetDT()
Dim dirinfo As New DirectoryInfo(Dir)
For Each fsi As FileSystemInfo In dirinfo.GetFileSystemInfos("*.txt")
Dim dr As DataRow = dt.NewRow()
dr("FileName") = fsi.Name()
dr("FileDate") = fsi.CreationTime()
dt.Rows.Add(dr)
Next
Return dt
Else
Return Nothing
End If
End Function

If you mean by Amount the number of files to be returned, then here is what you need to do:
First Change the header of ListDir function to accept a parameter to allow counting the number of files to be returned, and pass that parameter from the first function,
Public Function ListDirLatest(ByVal Dir As String, ByVal Amount As Integer) As DataTable
Dim dt As DataTable = ListDir(Dir, Amount)
If (dt Is Nothing) Then
Return Nothing
Else
Return dt ' This is where i would like to implement the latest x-files logic
End If
End Function
Private Function ListDir(ByVal Dir As String, ByVal Amount As Integer) As DataTable
If Directory.Exists(Dir) Then
Dim dt As DataTable = GetDT()
Dim dirinfo As New DirectoryInfo(Dir)
Dim cnt as Integer = 0
For Each fsi As FileSystemInfo In dirinfo.GetFileSystemInfos(".txt")
Dim dr As DataRow = dt.NewRow()
dr("FileName") = fsi.Name()
dr("FileDate") = fsi.CreationTime()
cnt += 1
if cnt >= Amount Then Exit For
Next
Return dt
Else
Return Nothing
End If
End Function

Related

Asynchronous didn't work in multiple Task

I want to make my program working asynchronously, but i got stuck in some part.
This is my main Sub, this will call Function ProsesData in loop, i got problem in my ProsesData Function.
Module Main
Sub Main()
Proses()
End Sub
Async Function Proses() As Task
Dim busOtomasi As New BusOtomasiSample
Dim dtProses As New DataTable
Dim strMessage As String = ""
Try
Dim tasks = New List(Of Task(Of Tuple(Of String, DataRow)))()
dtProses = busOtomasi.GetListProsesNotDone(strConn)
If dtProses.Rows.Count > 0 Then
For i = 0 To dtProses.Rows.Count - 1
Dim k = i
tasks.Add(ProsesData(dtProses.Rows(k), dtProses.Rows(k)("isAktelFinishProses")))
Next
For Each taskAwait In Await Task.WhenAll(tasks)
If taskAwait.Item1 = "success" Then
ExportExcel(taskAwait.Item2)
strMessage = "Data Otomasi Sample " & IIf(IsDBNull(taskAwait.Item2("param_strKcpCd")), taskAwait.Item2("param_strKcuCd").ToString, taskAwait.Item2("param_strKcpCd").ToString) & " Sudah Selesai Di Proses." & vbCrLf & "Data dapat di download di CAIS dan dibuka dengan password " & taskAwait.Item2("strPassword").ToString & "."
EmailNotification(strMessage, taskAwait.Item2("strEmail").ToString)
End If
Next
Console.ReadLine()
End If
Catch ex As Exception
EmailError("Modul Main" & vbCrLf & ex.ToString)
End Try
End Function
End Module
When It hit function AktivitasTeller.Main(dr) , it will run only one line after that apps will stoped without entering exception.
ProsesData()
Async Function ProsesData(ByVal dr As DataRow, ByVal isAktelFinishProses As Integer) As Task(Of Tuple(Of String, DataRow))
Try
If isAktelFinishProses = 0 Then
Dim result = Await Task.Run(Function() AktivitasTeller.Main(dr))
If result.ToString = "Success" Then
ProsesDataAA(dr)
Return Tuple.Create("success", dr)
Else
Console.WriteLine("Task AT Failed")
Return Tuple.Create("failed", dr)
End If
Else
ProsesDataAA(dr)
Return Tuple.Create("success", dr)
End If
Catch ex As Exception
EmailError("Modul Proses Data" & vbCrLf & ex.ToString)
Return Tuple.Create("failed", dr)
End Try
End Function
AktivitasTeller.Main()
Module AktivitasTeller
Async Function Main(ByVal dataRowAktel As DataRow) As Task(Of String)
Dim strConn As String = GetConn(Conn.eOperasional)
Dim busOtomasi As New BusOtomasiSample
Dim bitPlusKCP As Boolean = False
Dim strcabang As String = ""
Dim datediff As Integer = 0
Try
Dim tasks = New List(Of Task(Of String))()
busOtomasi.UpdateIsAktelFinishProses(strConn, 2, dataRowAktel("intIDProses"))
datediff = GetMonthDifference(dataRowAktel("param_datPeriodeAwal"), dataRowAktel("param_datPeriodeAkhir"))
If dataRowAktel("param_strKcpCd").ToString = "" Then
bitPlusKCP = True
strcabang = dataRowAktel("param_strKcuCd").ToString
Else
strcabang = dataRowAktel("param_strKcpCd").ToString
End If
busOtomasi.DeleteDataAktel(strConn, dataRowAktel("intIDProses").ToString)
For j = 0 To datediff
Dim k = 0 + 1
tasks.Add(AddAktelToSQL(dataRowAktel("intIDProses"), strcabang, CDate(dataRowAktel("param_datPeriodeAwal")).AddMonths(j), CDate(dataRowAktel("param_datPeriodeAwal")).AddMonths(datediff + k).AddDays(-1), bitPlusKCP))
Next
Dim t As Task = Task.WhenAll(tasks).ContinueWith(Sub() GET_CITIZENSHIP_DESC(dataRowAktel("intIDProses")), Sub() busOtomasi.UpdateIsAktelFinishProses(strConn, 1, dataRowAktel("intIDProses")))
Await t
If t.Status = TaskStatus.RanToCompletion Then
Return "Success"
Else
Return "Failed"
End If
Catch ex As Exception
Return "Failed"
End Try
End Function
Public Function GetMonthDifference(ByVal startDate As DateTime, ByVal endDate As DateTime) As Integer
Dim monthsApart As Integer = 12 * (startDate.Year - endDate.Year) + startDate.Month - endDate.Month
Return Math.Abs(monthsApart)
End Function
Async Function AddAktelToSQL(ByVal idProses As Integer, ByVal strCbg As String, ByVal tglAwal As Date, ByVal tglAkhir As Date, ByVal bitPlusKCP As Boolean) As Task(Of String)
'Dim tblAktelLog As New DataTable
Dim strConn As String = GetConn(Conn.eOperasional)
Dim objBusOtomasi_Script As New BusOtomasiSample
Dim DtTblSaving As New DataTable
Dim DtTblChecking As New DataTable
Dim DtTblDeposito As New DataTable
Dim DtTblRupa2 As New DataTable
Dim dtCekDeposito, dtCekSaving, dtCekChecking, dtCekRupa As New DataTable
Try
'RUPA
dtCekRupa = objBusOtomasi_Script.CekRupaBulanAtSudahProses(strConn, idProses, tglAwal.Month, tglAwal.Year, strCbg, bitPlusKCP)
If dtCekRupa.Rows.Count = 0 Then
DtTblRupa2.Clear()
DtTblRupa2 = await GetDtTbleRupa(idProses, tglAwal, tglAkhir, strCbg, bitPlusKCP)
objBusOtomasi_Script.BulkCopyRupaRupa(strConn, DtTblRupa2)
End If
'DEPOSITO
dtCekDeposito = objBusOtomasi_Script.CekBulanAtSudahProses(strConn, idProses, tglAwal.Month, tglAwal.Year, "DEPOSITO", strCbg, bitPlusKCP)
If dtCekDeposito.Rows.Count = 0 Then
DtTblDeposito.Clear()
DtTblDeposito = await GetDtTbleDeposito(idProses, tglAwal, tglAkhir, strCbg, bitPlusKCP)
objBusOtomasi_Script.bulkCopyAktTel(strConn, DtTblDeposito) 'import Deposito
End If
Return "Success"
Catch ex As Exception
'objBusOtomasi_Script.DelAktelbyID(strConn, idProses)
EmailError(ex.ToString)
Finally
strConn = Nothing
End Try
End Function
Async Function GetDtTbleDeposito(ByVal idProsesAktel As Integer, ByVal TglAwal As Date, ByVal TglAkhir As Date, ByVal KdCbg As String, ByVal FlagPlusKCP As Boolean) As Task(Of DataTable)
Dim strDWH As String
Dim objOraConn As New OracleConnection(GetConn(Conn.DWH))
Dim objOraComm As New OracleCommand
Dim objDtTableDeposito As New DataTable
Dim oraAdapter As OracleDataAdapter
Try
strDWH = "select * from ***"
Await objOraConn.OpenAsync()
oraAdapter = New OracleDataAdapter(objOraComm)
objDtTableDeposito = New DataTable
oraAdapter.Fill(objDtTableDeposito)
objOraConn.Close()
Catch ex As Exception
EmailError(ex.ToString)
End Try
Return objDtTableDeposito
End Function
Async Function GetDtTbleRupa(ByVal idProsesAktel As Integer, ByVal TglAwal As Date, ByVal TglAkhir As Date, ByVal KdCbg As String, ByVal FlagPlusKCP As Boolean) As Task(Of DataTable)
Dim strDWH As String
Dim objOraConn As New OracleConnection(GetConn(Conn.DWH))
Dim objOraComm As New OracleCommand
Dim objDtTableRupa2 As New DataTable
Dim oraAdapter As OracleDataAdapter
Try
strDWH = "select * from *** "
Await objOraConn.OpenAsync()
oraAdapter = New OracleDataAdapter(objOraComm)
objDtTableRupa2 = New DataTable
oraAdapter.Fill(objDtTableRupa2)
objOraConn.Close()
Catch ex As Exception
EmailError(ex.ToString)
End Try
Return objDtTableRupa2
End Function
Private Sub GET_CITIZENSHIP_DESC(ByVal idProses As Integer)
Dim strConn As String = GetConn(Conn.eOperasional)
Dim strDWH As String
Dim objOraConn As New OracleConnection(GetConn(Conn.DWH))
Dim objOraComm As New OracleCommand
Dim objDtTableDeposito As New DataTable
Dim oraAdapter As OracleDataAdapter
Dim dtData, dtListCust, dtResult As New DataTable
Dim busOtomasi As New BusOtomasiSample
Try
strDWH = "select * from ** "
dtListCust = busOtomasi.GetCisFromAktel(strConn, idProses)
If dtListCust.Rows.Count > 0 Then
For i = 0 To dtListCust.Rows.Count - 1
objOraConn.Open()
objOraComm = New OracleCommand(strDWH, objOraConn)
oraAdapter = New OracleDataAdapter(objOraComm)
dtData = New DataTable
oraAdapter.Fill(dtData)
If dtData.Rows.Count > 0 Then
dtResult.Merge(dtData.Copy)
End If
objOraConn.Close()
Next
busOtomasi.BulkCopyCustomerAktel(strConn, dtResult)
End If
Catch ex As Exception
EmailError(ex.ToString)
End Try
End Sub
End Module
What should i do to make this work

How do i get all columns / rows from my Database [VB.Net/MariaDB]

I am trying to get all results with the MySQL.Data Nuget because I am using MariaDB. But my Method just provides the first entry in my DB and does nothing more.
Public Function getAllFields(ByVal sql As String) As List(Of String)
Dim output As List(Of String) = New List(Of String)
Using cn = New MySqlConnection(connString.ToString())
Using cmd = New MySqlCommand(sql, cn)
cn.Open()
Using rd = cmd.ExecuteReader()
rd.Read()
Dim objs(rd.FieldCount) As Object
Dim quant As Integer = rd.GetValues(objs)
Dim i As Integer
For i = 0 To quant - 1
output.Add(objs(i))
Next i
rd.Close()
End Using
cn.Close()
End Using
End Using
Return output
End Function
The call to rd.Read returns True when data is read, and False otherwise. So you need to loop until it returns False.
Using rd = cmd.ExecuteReader()
While rd.Read()
Dim objs(rd.FieldCount) As Object
Dim quant As Integer = rd.GetValues(objs)
Dim i As Integer
For i = 0 To quant - 1
output.Add(objs(i))
Next i
End While
End Using

How to convert 2 dimensional arraylist to datatable?

I need a function that returns a datatable, from any arraylist (2 dimensions) as arguments? Thanks for your help
Creating two dimensional Arraylist:
Public Overrides Function Find(Optional ByRef conditions As ArrayList = Nothing) As System.Collections.ArrayList
Dim collection As New ArrayList
Dim cmd ......... ' Select command based on an arraylist of conditions
Dim dr As SqlDataReader = cmd.ExecuteReader()
While dr.Read()
Dim cnt As New contact
cnt .Id() = dr("id")
cnt .Name= dr("name")
'......... other columns are imported
collection.Add(cnt )
End While
dr.Close()
Return collection
End Function
Suitable solution found:
Public Shared Function ArrayListToDataTable(ByVal arraylist1 As ArrayList) As System.Data.DataTable
Dim dt As New System.Data.DataTable()
For i As Integer = 0 To arraylist1.Count - 1
Dim GenericObject As Object = arraylist1.Item(i)
Dim NbrProp As Integer = GenericObject.GetType().GetProperties().Count
For Each item As PropertyInfo In GenericObject.GetType().GetProperties()
Try
Dim column = New DataColumn()
Dim ColName As String = item.Name.ToString
column.ColumnName = ColName
dt.Columns.Add(column)
Catch
End Try
Next
Dim row As DataRow = dt.NewRow()
Dim j As Integer = 0
For Each item As PropertyInfo In GenericObject.GetType().GetProperties()
row(j) = item.GetValue(GenericObject, Nothing)
j += 1
Next
dt.Rows.Add(row)
Next
Return dt
End Function
After 2 years, Let me answer this=>
Function ConvertArrayListToDataTable(ByVal arraylist As ArrayList) As DataTable
Dim dt As DataTable = New DataTable()
If arraylist.Count <= 0 Then
Return dt
End If
Dim propertiesinfo As PropertyInfo() = arraylist(0).GetType().GetProperties()
For Each pf As PropertyInfo In propertiesinfo
Dim dc As DataColumn = New DataColumn(pf.Name)
dc.DataType = pf.PropertyType
dt.Columns.Add(dc)
Next
For Each ar As Object In arraylist
Dim dr As DataRow = dt.NewRow
Dim pf As PropertyInfo() = ar.GetType().GetProperties()
For Each prop As PropertyInfo In pf
dr(prop.Name) = prop.GetValue(ar, Nothing)
Next
dt.Rows.Add(dr)
Next
Return dt
End Function

convert csv data to DataTable in VB.net, capturing column names from row 0

I've adapted the code from the #tim-schmelter answer to question convert csv data to DataTable in VB.net (see below)
I would like to parse in the column titles from row 0 of the csv file
DT|Meter Number|Customer Account Number|Serial Number|Port...
but I'm not having any luck trying to figure out how to do this. any suggestions would be very appreciated.
Public Function csvToDatatable_2(ByVal filename As String, ByVal separator As String)
'////////////////////////////////////////
'Reads a selected txt or csv file into a datatable
'based on code from http://stackoverflow.com/questions/11118678/convert-csv-data-to-datatable-in-vb-net
'////////////////////////////////////////
Dim dt As System.Data.DataTable
Try
dt = New System.Data.DataTable
Dim lines = IO.File.ReadAllLines(filename)
Dim colCount = lines.First.Split(separator).Length
For i As Int32 = 1 To colCount
dt.Columns.Add(New DataColumn("Column_" & i, GetType(String)))
Next
For Each line In lines
Dim objFields = From field In line.Split(separator)
Dim newRow = dt.Rows.Add()
newRow.ItemArray = objFields.ToArray()
Next
Catch ex As Exception
Main.Msg2User(ex.Message.ToString)
Return Nothing
End Try
Return dt
End Function
Just loop thru all the line of the file. Use a boolean to check for the first row.
Public Function csvToDatatable_2(ByVal filename As String, ByVal separator As String)
Dim dt As New System.Data.DataTable
Dim firstLine As Boolean = True
If IO.File.Exists(filename) Then
Using sr As New StreamReader(filename)
While Not sr.EndOfStream
If firstLine Then
firstLine = False
Dim cols = sr.ReadLine.Split(separator)
For Each col In cols
dt.Columns.Add(New DataColumn(col, GetType(String)))
Next
Else
Dim data() As String = sr.Readline.Split(separator)
dt.Rows.Add(data.ToArray)
End If
End While
End Using
End If
Return dt
End Function
Here is a hybrid of the two solutions above, with a few other changes:
Public Shared Function FileToTable(ByVal fileName As String, ByVal separator As String, isFirstRowHeader As Boolean) As DataTable
Dim result As DataTable = Nothing
Try
If Not System.IO.File.Exists(fileName) Then Throw New ArgumentException("fileName", String.Format("The file does not exist : {0}", fileName))
Dim dt As New System.Data.DataTable
Dim isFirstLine As Boolean = True
Using sr As New System.IO.StreamReader(fileName)
While Not sr.EndOfStream
Dim data() As String = sr.ReadLine.Split(separator, StringSplitOptions.None)
If isFirstLine Then
If isFirstRowHeader Then
For Each columnName As String In data
dt.Columns.Add(New DataColumn(columnName, GetType(String)))
Next
isFirstLine = True ' Signal that this row is NOT to be considered as data.
Else
For i As Integer = 1 To data.Length
dt.Columns.Add(New DataColumn(String.Format("Column_{0}", i), GetType(String)))
Next
isFirstLine = False ' Signal that this row IS to be considered as data.
End If
End If
If Not isFirstLine Then
dt.Rows.Add(data.ToArray)
End If
isFirstLine = False ' All subsequent lines shall be considered as data.
End While
End Using
Catch ex As Exception
Throw New Exception(String.Format("{0}.CSVToDatatable Error", GetType(Table).FullName), ex)
End Try
Return result
End Function

Trimming a datagridview duplicat rows except the recent one

i'm in VS2008 Studio, i have this datagridview with multiple columns which the last column contains a date and time value.
lot's of rows are pretty the same except by they're date column.
what i wanted to do is to trim the whole datagridview duplicate rows except they're most recent ones based on they're date column.
i have sth like this:
Administrator,192.168.137.221,2,file://C:\WMPub\WMRoot\industrial.wmv , 07.Jul.2014 - 23:11:59
Administrator,192.168.137.221,2,file://C:\WMPub\WMRoot\industrial.wmv , 07.Jul.2014 -
21:11:59
Administrator,192.168.137.221,2,file://C:\WMPub\WMRoot\industrial.wmv , 07.Jul.2014 - 22:11:59
Administrator,192.168.137.221,2,file://C:\WMPub\WMRoot\industrial.wmv , 07.Jul.2014 - 20:11:59
Administrator,192.168.137.221,2,file://C:\WMPub\WMRoot\industrial.wmv , 07.Jul.2014 - 11:11:59
Everyone ,192.168.137.221,2,file://C:\WMPub\WMRoot\industrial.wmv , 07.Jul.2014 - 17:11:59
Everyone ,192.168.137.221,2,file://C:\WMPub\WMRoot\industrial.wmv , 07.Jul.2014 - 14:11:59
the output i want should be like this:
Administrator 192.168.137.221 2 file://C:\WMPub\WMRoot\industrial.wmv 07.Jul.2014 - 23:11:59
Everyone 192.168.137.201 2 file://C:\WMPub\WMRoot\industrial.wmv 07.Jul.2014 - 17:11:59
....
please consider "," as column seprators! (i dont know how to draw a table here, sorry again)!
i have this snippet that trim the duplicate lines in a datagridview but it lacks preserving the latest entry:
Public Function RemoveDuplicateRows(ByVal dTable As DataTable, ByVal colName As String) As DataTable
Dim hTable As New Hashtable()
Dim duplicateList As New ArrayList()
For Each dtRow As DataRow In dTable.Rows
If hTable.Contains(dtRow(colName)) Then
duplicateList.Add(dtRow)
Else
hTable.Add(dtRow(colName), String.Empty)
End If
Next
For Each dtRow As DataRow In duplicateList
dTable.Rows.Remove(dtRow)
Next
Return dTable
End Function
what should i do?
thanks in advance
Here is some code that illustrates the approach:
Dim dict As New dictionary(Of String, DataRow)
For Each dtRow As DataRow In dTable.Rows
Dim key As String = dtRow("column1") + "," + dtRow("column2") ' + etc.
Dim dictRow As DataRow = Nothing
If dict.TryGetValue(key, dictRow) Then
'check and update date
'you can skip this part, if your data is sorted
If dtRow("dateColumn") > dictRow("dateColumn") Then
dictRow("dateColumn") = dtRow("dateColumn")
End If
Else
dict.Add(key, dtRow)
End If
Next
In the end dict contains the rows you need, you can get them via dict.Values.ToArray()
EDIT: I found the error - dictRow should be dtRow in the above code (now fixed). Then it should work. Here is a full version of self contained example (console app), since I wrote it anyway - focus on RemoveDuplicates, the rest is just prepwork:
Sub Main()
Dim dt As New DataTable
With dt.Columns
.Add("PublishingPoint")
.Add("Username")
.Add("IP")
.Add("Status")
.Add("Req URL")
.Add("Last seen", GetType(Date))
End With
'this populates the initial data table, use your method
Dim _assembly As Assembly = Assembly.GetExecutingAssembly()
Dim _textStreamReader As New StreamReader(_assembly.GetManifestResourceStream("ConsoleApplication16.data.csv"))
While Not _textStreamReader.EndOfStream
Dim sLine As String = _textStreamReader.ReadLine().TrimEnd
If String.IsNullOrEmpty(sLine) Then Exit While
Dim values() As String = sLine.Split(",")
Dim newRow As DataRow = dt.NewRow
For iColumnIndex As Integer = 0 To dt.Columns.Count - 1
Dim columnName As String = dt.Columns(iColumnIndex).ColumnName
newRow.Item(columnName) = values(iColumnIndex)
Next
dt.Rows.Add(newRow)
End While
Console.WriteLine("Old count: " & dt.Rows.Count)
Dim newDt As DataTable = RemoveDuplicates(dt, "Last seen")
Console.WriteLine("New count: " & newDt.Rows.Count)
Console.ReadLine()
End Sub
Private Function RemoveDuplicates(dt As DataTable, colName As String) As DataTable
Dim keyColumnNames As New List(Of String)
Dim exceptColumnsHash As New HashSet(Of String)({colName})
For Each col As DataColumn In dt.Columns
Dim columnName As String = col.ColumnName
If Not exceptColumnsHash.Contains(col.ColumnName) Then
keyColumnNames.Add(columnName)
End If
Next
Dim dict As New Dictionary(Of String, DataRow)
For Each dtRow As DataRow In dt.Rows
Dim keyColumnValues As New List(Of String)
For Each keyColumnName In keyColumnNames
keyColumnValues.Add(dtRow.Item(keyColumnName))
Next
Dim key As String = String.Join(",", keyColumnValues)
Dim dictRow As DataRow = Nothing
If dict.TryGetValue(key, dictRow) Then
If dtRow(colName) > dictRow(colName) Then
dictRow(colName) = dtRow(colName)
End If
Else
dict.Add(key, dtRow)
End If
Next
Dim dtReturn As DataTable = dt.Clone
For Each dtRow As DataRow In dict.Values
dtReturn.ImportRow(dtRow)
Next
Return dtReturn
End Function
To make this code run, you need to manually add a file to the project and set build action to "Embedded resource".