交互式甘特图控件,教你如何使用日历!

时间:2024-03-19 13:40:15

VARCHART XGantt是一个交互式的甘特图控件,其模块化的设计让您可以创建满足您和您的客户所需求的应用程序。相较于其他甘特图控件,VARCHART XGantt稳定性高,开发时间长,各大行业的知名公司都在使用它。本文主要描述了如何使用日历教程中的一部分内容,现在跟着小编来了解一下吧~

点击下载VARCHART XGantt免费版

日历表示工作时间和非工作时间的无间隔序列。在具有可变配置文件的日历(轮班日历)中,不同的时间段会重复成功,例如早、晚或夜班。日历本身没有视觉外观,仅是工作时间和非工作时间的逻辑区别。只有将日历分配给CalendarGrid对象,日历才能变得可见。

在VARCHART XGantt中,日历还可以从工期中得出节点的开始和结束日期。如果未设置其他选项,则将使用名为BaseCalendar的预定义基本日历进行所有计算。在基本日历中,将星期一至星期五定义为工作时间,而星期日和星期六则不工作。如果需要,可以修改基本日历。

定义日历

日历可以在设计时通过属性页定义,也可以在运行时通过应用程序编程接口(API)定义。在本文中,我们将从开发人员的角度解释日历的基本处理,并提供一些C#编程示例。

VcGantt控件中,存在一个对象VcCalendarCollection,它负责管理所有日历。它具有与VARCHART XGantt中的其他集合类似的管理功能。预定义的BaseCalendar和在设计时创建的任何其他日历会自动构成集合的一部分。

可以通过CalendarCollection对象的Add方法创建一个新日历。该方法需要唯一的名称才能识别日历。最初,新日历仅由工作时间组成。

请注意:日历必须至少包含一个时间间隔,因为不能存在包含非工作时间的日历。

为了使我们的编程示例的结果可在甘特图的图片中得到验证,为编程示例中的时间范围定义了从2011年1月1日到2011年12月31日的恒定时间段。如果日历在集合中被**,则日历只能在甘特图的背景中可见:

示例代码

'To Create and to activate a new calendar
Dim calendar As VcCalendar
VcGantt1.TimeScaleEnd = "01.01.2012"
VcGantt1.TimeScaleStart = "01.01.2011" 
Set calendar = VcGantt1.CalendarCollection.Add("CompanyCalendar1")
VcGantt1.CalendarCollection.Active = calendar

交互式甘特图控件,教你如何使用日历!

点击下载VARCHART XGantt免费版

如果现在希望重新**默认的基本日历,则可以通过以下设置来执行此操作:

示例代码

'To re-activate the default calendar
Dim calendar As VcCalendar
Set calendar =
VcGantt1.CalendarCollection.CalendarByName("BaseCalendar")
VcGantt1.CalendarCollection.Active = calendar

交互式甘特图控件,教你如何使用日历!

在下面的示例中,我们将显示如何按时间间隔定义工作时间配置文件。定义非工作日的不规则模式:2011年1月1日以及2011年1月6日至1月20日,除了10日和11日的两天:

示例代码

'Defining non-working times
VcGantt1.TimeScaleEnd = "01.01.2012"
VcGantt1.TimeScaleStart = "01.01.2011"
Dim calendar As VcCalendar
Set calendar = VcGantt1.CalendarCollection.Add("CompanyCalendar1")
VcGantt1.CalendarCollection.Active = calendar
Dim interval As VcInterval
Set interval = calendar.IntervalCollection.Add("NewYear")
interval.CalendarProfileName = ""
interval.StartDateTime = "01.01.2011"
interval.EndDateTime = "02.01.2011"
Set interval = calendar.IntervalCollection.Add("NonworkPeriod")
interval.CalendarProfileName = ""
interval.StartDateTime = "06.01.2011" 
interval.EndDateTime = "21.01.2011"
Set interval = calendar.IntervalCollection.Add("WorkPeriod")
interval.CalendarProfileName = ""
interval.StartDateTime = "11.01.2011"
interval.EndDateTime = "13.01.2011"
VcGantt1.CalendarCollection.Update

交互式甘特图控件,教你如何使用日历!

