好的,我已經嘗試這個問題 2 周了,不得不承認這讓我發瘋了。
這是資料:
RowText AlloIndex PosIndex FromTime ToTime OverLap
test1 0 0 21/06/2022 14:42 22/06/2022 2:43 0
test2 0 0 21/06/2022 14:42 22/06/2022 2:43 1
test3 0 0 22/06/2022 2:42 22/06/2022 14:43 0
test4 0 0 22/06/2022 14:42 23/06/2022 2:43 0
test5 5 5 21/06/2022 19:42 22/06/2022 7:43 0
test6 6 6 21/06/2022 16:42 22/06/2022 4:43 0
test7 7 7 21/06/2022 15:42 22/06/2022 3:43 0
test8 7 7 21/06/2022 19:42 22/06/2022 7:43 1
test9 8 8 21/06/2022 21:42 22/06/2022 9:43 0
test10 8 8 21/06/2022 22:42 22/06/2022 10:43 1
test11 9 9 22/06/2022 0:42 22/06/2022 12:43 0
test12 9 9 21/06/2022 15:42 22/06/2022 3:43 1
test13 9 9 22/06/2022 12:42 23/06/2022 12:43 1
test14 9 9 22/06/2022 10:42 23/06/2022 10:43 1
test15 10 10 21/06/2022 20:42 22/06/2022 8:43 0
test16 10 10 22/06/2022 1:42 22/06/2022 13:43 1
我正在嘗試做的是,如果在同一個AlloIndex組中有時間重疊,則將重疊的 PosIndex 增加1(那些被確定為重疊的是那些在重疊的同一個AlloIndex組中時間更大的那些。我已經重疊列突出顯示這些)。
但是,這是棘手的部分,如果重疊將PosIndex增加1,則所有其他PosIndex值大于重疊PosIndex的行也增加 1。示例:PosIndex 0 有重疊,所以所有大于 0的PosIndex也有增加 1,從某種意義上說,他們的排名下降了。尤其是PosIdex 9,非常棘手,因為您有 4 個條目和 3 個重疊。因此,您必須將每個重疊條目的PosIndex增加 1(僅保留組中的第一個條目),但任何更大的PosIndex也需要增加 1。希望這是有道理的。
我試過FOR LOOPS,LINQ和lambda無濟于事......
這是我最接近解決這個問題的方法,但是當同一個AlloIndex組中有超過 2 個重疊時它不起作用。
For Each bar In lst
If prevFromDT < bar.ToTime
And prevToDT > bar.FromTime
And prevIndex = bar.PosIndex Then
bar.overLap = True
End If
next
For Each tsk In lst
If tsk.overLap Then
For Each tsk1 In lst
If tsk1.PosIndex > tsk.PosIndex Then
tsk1.PosIndex = 1
Next
End If
Next
For Each tsk In lst
If tsk.overLap Then
tsk.PosIndex = 1
End If
Next
結果資料應如下所示:
RowText AlloIndex PosIndex FromTime ToTime OverLap
test1 0 0 21/06/2022 14:42 22/06/2022 2:43 0
test2 0 1 21/06/2022 14:42 22/06/2022 2:43 1
test3 0 0 22/06/2022 2:42 22/06/2022 14:43 0
test4 0 0 22/06/2022 14:42 23/06/2022 2:43 0
test5 5 6 21/06/2022 19:42 22/06/2022 7:43 0
test6 6 7 21/06/2022 16:42 22/06/2022 4:43 0
test7 7 8 21/06/2022 15:42 22/06/2022 3:43 0
test8 7 9 21/06/2022 19:42 22/06/2022 7:43 1
test9 8 10 21/06/2022 21:42 22/06/2022 9:43 0
test10 8 11 21/06/2022 22:42 22/06/2022 10:43 1
test11 9 12 22/06/2022 0:42 22/06/2022 12:43 0
test12 9 13 21/06/2022 15:42 22/06/2022 3:43 1
test13 9 14 22/06/2022 12:42 23/06/2022 12:43 1
test14 9 15 22/06/2022 10:42 23/06/2022 10:43 1
test15 10 16 21/06/2022 20:42 22/06/2022 8:43 0
test16 10 17 22/06/2022 1:42 22/06/2022 13:43 1
uj5u.com熱心網友回復:
給你...RenderBookings()代碼是無關緊要的 - 它只是為了表明排序的資料是正確的并且匹配它應該看起來的樣子。SortBookings()是你需要看的。


