vb.netsplitdate-range

how to repeat date range Between 2 Dates via linq in vb.net


I'M trying to repeat date range Between 2 Dates via linq in vb.net

Below is the start and end date information in the datetimepicker control

startDate = 16-Mar-24
endDate   = 22-Mar-24 

so I want to be able to repeat if it is outside the date the data file is based on ID , [DATE] , INOUT

like the desired result below

Private Sub Form6_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Me.ReadDatFile()
End Sub

Private Sub ReadDatFile()
    OpenFileDialog1.InitialDirectory = "E:\TestFile"
    OpenFileDialog1.Filter = "Dat files(*.Dat)|*.Dat"
    OpenFileDialog1.RestoreDirectory = True
    OpenFileDialog1.ShowDialog()
    Me.Activate()
End Sub

Private Sub OnFilter(ByVal sender As Object, ByVal e As EventArgs) Handles btnFilter.Click
    Dim datfiles As List(Of DatFile) = New List(Of DatFile)()
    Dim lines As String() = File.ReadAllLines(OpenFileDialog1.FileName)

    For i As Integer = 0 To lines.Length - 1
        If Not String.IsNullOrEmpty(lines(i).Trim()) Then
            Dim data As String() = lines(i).Trim().Split(CType(vbTab, Char()))
            datfiles.Add(New DatFile With {
                .ID = Convert.ToInt32(data(0)),
                .DATE = CDate(data(1).ToString().Split(" "c)(0)),
                .TIME = data(1).ToString().Split(" "c)(1),
                .FP = data(2),
                .INOUT = If(data(3).ToString() = "0", "IN", "OUT"),
                .OTHERS1 = data(4),
                .OTHERS2 = data(5)
            })
        End If
    Next
    Dim dtStart As DateTime = Convert.ToDateTime(startDate.Value).Date
    Dim dtEnd As DateTime = Convert.ToDateTime(endDate.Value).Date
    datfiles = datfiles.Where(Function(x) Convert.ToDateTime(x.DATE) >= dtStart AndAlso Convert.ToDateTime(x.DATE) <= dtEnd).ToList()
    DataGridView1.DataSource = datfiles
End Sub

Public Class DatFile
    Public Property ID As Integer
    Public Property [DATE] As DateTime
    Public Property TIME As String
    Public Property FP As String
    <DisplayName("IN/OUT")>
    Public Property INOUT As String
    Public Property OTHERS1 As String
    Public Property OTHERS2 As String
End Class

SAMPLE DAT FILES

 5010   2024-03-17 06:59:10 1   0   0   0
 5014   2024-03-17 07:11:00 1   0   0   0
 5014   2024-03-17 16:32:09 1   1   0   0
 5010   2024-03-17 16:33:19 1   1   0   0
 5010   2024-03-18 06:59:10 1   0   0   0
 5014   2024-03-18 07:11:00 1   0   0   0
 5014   2024-03-18 16:32:09 1   1   0   0
 5010   2024-03-18 16:33:19 1   1   0   0
 5010   2024-03-19 07:05:15 1   0   0   0
 5014   2024-03-19 07:31:19 1   0   0   0
 5014   2024-03-19 16:30:50 1   1   0   0
 5010   2024-03-19 16:31:12 1   1   0   0

RESULT FROM CODE

ID DATE TIME FP INOUT OTHERS1 OTHERS2
5010 17-Mar-24 06:59:10 1 IN 0 0
5014 17-Mar-24 07:11:00 1 IN 0 0
5014 17-Mar-24 16:32:09 1 OUT 0 0
5010 17-Mar-24 16:33:19 1 OUT 0 0
5010 18-Mar-24 06:59:10 1 IN 0 0
5014 18-Mar-24 07:11:00 1 IN 0 0
5014 18-Mar-24 16:32:09 1 OUT 0 0
5010 18-Mar-24 16:33:19 1 OUT 0 0
5010 19-Mar-24 07:05:15 1 IN 0 0
5014 19-Mar-24 07:31:19 1 IN 0 0
5014 19-Mar-24 16:30:50 1 OUT 0 0
5010 19-Mar-24 16:31:12 1 OUT 0 0

DESIRED RESULT

ID DATE TIME FP INOUT OTHERS1 OTHERS2
5010 16-Mar-24 IN
5014 16-Mar-24 IN
5014 16-Mar-24 OUT
5010 16-Mar-24 OUT
5010 17-Mar-24 06:59:10 1 IN 0 0
5014 17-Mar-24 07:11:00 1 IN 0 0
5014 17-Mar-24 16:32:09 1 OUT 0 0
5010 17-Mar-24 16:33:19 1 OUT 0 0
5010 18-Mar-24 06:59:10 1 IN 0 0
5014 18-Mar-24 07:11:00 1 IN 0 0
5014 18-Mar-24 16:32:09 1 OUT 0 0
5010 18-Mar-24 16:33:19 1 OUT 0 0
5010 19-Mar-24 07:05:15 1 IN 0 0
5014 19-Mar-24 07:31:19 1 IN 0 0
5014 19-Mar-24 16:30:50 1 OUT 0 0
5010 19-Mar-24 16:31:12 1 OUT 0 0
5010 20-Mar-24 IN
5014 20-Mar-24 IN
5014 20-Mar-24 OUT
5010 20-Mar-24 OUT
5010 21-Mar-24 IN
5014 21-Mar-24 IN
5014 21-Mar-24 OUT
5010 21-Mar-24 OUT
5010 22-Mar-24 IN
5014 22-Mar-24 IN
5014 22-Mar-24 OUT
5010 22-Mar-24 OUT

Solution

  • This is not a solution based on pure LINQ, but at least it may help.

    After loading the datfiles list, make a list of all IDs:

    DIM All_IDs AS LIST(of integer) = (
        FROM df IN datfiles
        GROUP BY the_ID=df.ID
            INTO GROUP
        SELECT the_ID
        ).tolist
    

    And make a list of all dates from startDate to endDate:

    DIM All_Dates AS NEW LIST(of date)
    DIM day AS date=startDate
    WHILE day <= endDate
        All_Dates.add(day)
        day=day.AddDays(1)
    END WHILE   
    

    In a nested loop that covers all possible combinations of IDs per date, check the missed records and add a record according to it in the datfiles:

    WITH datfiles
        All_Dates.foreach(SUB(the_Date)
            All_IDs.foreach(SUB(the_ID)
                IF .WHERE(FUNCTION(x) x.DATE=the_Date ANDALSO x.ID=the_ID ANDALSO x.INOUT=0).Count=0 THEN
                    .add(NEW datfile WITH {.ID=the_ID , .[DATE]=the_Date , .INOUT=0})
                END IF
                IF .WHERE(FUNCTION(x) x.DATE=the_Date ANDALSO x.ID=the_ID ANDALSO x.INOUT=1).Count=0 THEN
                    .add(NEW datfile WITH {.ID=the_ID , .[DATE]=the_Date , .INOUT=1})
                END IF
            End SUB)
        End SUB)
    END WITH
    

    Now, query the results:

    DIM Results =
        FROM df IN datfiles
        WHERE df.[DATE] >= startDate ANDALSO df.[DATE] <= endDate
        SELECT 
            df.ID,
            df.[DATE],
            df.TIME,
            df.FP,
            INOUT = IF(df.INOUT = 0, "IN", "OUT"),
            df.OTHERS1,
            df.OTHERS2
        ORDER BY [DATE],ID,INOUT