在视觉上,可以通过浅灰色阴影来识别非工作时间。由于默认情况下工作时间没有颜色,因此图表的白色背景在其中仍然可见。在下一步中,我们希望工作时间以浅黄色显示,非工作时间以浅蓝色显示。颜色由可在间隔处定义的图形属性产生。

示例代码

'Assigning colors to intervals
VcGantt1.TimeScaleEnd = "01.01.2012"
VcGantt1.TimeScaleStart = "01.01.2011"
Dim calendar As VcCalendar
Set calendar = VcGantt1.CalendarCollection.Add("CompanyCalendar1")
VcGantt1.CalendarCollection.Active = calendar
VcGantt1.TimeScaleCollection.FirstTimeScale.Section(0).CalendarGridEx(0)
.UseGraphicalAttributesOfIntervals = True
Dim interval As VcInterval
Set interval = calendar.IntervalCollection.Add("Work")
interval.CalendarProfileName = ""
interval.BackColorAsARGB = &HFFFFFFE0
interval.UseGraphicalAttributes = True
Set interval = calendar.IntervalCollection.Add("NewYear")
interval.CalendarProfileName = ""
interval.StartDateTime = "01.01.2011"
interval.EndDateTime = "02.01.2011"
interval.BackColorAsARGB = &HFFD4E3F5
interval.UseGraphicalAttributes = True
Set interval = calendar.IntervalCollection.Add("NonworkPeriod")
interval.CalendarProfileName = ""
interval.StartDateTime = "06.01.2011"
interval.EndDateTime = "21.01.2011"
interval.BackColorAsARGB = &HFFD4E3F5
interval.UseGraphicalAttributes = True
Set interval = calendar.IntervalCollection.Add("WorkPeriod") 
interval.CalendarProfileName = ""
interval.StartDateTime = "11.01.2011"
interval.EndDateTime = "13.01.2011"
interval.BackColorAsARGB = &HFFFFFFE0
interval.UseGraphicalAttributes = True
VcGantt1.CalendarCollection.Update

交互式甘特图控件,教你如何使用日历!

下面的示例显示如何定义一个星期,其中星期一至星期五为工作时间,而周末为空闲时间。到目前为止引入的选项还不足以满足此要求;必须提供VcCalendarProfile类型的对象。

请注意:在VARCHART XGantt中,可以在全局或局部级别上定义VcCalendarProfile对象。本地日历配置文件对象只能在定义它们的日历中使用,而全局对象可以同时在不同的日历中使用。在我们的编程示例中,仅使用本地日历配置文件对象。就功能而言,本地日历与全局日历没有区别。如果创建了具有相同名称的本地配置文件和全局配置文件,则在相应的日历内仅寻址本地配置文件;无法访问全局配置文件。

vcWeekProfile类型的日历配置文件允许描述一周中某天的工作时间和非工作时间。仅在将周配置文件添加到日历的间隔集合后,该配置文件才生效。可以省略设置StartDateTimeEndDateTime,因为我们希望我们的设置在日历的整个期间内都是有效的,没有任何限制。预设名称<WORK><NONWORK>的日历配置文件具有定义的含义:它们用于分配工作时间和非工作时间。

示例代码

'Defining a week profile
Dim calendar As VcCalendar
Dim interval As VcInterval
Dim calendarProfile As VcCalendarProfile
Set calendar = VcGantt1.CalendarCollection.Add("CompanyCalendar1")
VcGantt1.CalendarCollection.Active = calendar
Set calendarProfile =
calendar.CalendarProfileCollection.Add("WeekProfile")
calendarProfile.Type = vcWeekProfile 
VcGantt1.TimeScaleCollection.FirstTimeScale.Section(0).CalendarGridEx(0)
.UseGraphicalAttributesOfIntervals = True
Set interval = calendarProfile.IntervalCollection.Add("Mo-Fr")
interval.CalendarProfileName = ""
interval.StartWeekday = vcMonday
interval.EndWeekday = vcFriday

Set interval = calendarProfile.IntervalCollection.Add("Sa")
interval.CalendarProfileName = ""
interval.BackColorAsARGB = &HFFFFF69F
interval.StartWeekday = vcSaturday
interval.EndWeekday = vcSaturday
Set interval = calendarProfile.IntervalCollection.Add("Su")
interval.CalendarProfileName = ""
interval.BackColorAsARGB = &HFFFBD3AA
interval.StartWeekday = vcSunday
interval.EndWeekday = vcSunday
Set interval = calendar.IntervalCollection.Add("StandardWeek")
interval.CalendarProfileName = "WeekProfile"

