在VB.NET中使用或不使用LINQ格式化DataTable中的数据

时间:2018-11-21 22:30:23

标签: vb.net linq

在尝试正确格式化某些数据时遇到了一些麻烦。

我不确定LINQ在这种情况下是否有帮助,但以下是:

预期产量

openGL.1.so

当前数据输出

March 14
2:00 PM - 7:00 PM | Registration
5:30 PM - 7:00 PM | Meetup
7:30 PM - 9:00 PM | Dinner
March 15
2:00 PM - 7:00 PM | Registration
5:30 PM - 7:00 PM | Meetup

代码结构

March 14
2:00 PM - 7:00 PM | Registration
March 14
5:30 PM - 7:00 PM | Meetup
March 14
7:30 PM - 9:00 PM | Dinner
March 15
2:00 PM - 7:00 PM | Registration
March 15
6:00 PM - 7:00 PM | Meetup

我已经引用了诸如THIS之类的其他SO问题,但是我不确定LINQ是否会使期望的输出更容易获得。

欢迎任何建议。我正在尝试为每个循环添加一个嵌套,然后如果sessionDate相同,则添加一个条件。

****** 更新 *******

我非常感谢您的反馈和有用的答案。我正在尝试对数据进行另一种格式更改。我必须向所有事件项添加特定的SVG图标。 SVG图标特定于“第一”,“最后”,“其余”事件。

我正在尝试使用提供的LINQ答案,但是我对使用它的了解并不深,但是它看起来非常易于阅读。出于本示例的目的,可以将String变量用作first / rest / last的占位符。

我还尝试添加图标,但是我没有使用LINQ。

下面是更新的代码预期的输出

预期输出

Imports System
Imports System.Globalization
Imports System.Data
Imports System.Data.DataSetExtensions

