217 lines
11 KiB
C#
217 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Forms;
|
|
|
|
namespace AdvertsingProfitControl
|
|
{
|
|
public partial class NewAddRecord : Form
|
|
{
|
|
private static readonly FrmLogConsole LogConsole = FrmLogConsole.GetStaticInstance;
|
|
|
|
public NewAddRecord()
|
|
{
|
|
InitializeComponent();
|
|
//Assign the events that all APC DataGridViews will use.
|
|
projectionsDataGridView.RowsAdded += DisplayRowNumbers;
|
|
inventoryDataGridView.RowsAdded += DisplayRowNumbers;
|
|
actualDataGridView.RowsAdded += DisplayRowNumbers;
|
|
|
|
//Assign the events for the comments text box and display the remaining character count for the user.
|
|
commentsTextBox.TextChanged += DisplayRemainingCommentCharacterCount;
|
|
//commentsTextBox.KeyUp += DisplayRemainingCommentCharacterCount;
|
|
commentsGroupBox.Text = @"Comments (Characters Remaining: " + commentsTextBox.MaxLength + @")";
|
|
|
|
/*
|
|
*
|
|
OnCellLeave(C1)
|
|
OnRowLeave(R1)
|
|
OnCellValidating(C1)
|
|
OnCellValidated(C1)
|
|
OnRowValidating(R1)
|
|
OnRowValidated(R1)
|
|
OnRowEnter(R2)
|
|
OnCellEnter(C2)
|
|
*
|
|
*/
|
|
//Setup the events for that the Projected and Actual Sales DataGridViews will share.
|
|
//Events are assigned with regard to which event gets triggered first and so on..
|
|
projectionsDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
|
|
actualDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
|
|
}
|
|
|
|
#region APC DataGridView Events
|
|
|
|
/// <summary>
|
|
/// Event Used: RowsAdded
|
|
/// Draws the row number in the row's cell header whenever a row is added.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private static void DisplayRowNumbers(object sender, DataGridViewRowsAddedEventArgs e)
|
|
{
|
|
var table = ((DataGridView)sender);
|
|
table.Rows[e.RowIndex].HeaderCell.Value = (e.RowIndex + 1).ToString();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Sales DataGridView Events
|
|
|
|
/// <summary>
|
|
/// Event Used: CellValidating
|
|
/// Validates the contents of a cell, before leaving it. If the contents
|
|
/// are valid then the appropriate formatting is applied if needed.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void ValidateSalesDataGridViewCellContents(object sender, DataGridViewCellValidatingEventArgs e)
|
|
{
|
|
//Grab the DataGirdView that fired the event and make it into a local variable.
|
|
var dataGridView = ((DataGridView)sender);
|
|
//
|
|
var textInfo = new CultureInfo("en-US", false).TextInfo;
|
|
//Check for isNewRow if it is, return no need to check it for anything.
|
|
if (dataGridView.Rows[e.RowIndex].IsNewRow)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//Check to see if the current column is the ad item column.
|
|
if (e.ColumnIndex == 0)
|
|
{
|
|
var adItemText = dataGridView.Rows[e.RowIndex].Cells[0].EditedFormattedValue.ToString();
|
|
//If there is text after all the whitespace has been cleared, clear the error text property regardless of whether or not it is set.
|
|
if (!string.IsNullOrEmpty(Regex.Replace(adItemText, @"\s+", "")))
|
|
{
|
|
//Clear the error text since there is in fact an item entered.
|
|
dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "";
|
|
//Send the ad item text through the formatting engine and assign the new value to the cell.
|
|
dataGridView.Rows[e.RowIndex].Cells[0].Value = TextFormat.FormatAdItemText(adItemText);
|
|
//Force a refresh so the cell's text updates and displays for the user.
|
|
dataGridView.RefreshEdit();
|
|
return;
|
|
}
|
|
//If column one (1) is blank then cancel cell validating.
|
|
if (e.ColumnIndex == 0 && Regex.Replace(adItemText, @"\s+", "") == "") dataGridView.Rows[e.RowIndex].Cells[0].ErrorText = "Ad Item needed"; return;
|
|
}
|
|
//Check to see if the cell is in the "Sold" column.
|
|
if (e.ColumnIndex == 1)
|
|
{
|
|
//This Reg-ex pattern will match any number followed by the word bin(s), to allow specifying the number of bins of product were ordered.
|
|
var inventoryStringCheck = new Regex(@"^[0-9]{1,2} \bbin(s){0,1}\b", RegexOptions.IgnoreCase);
|
|
if (
|
|
inventoryStringCheck.IsMatch(
|
|
dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString()))
|
|
{
|
|
//IF a match has been found, then make sure the word 'bin(s)' is capitalized to keep things looking pretty.
|
|
var input = textInfo.ToTitleCase(dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString());
|
|
dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = input;
|
|
dataGridView.RefreshEdit();
|
|
return;
|
|
}
|
|
}
|
|
//If the column is the "Sale Price" column try to parse the contents to a Double and apply number formatting to the contents.
|
|
//Check for the cost column to see if there are any strings formatted like such:
|
|
var regExpression = new Regex(@"^\d+( *)?/( *)?\${0,1}?\d+(\.\d+)?", RegexOptions.IgnoreCase); // [0-9]/($)?[0-9]
|
|
//IF the current cell is in the sale price column, check for the string format above, else move to the default method.
|
|
if ((e.ColumnIndex == 2) && regExpression.IsMatch(dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString()))
|
|
{
|
|
//Grab the input and split it at the forward slash (/) for formatting.
|
|
var input = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString();
|
|
input = input.Replace(" ", "");
|
|
//Remove any dollar signs as these cause errors.
|
|
input = input.Replace("$", "");
|
|
var stringArray = input.Split('/');
|
|
//Format the last number as Currency, and round it up if necessary.
|
|
dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value =
|
|
$@"{stringArray[0]}/{Math.Round(decimal.Parse(stringArray[1]), 2):C}";
|
|
//Always refresh edit so the new value shows up to the user.
|
|
dataGridView.RefreshEdit();
|
|
return; //And return, there is no need to go further.
|
|
}
|
|
//If the column is any other then check to see if the entered value can be parsed to a double (is a number), if not then throw an error to the user.
|
|
double parsedUserInput;
|
|
if (
|
|
!double.TryParse(
|
|
dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString(),
|
|
out parsedUserInput))
|
|
{
|
|
MessageBox.Show(@"Non numeric characters in column " + (e.ColumnIndex + 1) + @" are not allowed.", @"Invalid Characters Detected");
|
|
e.Cancel = true;
|
|
dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = "";
|
|
dataGridView.RefreshEdit();
|
|
return;
|
|
}
|
|
//IF the index is greater then two (2), then that means we are not in a column that requires special formatting out side of currency.
|
|
if (e.ColumnIndex <= 2) return;
|
|
//IF not, then apply currency formatting to the cell.
|
|
var value = double.Parse(dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString(), NumberStyles.Currency);
|
|
//If all goes well, format the string in question by adding commas and decimal points if applicable.
|
|
dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Math.Round(value, 2).ToString("N", new CultureInfo("en-US"));
|
|
//Always refresh edit so the new value shows up to the user.
|
|
dataGridView.RefreshEdit();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Comments TextBox Events
|
|
/// <summary>
|
|
/// Event Used: KeyUp
|
|
/// Calculates and displays the remaining number of characters left available for the user to enter,
|
|
/// and changes the color of the label displaying the character count to red when 20% or less characters remain.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void DisplayRemainingCommentCharacterCount(object sender, EventArgs e)
|
|
{
|
|
//If the amount of characters left is less then 20% (Or more 80% or more characters have been used) then color the label red, otherwise color it its default color.
|
|
commentsGroupBox.ForeColor = (double)commentsTextBox.TextLength / commentsTextBox.MaxLength < .8 ? default(Color) : Color.DarkRed;
|
|
commentsGroupBox.Text = @"Comments (Characters Remaining: " + (commentsTextBox.MaxLength - commentsTextBox.TextLength) + @")";
|
|
}
|
|
#endregion
|
|
|
|
#region MonthCalendar Events
|
|
/// <summary>
|
|
/// Updates the week ending masked text box with the selected date
|
|
/// using the format (MM/DD/YYYY).
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void UpdateWeekEndingMaskedTextBox(object sender, DateRangeEventArgs e)
|
|
{
|
|
var selectedDate = weekEndingMonthCalendar.SelectionStart;
|
|
if (!selectedDate.ToString("D").StartsWith("Saturday"))
|
|
{
|
|
weekEndingMaskedTextBox.ForeColor = Color.Maroon;
|
|
weekEndingMaskedTextBoxInstructionLabel.Text = @"... or manually enter it here: *";
|
|
errorLabel.Text = @"The date you selected does not appear to be a week ending date.";
|
|
}
|
|
else
|
|
{
|
|
weekEndingMaskedTextBox.ForeColor = Color.Black;
|
|
weekEndingMaskedTextBoxInstructionLabel.Text = @"... or manually enter it here:";
|
|
errorLabel.Text = "";
|
|
}
|
|
weekEndingMaskedTextBox.Text = selectedDate.ToString("MM-dd-yyyy");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Data Grid View Construction Functions
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|