区分一天中的工作时间和非工作时间需要一个日配置文件,该日配置文件可以指定精确的时钟时间,例如从8.00 h到12.00 h am和从1.00 h到5.00 h pm。由于新创建的日简介仅包含工作时间,因此任何中断都应定义为非工作间隔。

示例代码

'Defining a day profile
Dim interval As VcInterval
Dim calendarProfile As VcCalendarProfile
Set calendarProfile =
calendar.CalendarProfileCollection.Add("DayProfile")
calendarProfile.Type = vcDayProfile
Set interval = calendarProfile.IntervalCollection.Add("Interval_1")
' 00:00-8:00
interval.CalendarProfileName = ""
interval.StartTime = "1.1.2011 0:00"
interval.EndTime = "1.1.2011 8:00"

Set interval = calendarProfile.IntervalCollection.Add("Interval_2")
' 12:00-13:00
interval.CalendarProfileName = ""
interval.StartTime = "1.1.2011 12:00"
interval.EndTime = "1.1.2011 13:00"
Set interval = calendarProfile.IntervalCollection.Add("Interval_3")
' 17:00-24:00
interval.CalendarProfileName = ""
interval.StartTime = "1.1.2011 17:00"
interval.EndTime = "1.1.2011 00:00"

点击下载VARCHART XGantt免费版

时钟时间由对象DateTime设置。日期部分被忽略,因为在这种情况下它毫无意义。只需要在构造函数中设置日期,即可为构造函数所需的所有参数设置一个值。在Interval_3中,指定0h或24h是很重要的,因为后者在DateTime对象中不被接受。

一年中的定期日期(例如1月1日的除夕夜或12月25日至26日的圣诞节节礼日),由涵盖全年的日历配置文件定义。

示例代码

'Setting a profile of fixed annual holidays
Dim calendarProfile As VcCalendarProfile
Dim interval As VcInterval
Set calendarProfile =
calendar.CalendarProfileCollection.Add("YearProfile")
calendarProfile.Type = vcYearProfile
Set interval = calendarProfile.IntervalCollection.Add("New Year")
interval.CalendarProfileName = ""
interval.DayInStartMonth = 1
interval.StartMonth = vcJanuary
interval.DayInEndMonth = 1
interval.EndMonth = vcJanuary
Call SetAppearanceForHolidays(interval)
Set interval = calendarProfile.IntervalCollection.Add("Christmas")
interval.CalendarProfileName = ""
interval.DayInStartMonth = 25
interval.StartMonth = vcDecember
interval.DayInEndMonth = 26
interval.EndMonth = vcDecember
Call SetAppearanceForHolidays(interval)

为了避免重复设置产生相同的外观,我们使用名为SetAppearanceForHolidays的方法收集调用:

示例代码

'Method to set the visual appearance of holidays
Private Sub SetAppearanceForHolidays(ByVal interval As VcInterval)
 interval.BackColorAsARGB = &HFFFFA4A4
 interval.Pattern = vcWeavePattern
 interval.PatternColorAsARGB = &HFF404040
 interval.LineColor = &HFF808080
 interval.LineThickness = 1
 interval.LineType = vcSolid
 interval.UseGraphicalAttributes = True
End Sub

请注意:颜色属性仅在其CalendarProfileName设置为或的间隔内有效。另外,间隔属性UseGraphicalAttribute需要设置为true。对于calenderGrid属性UseGraphicalAttributesOfIntervals同样如此。

每年必须计算浮动假期(例如复活节)和其他与之相关的假期,并且需要将其作为固定日期分配给日历。下面的方法对此非常有用:

示例代码