Public Module Module1

    Public Sub Main()
        Dim sessions = SampleTable()
        Dim ci = CultureInfo.CreateSpecificCulture("en-us")
        For Each session In sessions.AsEnumerable()

            Dim sessionID = session.Item("SessionID")
            Dim sessionDate = CDate(session.Item("SessionStartTime")).ToString("M", ci)
            Dim sessionStart = CDate(session.Item("SessionStartTime")).ToString("t", ci)
            Dim sessionEnd = CDate(session.Item("SessionEndTime")).ToString("t", ci)
            Dim sessionTitle = CStr(session.Item("SessionName"))

            Console.WriteLine("{0}", sessionDate)
            Console.WriteLine("{0} - {1} | {2}", sessionStart, sessionEnd, sessionTitle)
        Next
    End Sub

    Public Function SampleTable() As DataTable
        Dim table As New DataTable
        With table
            'Add Named Columns
            .Columns.Add("SessionID", GetType(Integer))
            .Columns.Add("SessionStartTime", GetType(Date))
            .Columns.Add("SessionEndTime", GetType(Date))
            .Columns.Add("SessionName", GetType(String))

            'Add 5 Rows of Data to test
            .Rows.Add(1, #03/14/2019 14:00:00#, #03/14/2019 19:00:00#, "Registration")
            .Rows.Add(1, #03/14/2019 17:30:00#, #03/14/2019 19:00:00#, "Meetup")
            .Rows.Add(1, #03/14/2019 19:30:00#, #03/14/2019 21:00:00#, "Dinner")
            .Rows.Add(2, #03/15/2019 14:00:00#, #03/15/2019 19:00:00#, "Registration")
            .Rows.Add(2, #03/15/2019 18:00:00#, #03/15/2019 19:00:00#, "Meetup")
        End With
        Return table
    End Function
End Module

代码结构

March 14
(Start SVG) 2:00 PM - 7:00 PM | Registration
(Body SVG)  5:30 PM - 7:00 PM | Meetup
(End SVG)   7:30 PM - 9:00 PM | Dinner
March 15
(Start SVG) 2:00 PM - 7:00 PM | Registration
(End SVG)   5:30 PM - 7:00 PM | Meetup

4 个答案:

答案 0 :(得分:2)

使用LINQ时,就像这样

Public Sub Main()

    Dim ci = CultureInfo.CreateSpecificCulture("en-us")

    Dim sessions = SampleTable().AsEnumerable().[Select](Function(x) New With {
        Key .SessionDate = x.Field(Of Date)("SessionStartTime").ToString("M", ci),
        Key .SessionStartTime = x.Field(Of Date)("SessionStartTime").ToString("t", ci),
        Key .SessionEndTime = x.Field(Of Date)("SessionEndTime").ToString("t", ci),
        Key .SessionName = x.Field(Of String)("SessionName")
    })

    For Each g In sessions.GroupBy(Function(s) s.SessionDate)
        Console.WriteLine("{0}", g.Key)
        For Each r In g
            Console.WriteLine("{0} - {1} | {2}", r.SessionStartTime, r.SessionEndTime, r.SessionName)
        Next
    Next

End Sub

添加

基本上,您的思维方式没有错。 添加该代码的位置略有不同。 因为您要处理按日期分组的每一行 必须在该循环中完成。

Public Sub Main()

    Dim ci = CultureInfo.CreateSpecificCulture("en-us")

    Dim sessions = SampleTable().AsEnumerable().[Select](Function(x) New With {
    Key .SessionDate = x.Field(Of Date)("SessionStartTime").ToString("M", ci),
    Key .SessionStartTime = x.Field(Of Date)("SessionStartTime").ToString("t", ci),
    Key .SessionEndTime = x.Field(Of Date)("SessionEndTime").ToString("t", ci),
    Key .SessionName = x.Field(Of String)("SessionName")
})

    For Each g In sessions.GroupBy(Function(s) s.SessionDate)
        Console.WriteLine("{0}", g.Key)
        For Each r In g
            Dim sessionIcon As String
            If r.Equals(g.First) Then
                sessionIcon = "<svg>Start Icon</svg>"
            ElseIf r.Equals(g.Last) Then
                sessionIcon = "<svg>End Icon</svg>"
            Else
                sessionIcon = "<svg>Body Icon</svg>"
            End If
            Console.WriteLine("{3} {0} - {1} | {2}", r.SessionStartTime, r.SessionEndTime, r.SessionName, sessionIcon)
        Next
    Next

End Sub

答案 1 :(得分:1)

如果您不希望花哨的东西,则可能会达到最终结果:

0x0000000000bc724e <+80>:    mov    rax,QWORD PTR [r8+0x8]
0x0000000000bc7252 <+84>:    test   al,0x1
0x0000000000bc7254 <+86>:    je     0xbc7263 <_ZN24CPDF_StreamContentParser10OnOperatorEPKc+101>
0x0000000000bc7256 <+88>:    mov    rdx,QWORD PTR [r8+0x10]
0x0000000000bc725a <+92>:    mov    rdx,QWORD PTR [rdi+rdx*1]
0x0000000000bc725e <+96>:    mov    rax,QWORD PTR [rdx+rax*1-0x1]
0x0000000000bc7263 <+101>:   imul   r9,r9,0x18
0x0000000000bc7267 <+105>:   lea    rdx,[rip+0x180f402]        # 0x23d6670 <_ZL9g_OpCodes>
0x0000000000bc726e <+112>:   add    rdi,QWORD PTR [rdx+r9*1+0x10]
0x0000000000bc7273 <+117>:   call   rax

答案 2 :(得分:0)

我添加了一个复杂功能,可以按任意顺序输入事件,然后将其分类到DataView中。

Sub Main()

        Dim sessions = SampleTable()
        Dim SortedView As New DataView(sessions)
        SortedView.Sort = "SessionStartTime"
        Dim ci = CultureInfo.CreateSpecificCulture("en-us")
        Dim row As DataRowView = SortedView(0)
        Dim currentDate As String = #1/1/1950#.ToString("YYYY-MM-dd") 'CDate(row("SessionStartTime")).Date

        For Each session As DataRowView In SortedView
            If currentDate <> CDate(session.Item("SessionStartTime")).ToString("YYYY-MM-dd") Then

                Dim sessionDate = CDate(session.Item("SessionStartTime")).ToString("M", ci)

                Console.WriteLine("{0}", sessionDate)
                currentDate = CDate(session.Item("SessionStartTime")).ToString("YYYY-MM-dd")
            End If
            Dim sessionID = session.Item("SessionID")
                Dim sessionStart = CDate(session.Item("SessionStartTime")).ToString("t", ci)
                Dim sessionEnd = CDate(session.Item("SessionEndTime")).ToString("t", ci)
                Dim sessionTitle = CStr(session.Item("SessionName"))
                Console.WriteLine("{0} - {1} | {2}", sessionStart, sessionEnd, sessionTitle)

        Next
        Console.ReadLine()

    End Sub
    Public Function SampleTable() As DataTable
        Dim table As New DataTable
        With table
            'Add Named Columns
            .Columns.Add("SessionID", GetType(Integer))
            .Columns.Add("SessionStartTime", GetType(Date))
            .Columns.Add("SessionEndTime", GetType(Date))
            .Columns.Add("SessionName", GetType(String))
            .Rows.Add(2, #03/15/2019 18:00:00#, #03/15/2019 19:00:00#, "Meetup")
            'Add 5 Rows of Data to test
            'Notice that the Events do not have to added in order
            .Rows.Add(2, #03/15/2019 18:00:00#, #03/15/2019 19:00:00#, "Meetup")
            .Rows.Add(1, #03/14/2019 14:00:00#, #03/14/2019 19:00:00#, "Registration")
            .Rows.Add(1, #03/14/2019 17:30:00#, #03/14/2019 19:00:00#, "Meetup")
            .Rows.Add(1, #03/14/2019 19:30:00#, #03/14/2019 21:00:00#, "Dinner")
            .Rows.Add(2, #03/15/2019 14:00:00#, #03/15/2019 19:00:00#, "Registration")

        End With
        Return table
End Function

答案 3 :(得分:0)

在演示者类的帮助下可读的LINQ

Public Class Session
    Private ReadOnly _ci As CultureInfo
    Public ReadOnly Name As String
    Public ReadOnly StartTime As Date
    Public ReadOnly EndTime As Date

    Public Sub New(row As DataRow, CultureInfo ci)
        _ci= ci
        Name = row.Field(Of String)("SessionName")
        StartTime = row.Field(Of Date)("SessionStartTime")
        EndTime = row.Field(Of Date)("SessionEndTime")
    End Sub

    Public Overrides Function ToString() As String
        Return $"{StartTime.ToString("t", ci)} - {EndTime.ToString("t", ci)} | {Name}"
    End Function
End Class

' Format rows with the key row
Dim sessions = SampleTable()
Dim ci = CultureInfo.CreateSpecificCulture("en-us")
var output = 
    sessions.AsEnumerable().
            Select(Function(row) New Session(row, ci)).
            GroupBy(Function(session) session.StartTime.Date).
            Aggregate(new StringBuilder(),
                      Function(builder, day)
                        builder.AppendLine(day.Key.ToString("M", ci))
                        day.Aggregate(builder, Function(b, session) b.AppendLine(session))
                        Return builder
                      End Function).
            ToString()    

Console.WriteLine(output)