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
///
/// Event Used: RowsAdded
/// Draws the row number in the row's cell header whenever a row is added.
///
///
///
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
///
/// 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.
///
///
///
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
///
/// 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.
///
///
///
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
///
/// Updates the week ending masked text box with the selected date
/// using the format (MM/DD/YYYY).
///
///
///
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
}
}