'Method to find floating holidays
Const AshWednesday = 0
Const GoodFriday = 1
Const EasterSunday = 2
Const EasterMonday = 3
Const FeastOfCorpusChristi = 4
Const AscensionOfChrist = 5
Const WhitSunday = 6
Const WhitMonday = 7
Const CentralEuropeanSummerTimeStart = 8
Const CentralEuropeanSummerTimeEnd = 9
Private Function calculateAnniversaryForYear(ByVal year As Integer,
ByVal specialDay As Integer) As Date
 Dim g As Integer
 Dim c As Integer
 Dim h As Integer
 Dim i As Integer
 Dim j As Integer
 Dim month As Integer
 Dim day As Integer
 Dim dayOffset As Integer

 g = year Mod 19
 c = year Mod 100
 h = (c - c / 4 - (8 * c + 13) / 25 + 19 * g + 15) Mod 30
 i = h - (h / 28) * (1 - (29 / (h + 1)) * ((21 - g) / 11))
 j = (year + year / 4 + i + 2 - c + c / 4) Mod 7
 month = 3 + (i - j + 40) / 44
 day = i - j + 28 - 31 * (month / 4)
 dayOffset = 0

 Select Case specialDay
 Case AshWednesday
 dayOffset = -40
 Case GoodFriday
 dayOffset = -2
 Case EasterSunday
 dayOffset = 0
 Case EasterMonday
 dayOffset = 1
 Case AscensionOfChrist
 dayOffset = 39
 Case WhitSunday
 dayOffset = 49
 Case WhitMonday
 dayOffset = 50
 Case FeastOfCorpusChristi
 dayOffset = 60
 Case CentralEuropeanSummerTimeStart 
 month = 3
 day = 31 - Weekday("31.3" + yearConvert + 1)
 Case CentralEuropeanSummerTimeEnd
 month = 10
 day = 31 - Weekday("31.10" + yearConvert + 1)
 End Select
 Dim tmpDate As Date
 tmpDate = day & "." & month & "." & year
 calculateAnniversaryForYear = tmpDate + dayOffset
End Function

在下一步中,将周配置文件和假日配置文件作为间隔分配给日历。然后以相同的方式计算浮动假期并将其分配给日历:

示例代码

'Assembling the week profile, the holiday profile and the floating
holidays into an interval
Set interval = calendar.IntervalCollection.Add("Weekly_Pattern")
interval.CalendarProfileName = "WeekProfile"

Set interval = calendar.IntervalCollection.Add("Yearly_Pattern")
interval.CalendarProfileName = "YearProfile"

Dim startYear As Integer
Dim endYear As Integer
startYear = year(VcGantt1.TimeScaleStart)
endYear = year(VcGantt1.TimeScaleEnd)

Dim i As Integer
For i = startYear To endYear Step i + 1
 Set interval = calendar.IntervalCollection.Add("GoodFriday_" & i)
 interval.CalendarProfileName = ""
 interval.StartDateTime = calculateAnniversaryForYear(i, GoodFriday)
 interval.EndDateTime = calculateAnniversaryForYear(i, EasterMonday)
 'interval.StartDateTime
 Call SetAppearanceForHolidays(interval)

 Set interval = calendar.IntervalCollection.Add("EasterMonday_" & i)
 interval.CalendarProfileName = ""
 interval.StartDateTime = calculateAnniversaryForYear(i, EasterMonday)
 interval.EndDateTime = interval.StartDateTime
 Call SetAppearanceForHolidays(interval)

 Set interval =
calendar.IntervalCollection.Add("FeastOfCorpusChristi_" & i)
 interval.CalendarProfileName = ""
 interval.StartDateTime = calculateAnniversaryForYear(i,
FeastOfCorpusChristi)
 interval.EndDateTime = interval.StartDateTime
 Call SetAppearanceForHolidays(interval)

 Set interval = calendar.IntervalCollection.Add("AscensionOfChrist_" &
i)
 interval.CalendarProfileName = ""
 interval.StartDateTime = calculateAnniversaryForYear(i,
AscensionOfChrist)
 interval.EndDateTime = interval.StartDateTime 
 Call SetAppearanceForHolidays(interval)

 Set interval = calendar.IntervalCollection.Add("WhitMonday_" & i)
 interval.CalendarProfileName = ""
 interval.StartDateTime = calculateAnniversaryForYear(i, WhitMonday)
 interval.EndDateTime = interval.StartDateTime
 Call SetAppearanceForHolidays(interval)
Next

VcGantt1.CalendarCollection.Update

交互式甘特图控件,教你如何使用日历!

