/// <summary> /// Loads the data file for the given month if it was not already loaded. /// </summary> /// <param name="monthToLoad">The month to load.</param> /// <returns><b>true</b> if the file was to be loaded.</returns> static public bool LoadDataFileIfNotAlreadyLoaded(DateTime monthToLoad) { bool retVal = false; if (!s_MonthsLoaded.Exists(delegate(DateTime loadedMonth) { return(loadedMonth.Year == monthToLoad.Year && loadedMonth.Month == monthToLoad.Month); })) { retVal = LogFileManager.LoadDataFile(monthToLoad); } return(retVal); }
/// <summary> /// Print Report showing daily activity (optionally showing all tasks) /// </summary> /// <param name="e"></param> private void PrintActivityPage(PrintPageEventArgs e, Point drawLocation) { bool skipRestOfPage = m_needToShowOverallTotals; while (!skipRestOfPage && drawLocation.Y < e.MarginBounds.Bottom && m_currentDateBeingPrinted <= m_endDate) { LogFileManager.LoadDataFileIfNotAlreadyLoaded(m_currentDateBeingPrinted); SortableBindingList <TimeLogEntry> logs = TimeLogEntry.LogsForDay(m_currentDateBeingPrinted); if (null == logs || 0 == logs.Count) { if (!m_skipDaysWithoutTasks) { PrintDayHeaderLine(e, ref drawLocation); e.Graphics.DrawString(Properties.Resources.ReportStrNoActivity, m_detailFont, m_detailBrush, drawLocation); drawLocation.Y += m_detailFont.Height; m_lastDayDisplayed = m_currentDateBeingPrinted; } // Move to next day m_currentDateBeingPrinted = m_currentDateBeingPrinted.AddDays(1); m_customersSeenForDay.Clear(); m_indexOfTaskInCurrentDay = 0; continue; } // If not already past end and do not need to show summary from last page else if (!m_needToShowSummary && m_indexOfTaskInCurrentDay < logs.Count) { TimeLogEntry log = logs[m_indexOfTaskInCurrentDay]; if (!m_customersSeenForDay.Contains(log.Customer.Name)) { m_customersSeenForDay.Add(log.Customer.Name); } // Add to overall totals TimeSpan[] timeSpans = null; if (!m_customerSummaryData.ContainsKey(log.Customer.Name)) { timeSpans = new TimeSpan[2]; m_customerSummaryData[log.Customer.Name] = timeSpans; } else { timeSpans = m_customerSummaryData[log.Customer.Name]; } if (log.IsBillable) { timeSpans[BILLABLE_TIME_INDEX] += log.Duration; } else { timeSpans[NON_BILLABLE_TIME_INDEX] += log.Duration; } if (m_lastDayDisplayed != m_currentDateBeingPrinted) { PrintDayHeaderLine(e, ref drawLocation); m_lastDayDisplayed = m_currentDateBeingPrinted; } if (m_showTasks) { // {0} for {1} from {2} to {3}. Duration{4}({5}) Billable:{6} string durationStr = string.Format("{0}:{1}", log.Duration.Hours.ToString(), log.Duration.Minutes.ToString("00")); string durationPercentStr = string.Format("{0}.{1}", log.Duration.Hours.ToString(), ((int)(log.Duration.Minutes * 100) / 60).ToString("00")); string billiableFlagStr = ""; if (!log.IsBillable) { billiableFlagStr = Properties.Resources.ReportStrNotBillableReportTag; } string taskLine = string.Format(Properties.Resources.ReportStrActivityLine, log.Task.Name, log.Customer.Name, log.StartTime.ToShortTimeString(), log.StopTime.ToShortTimeString(), durationStr, durationPercentStr, billiableFlagStr); e.Graphics.DrawString(taskLine, m_detailFont, m_detailBrush, drawLocation); drawLocation.Y += m_detailFont.Height; } // Move to next item (could bump to next day) ++m_indexOfTaskInCurrentDay; } Point startPoint; Point endPoint; if (null != logs && m_indexOfTaskInCurrentDay >= logs.Count) { if (0 < m_customersSeenForDay.Count) { m_needToShowSummary = true; // See if there is enough room to display the summary (# customers + 1 for totals + 1 for horz line + 1 for header) int summaryHeight = m_summaryFont.Height * (3 + m_customersSeenForDay.Count); if (drawLocation.Y + summaryHeight > e.MarginBounds.Bottom) { // Must wait for next page skipRestOfPage = true; break; } m_needToShowSummary = false; // we are going to print it so clear flag // OK, we have enough room for the summary DrawSummaryHeader(ref drawLocation, e, Properties.Resources.ReportStrCustomerColHeader); TimeSpan dailyTotalTime = new TimeSpan(); TimeSpan dailyBillableTime = new TimeSpan(); TimeSpan dailyNonBillableTime = new TimeSpan(); // Sort customers alphabetically m_customersSeenForDay.Sort(); foreach (string customerName in m_customersSeenForDay) { TimeSpan billableTime = new TimeSpan(); TimeSpan nonBillableTime = new TimeSpan(); // Total up time for this customer foreach (TimeLogEntry log in logs) { if (log.Customer.Name == customerName) { if (log.IsBillable) { billableTime += log.Duration; dailyBillableTime += log.Duration; } else { nonBillableTime += log.Duration; dailyNonBillableTime += log.Duration; } } } DrawSummaryLine(ref drawLocation, e, customerName, billableTime, nonBillableTime); } // Update the overall totals m_overallBillableTime += dailyBillableTime; m_overallNonBillableTime += dailyNonBillableTime; DrawSummaryLine(ref drawLocation, e, Properties.Resources.ReportStrTotalTitle, dailyBillableTime, dailyNonBillableTime); // Draw a dividing line between details and summary (if showing details) startPoint = drawLocation; startPoint.Y += m_summaryFont.Height / 2; endPoint = new Point(e.MarginBounds.Left + e.MarginBounds.Width / 2, drawLocation.Y + m_summaryFont.Height / 2); e.Graphics.DrawLine(m_linePen, startPoint, endPoint); drawLocation.Y += m_summaryFont.Height; } m_indexOfTaskInCurrentDay = 0; m_currentDateBeingPrinted = m_currentDateBeingPrinted.AddDays(1); m_customersSeenForDay.Clear(); } } e.HasMorePages = skipRestOfPage || (m_currentDateBeingPrinted < m_endDate); // See if we need to display the grand totals if (m_needToShowOverallTotals || !e.HasMorePages) { m_needToShowOverallTotals = true; // See if there is enough room to display the summary (# customers + 1 for totals + 1 for horz line + 1 for header) int summaryHeight = m_summaryFont.Height * (3 + m_customerSummaryData.Count); if (drawLocation.Y + summaryHeight > e.MarginBounds.Bottom) { e.HasMorePages = true; // Must put summary on last page } else { m_needToShowOverallTotals = false; // we are going to print it so clear flag if (drawLocation.Y > e.MarginBounds.Top) { drawLocation.Y += m_summaryFont.Height; } // draw a horz line all the way across Point startPoint = drawLocation; startPoint.Y += m_summaryFont.Height / 2; Point endPoint = new Point(e.MarginBounds.Right, drawLocation.Y + m_summaryFont.Height / 2); e.Graphics.DrawLine(m_linePen, startPoint, endPoint); drawLocation.Y += m_summaryFont.Height; DrawSummaryHeader(ref drawLocation, e, Properties.Resources.ReportStrCustomerColHeader); // Sort customers alphabetically List <string> allCustomerNames = new List <string>(); foreach (string key in m_customerSummaryData.Keys) { allCustomerNames.Add(key); } allCustomerNames.Sort(); // Now show each customer's totals TimeSpan overallBillable = new TimeSpan(); TimeSpan overallNonBillable = new TimeSpan(); TimeSpan overallTotal = new TimeSpan(); foreach (string name in allCustomerNames) { TimeSpan[] timeSpans = m_customerSummaryData[name]; DrawSummaryLine(ref drawLocation, e, name, timeSpans[BILLABLE_TIME_INDEX], timeSpans[NON_BILLABLE_TIME_INDEX]); // Add to global total overallBillable += timeSpans[BILLABLE_TIME_INDEX]; overallNonBillable += timeSpans[NON_BILLABLE_TIME_INDEX]; overallTotal += timeSpans[BILLABLE_TIME_INDEX] + timeSpans[NON_BILLABLE_TIME_INDEX]; } DrawSummaryLine(ref drawLocation, e, Properties.Resources.ReportStrTotalTitle, overallBillable, overallNonBillable); e.HasMorePages = false; // this is the end } } }
/// <summary> /// Run through all tasks in given time period and calculate sums. /// </summary> private void CalculateSummaries() { if (m_showTasks) { m_taskSummaryData = new Dictionary <string, Dictionary <string, TimeSpan[]> >(); } while (m_currentDateBeingPrinted <= m_endDate) { LogFileManager.LoadDataFileIfNotAlreadyLoaded(m_currentDateBeingPrinted); SortableBindingList <TimeLogEntry> logs = TimeLogEntry.LogsForDay(m_currentDateBeingPrinted); if (null != logs && 0 != logs.Count) { foreach (TimeLogEntry log in logs) { if (m_showTasks) { // Update task level totals Dictionary <string, TimeSpan[]> taskList = null; // Get the task list for this customer (or create one) if (m_taskSummaryData.ContainsKey(log.Customer.Name)) { taskList = m_taskSummaryData[log.Customer.Name]; } else { taskList = new Dictionary <string, TimeSpan[]>(); m_taskSummaryData[log.Customer.Name] = taskList; } // See if this task exists yet TimeSpan[] taskTimes = null; if (taskList.ContainsKey(log.Task.Name)) { taskTimes = taskList[log.Task.Name]; } else { taskTimes = new TimeSpan[2]; } if (log.IsBillable) { taskTimes[0] += log.Duration; } else { taskTimes[1] += log.Duration; } taskList[log.Task.Name] = taskTimes; } // Update customer level totals TimeSpan[] customerTotals = null; if (m_customerSummaryData.ContainsKey(log.Customer.Name)) { customerTotals = m_customerSummaryData[log.Customer.Name]; } else { customerTotals = new TimeSpan[2]; m_customerSummaryData[log.Customer.Name] = customerTotals; } if (log.IsBillable) { customerTotals[0] += log.Duration; } else { customerTotals[1] += log.Duration; } } } // Move to next day m_currentDateBeingPrinted = m_currentDateBeingPrinted.AddDays(1); } // Sort customer names foreach (string s in m_customerSummaryData.Keys) { m_customersSeenForDay.Add(s); } m_customersSeenForDay.Sort(); // Get ready to run through the list m_customerEnumerator = m_customersSeenForDay.GetEnumerator(); m_needNextCustomer = true; m_needToShowSummary = true; }