ASPX 代碼...
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="BookingSorting.aspx.vb" Inherits="Scrap.BookingSorting" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h3>Before</h3>
<asp:GridView ID="gv_Before" runat="server" ></asp:GridView>
<h3>After</h3>
<asp:GridView ID="gv_After" runat="server" ></asp:GridView>
<h3>Proof</h3>
<asp:Literal ID="lit_Bars" runat="server" />
</div>
</form>
</body>
</html>
VB.NET 代碼
Public Class BookingSorting
Inherits System.Web.UI.Page
Private Class Booking
Public Property BookingUID As Guid
Public Property Bedroom As String ' AlloIndex
Public Property PosIndex As Integer
Public Property BookingName As String
Public Property DateFrom As Date
Public Property DateTo As Date
Public Property HasClash As Boolean = False
Public Sub New(Bedroom As String, BookingName As String, DateFrom As Date, DateTo As Date)
BookingUID = Guid.NewGuid
Me.Bedroom = Bedroom
Me.BookingName = BookingName
Me.DateFrom = DateFrom
Me.DateTo = DateTo
End Sub
End Class
Private Bookings As List(Of Booking) = New List(Of Booking)
Private Sub SortBookings()
' Simple sort
Bookings = (From x In Bookings Select x Order By x.DateFrom, x.DateTo).ToList
' Check for clashes (will force booking onto a new line in the chart
For Each Booking In Bookings
If (From x In Bookings Where x.DateFrom < Booking.DateTo And x.DateTo > Booking.DateFrom And x.Bedroom = Booking.Bedroom And x.BookingUID <> Booking.BookingUID).Any Then
Booking.HasClash = True
End If
Next
' Somewhere to write the list as we sort it
Dim SortedBookings As List(Of Booking) = New List(Of Booking)
' get a unique list of bedrooms
Dim Beds = (From x In Bookings Select x.Bedroom Distinct).OrderBy(Function(b) b)
' Loop bedrooms
For Each Bed In Beds
Dim BedBookings = (From x In Bookings Where x.Bedroom = Bed Select x Order By x.DateFrom)
Dim InsertBookings As New List(Of Booking)
Dim First As Boolean = True
' Loop bookings for each bedroom
For Each Booking In BedBookings
If Booking.HasClash And Not First Then
Booking.PosIndex = InsertBookings.Count 1
InsertBookings.Add(Booking)
Else
' Add to this row
Booking.PosIndex = 0
SortedBookings.Add(Booking)
End If
First = False
Next
SortedBookings.AddRange(InsertBookings)
Next
Bookings = SortedBookings
End Sub
Private Sub Test()
Bookings.Add(New Booking("Bedroom 06", "Miss Uber", Date.Today.AddHours(7), Date.Today.AddHours(13)))
Bookings.Add(New Booking("Bedroom 01", "Mr Jones", Date.Today.AddHours(9), Date.Today.AddHours(15)))
Bookings.Add(New Booking("Bedroom 03", "Mrs Ave", Date.Today.AddHours(10), Date.Today.AddHours(17)))
Bookings.Add(New Booking("Bedroom 04", "Mr Aubury", Date.Today.AddHours(12), Date.Today.AddHours(22)))
Bookings.Add(New Booking("Bedroom 10", "Mr Orange", Date.Today.AddHours(14), Date.Today.AddHours(19)))
Bookings.Add(New Booking("Bedroom 12", "Mr Black", Date.Today.AddHours(7), Date.Today.AddHours(18)))
Bookings.Add(New Booking("Bedroom 05", "Mr King", Date.Today.AddHours(14), Date.Today.AddHours(20)))
Bookings.Add(New Booking("Bedroom 08", "Mrs Amber", Date.Today.AddHours(6), Date.Today.AddHours(14)))
Bookings.Add(New Booking("Bedroom 09", "Mr & Mrs Red", Date.Today.AddHours(10), Date.Today.AddHours(17)))
Bookings.Add(New Booking("Bedroom 06", "Dr Jones", Date.Today.AddHours(6), Date.Today.AddHours(10)))
Bookings.Add(New Booking("Bedroom 02", "Mr & Mrs Williams", Date.Today.AddHours(8), Date.Today.AddHours(20)))
Bookings.Add(New Booking("Bedroom 09", "Mrs Brown", Date.Today.AddHours(7), Date.Today.AddHours(40)))
Bookings.Add(New Booking("Bedroom 06", "Mr Davis", Date.Today.AddHours(9), Date.Today.AddHours(30)))
Bookings.Add(New Booking("Bedroom 07", "Miss Davies", Date.Today.AddHours(8), Date.Today.AddHours(12)))
Bookings.Add(New Booking("Bedroom 10", "Miss Pink", Date.Today.AddHours(26), Date.Today.AddHours(40)))
Bookings.Add(New Booking("Bedroom 11", "Miss Nathan", Date.Today.AddHours(13), Date.Today.AddHours(28)))
Bookings.Add(New Booking("Bedroom 09", "Mr Green", Date.Today.AddHours(2), Date.Today.AddHours(16)))
gv_Before.DataSource = Bookings
gv_Before.DataBind()
SortBookings()
gv_After.DataSource = Bookings
gv_After.DataBind()
RenderBookings()
End Sub
Private Sub RenderBookings()
Dim s As New StringBuilder
Dim TotalDays As Integer = 0
' get a unique list of bedrooms
Dim Beds = (From x In Bookings Select x.Bedroom Distinct).OrderBy(Function(b) b)
Dim MinDate = (From x In Bookings Select x.DateFrom).Min
Dim MaxDate = (From x In Bookings Select x.DateTo).Max
s.AppendLine("<table style=""border:solid 1px black;"" cellpadding=""2"" cellspacing=""0"" border=""1"">")
' header rows
s.AppendLine("<tr><td rowspan=""2"">Bedroom</td>")
Dim Day, Hour As Integer
For Day = 0 To DateDiff(DateInterval.Day, MinDate, MaxDate) 1
s.AppendLine("<td colspan=""24"" style=""text-align:center;"">" & MinDate.Date.AddDays(Day).ToString("dd/MM/yyyy") & "</td>")
TotalDays = 1
Next
s.AppendLine("</tr><tr>")
For Day = 0 To DateDiff(DateInterval.Day, MinDate, MaxDate) 1
For Hour = 0 To 23
s.AppendLine("<td style=""text-align:center;"">" & Hour.ToString.PadLeft(2, "0") & "</td>")
Next
Next
s.AppendLine("</tr>")
' Loop bedrooms
For Each Bed In Beds
s.AppendLine("<tr style=""height:30px;""><td>" & Bed & "</td><td style=""position:relative;"" colspan=""" & TotalDays * 24 & """>")
Dim BedBookings = (From x In Bookings Where x.Bedroom = Bed Select x)
Dim InsertRows As String = ""
Dim First As Boolean = True
' Loop bookings for each bedroom
For Each Booking In BedBookings
' divide 100 % by the time period in minutes we're trying to cover
Dim Scale As Decimal = (100 / (TotalDays * 24 * 60)) ' 100% / total minutes in the row
' How many whole days are there between this booking and our MinDate.Date?
Dim OffsetDays As Integer = Math.Floor((Booking.DateFrom.Date - MinDate.Date).TotalDays)
' Calculate the left %
Dim Left As Decimal = ((OffsetDays * 24 * 60) (Booking.DateFrom - Booking.DateFrom.Date).TotalMinutes) * Scale
' Calculate the width %
Dim Width As Decimal = (Booking.DateTo - Booking.DateFrom).TotalMinutes * Scale
' Get our Bar HTML
Dim Bar As String = "<div style=""overflow:hidden;position:absolute;border:solid 1px red;background-color:navy;color:#fff;top:3px;width:" & Width & "%;left:" & Left & "%"" title=""" & Booking.DateFrom.ToString("dd/MM/yyyy HH:mm") & " - " & Booking.DateTo.ToString("dd/MM/yyyy HH:mm") & " - " & Booking.Bedroom & """>" & Booking.BookingName & "</div>"
If Booking.HasClash And Not First Then
' We need an insert row here because it's a clash for the same room
InsertRows &= "<tr style=""height:30px;""><td></td><td style=""position:relative;"" colspan=""" & TotalDays * 24 & """>"
InsertRows &= Bar
InsertRows &= "</tr>"
Else
' Add to this row
s.AppendLine(Bar)
End If
First = False
Next
s.AppendLine("</td></tr>{INSERTROWS}")
' Insert our clashing rows
s = s.Replace("{INSERTROWS}", InsertRows)
Next
s.AppendLine("</table>")
lit_Bars.Text = s.ToString
End Sub
Private Sub BookingSorting_Load(sender As Object, e As EventArgs) Handles Me.Load
Test()
End Sub
End Class
uj5u.com熱心網友回復:
我想我已經解決了。我感謝 @fawlty 引導我使用 Linq/Lambda。這是代碼。它有點亂,但它有效。
Private Sub addBedOverLapIndex()
Dim i As Integer
Dim first As Boolean = True
For Each bar In lstBars
If (From x In lstBars Where x.FromTime < bar.ToTime And x.ToTime > bar.FromTime And x.PosIndex = bar.PosIndex And x.BookingUID <> bar.BookingUID).Any Then bar.overLap = True
If bar.overLap Then
Dim test = From x In lstBars Where x.AllocationIndex = bar.AllocationIndex And bar.overLap = True And x.overLap = True
If test.Count > 1 Then
first = True
i = 1
For Each all In test
If Not first Then
all.BedOverLapIndex = i
i = 1
End If
first = False
Next
End If
End If
Next
End Sub
Public Sub sortbars()
Dim j As Integer = 0
Dim first As Boolean = True
addBedOverLapIndex()
Dim RemoveFirstOverlap = lstBars.Where(Function(ol1) ol1.overLap = True).GroupBy(Function(x) x.PosIndex, Function(key, g) g.OrderBy(Function(e) e.PosIndex).FirstOrDefault).ToList()
For Each tst In RemoveFirstOverlap
tst.overLap = False
Next
lstBars = (From x In lstBars Select x Order By x.AllocationIndex, x.BedOverLapIndex).ToList
For Each s In lstBars
If s.overLap Then j = 1
If Not first Then s.PosIndex = j
first = False
Next
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/496418.html
標籤:VB.net
上一篇:VisualBasic生成表單