这些是组装日历所需的摘要步骤。根据要求,可以省略单个步骤:

  1. 创建不同工作日的日配置文件

  2. 通过使用日配置文件组装周配置文件

  3. 定义假期资料

  4. 将星期概要和假日概要分配给日历的间隔集合

  5. 为间隔集合分配其他日期(例如,浮动假期)

间隔对象允许定义可解释为工作时间或非工作时间的时间段。通过CalendarProfileName属性将句点区分为或。通过此属性,日历还可以引用其他现有配置文件并采用其设置。设置此属性时,请注意,根据间隔类型,只能分配某些配置文件类型。间隔类型由选定的配置文件类型隐式选择。日历配置文件的预设默认值vcDayProfile可以在初始时(即在定义间隔之前)通过相应的设置进行修改。

交互式甘特图控件,教你如何使用日历!

配置文件类型建议允许的间隔类型。例如,日期配置文件始终需要vcDayProfileInterval类型的间隔。

交互式甘特图控件,教你如何使用日历!

日历配置文件可以显示类型为日配置文件周配置文件年配置文件变量配置文件。在一天配置文件中,只能通过在一天的限制范围内的时钟时间来定义间隔。一周配置文件包含要在某些天应用的日期配置文件。年份配置文件分配选定的一天配置文件,这些配置文件适用于单个重复日期或几个重复日期。变量配置文件包含一系列不同的工作时间。根据间隔类型vcCalendarIntervalvcDayProfileIntervalvcWeekProfileIntervalvcYearProfileIntervalvcVariableProfileInterval,仅对象的某些属性是相关的。下表映射了概要文件类型和相关属性。

交互式甘特图控件,教你如何使用日历!

CalendarInterval在精确定义的间隔中描述了唯一的时间跨度。例:2010年5月5日从11:30时到2010年9月15日17:00时。

YearProfileInterval允许定义每年重复一次的天数或时间跨度。例:5月1日或12月24日至26日。

WeekProfileInterval处理一周中的一天或几天。例:星期六或星期一至星期五。

DayProfileInterval处理一天之内的时间规格。例:8.00至17.00。

VariableProfile描述了时间跨度,而不引用定义的日期或时间。时间间隔的单位可以是天、小时、分钟或秒,并且由时间间隔对象的属性TimeUnit指定。例:4小时。

点击下载VARCHART XGantt免费版

如何使用日历进行计算

日历中的计算不一定在时间范围内可见。对象日历AddDuration方法从开始日期和指定的工作时间单位数计算最终日期,同时考虑到非工作时间。传递负号的时间单位将导致从给定的结束日期开始计算开始日期。 CalcDuration方法是AddDuration方法的补充,它从给定的开始日期和结束日期计算工作时间单位(持续时间)数。

交互式甘特图控件,教你如何使用日历!

计算方法是如何工作的

请注意:指定为天、小时、分钟或秒的工作时间单位必须与VcGantt对象的属性TimeUnit定义的时间单位相对应。

AddDuration方法可确保所计算的日期始终位于工作时间间隔内。同时,如果源值位于非工作时间内,则后向计算不一定提供与前向计算的源值相等的结果。

计算的有限可逆性

以交互方式创建或修改活动时,VARCHART XGantt会自动注意活动无法在非工作时间内开始或结束。如果希望通过API创建或修改节点时行为保持一致,则需要通过手动更正开始日期或结束日期来确保这一点。为此,位于非工作时间中的开始日期需要移动到下一个工作时间间隔的开始,并且结束日期对应于上一个工作时间间隔的结束。有一些方法可以确定间隔的极限。

示例代码

If calendar.IsWorktime(StartDate) = False Then
 StartDate = calendar.GetNextIntervalBorder(StartDate)
End If
If calendar.IsWorktime(EndDate) = False Then
 EndDate = calendar.GetNextIntervalBorder(EndDate)
End If

夏令时

VARCHART XGantt自动支持夏令时。在中欧,DST从3月的最后一个星期日开始,到10月的最后一个星期日结束。在夏令时开始时,时钟从2:00 h延迟到3:00 h,在时钟结束时从3:00 h延迟到2:00 h。

夏令时开始:

交互式甘特图控件,教你如何使用日历!

夏令时结束:

交互式甘特图控件,教你如何使用日历!

如果将TimeUnit设置为小时,则在夏时制的开始日期,方法calcDuration检索23小时的时间跨度,而在最后一天,则返回25小时。如果设置为天,则两种情况下的时间跨度均为1天。

检索时间间隔的限制

Calendar对象用于检索时间间隔GetStartOfIntervalGetNextIntervalBorderGetPreviousIntervalBorder的限制的方法,允许迭代工作时间间隔和非工作时间间隔。返回的结果是相对的,并以方法作为参数传递的参考日期为参考。

可以通过Calendar对象的IsWorkTime方法检查日期是否在工作时间或非工作时间。尽管新间隔的开始日期等于上一个间隔的结束日期,但是开始日期始终属于新间隔(向右打开)。

方法GetEndOfPreviousWorkTimeGetStartOfNextWorkTime不提供新的选项,而只是简化了工作时间间隔的处理。

在下面的编程示例中,将检索日历的时间间隔并将其写入文件。此外,计算给定期间内可用的工作时间:

示例代码

Private Sub writeCalendarIntervalsToFile(ByVal filename As String, ByVal
calendar As VcCalendar, ByVal startDate As Date, ByVal endDate As Date,
ByVal listWorkIntervals As Boolean, ByVal listNonWorkIntervals As
Boolean)
Dim tmpStartDate As Date
Dim nextStartDate As Date
Dim totalWorkTime As Integer
Open filename For Output As #1
Print #1, "Time Intervals of " & calendar.Name & "between " & startDate
& " - " & endDate 
 tmpStartDate = startDate
 Do While tmpStartDate < endDate

 nextStartDate = calendar.GetNextIntervalBorder(tmpStartDate)

 If tmpStartDate = nextStartDate Then
 nextStartDate = endDate
 End If

 If nextStartDate > endDate Then
 nextStartDate = endDate
 End If

 If calendar.IsWorktime(tmpStartDate) Then
 If listWorkIntervals Then
 Print #1, "WorkInterval" & " " & tmpStartDate & " " &
nextStartDate
 End If
 Else
 If listNonWorkIntervals Then
 Print #1, "NonWorkInterval" & " " & tmpStartDate & " " &
nextStartDate
 End If
 End If

 tmpStartDate = nextStartDate
Loop

 totalWorkTime = calendar.CalcDuration(startDate, endDate)
 Print #1, "Total work time: " & totalWorkTime & " Units"
 Close #1
End Sub

请注意:日历中的时间间隔可以精确地指定为秒,并且最多可以包含137年(以秒为单位)的间隔。

将时间间隔写入文件的代码

示例代码

Call writeCalendarIntervalsToFile("C:\text.txt", calendar,
VcGantt1.TimeScaleStart, VcGantt1.TimeScaleEnd, True, True)
Time Intervals of CompanyCalendar_1 between
01.01.2011 00:00:00 - 01.01.2012 00:00:00
01.01.2011 00:00:00 - 02.01.2011 00:00:00 non-work time
02.01.2011 00:00:00 - 03.01.2011 00:00:00 non-work time
03.01.2011 00:00:00 - 03.01.2011 08:00:00 non-work time
03.01.2011 08:00:00 - 03.01.2011 12:00:00 work time
03.01.2011 12:00:00 - 03.01.2011 13:00:00 non-work time
03.01.2011 13:00:00 - 03.01.2011 17:00:00 work time
03.01.2011 17:00:00 - 04.01.2011 00:00:00 non-work time
04.01.2011 00:00:00 - 04.01.2011 08:00:00 non-work time
04.01.2011 08:00:00 - 04.01.2011 12:00:00 work time
04.01.2011 12:00:00 - 04.01.2011 13:00:00 non-work time 
04.01.2011 13:00:00 - 04.01.2011 17:00:00 work time
04.01.2011 17:00:00 - 05.01.2011 00:00:00 non-work time
...
30.12.2011 00:00:00 - 30.12.2011 08:00:00 non-work time
30.12.2011 08:00:00 - 30.12.2011 12:00:00 work time
30.12.2011 12:00:00 - 30.12.2011 13:00:00 non-work time
30.12.2011 13:00:00 - 30.12.2011 17:00:00 work time
30.12.2011 17:00:00 - 31.12.2011 00:00:00 non-work time
31.12.2011 00:00:00 - 01.01.2012 00:00:00 non-work time
Total work time: 2064 Units