Moved the text formatting class to the data table parsing class. Slightly organized the code in the NewModifyRecord form.

This commit is contained in:
2017-11-12 02:27:22 -06:00
parent 4e807e03b9
commit 4b96f6c1fa
11 changed files with 341 additions and 336 deletions
@@ -1,5 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
@@ -188,7 +188,6 @@
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="ReportGenerator.cs" /> <Compile Include="ReportGenerator.cs" />
<Compile Include="TextFormat.cs" />
<Compile Include="BackPageGenerator.cs" /> <Compile Include="BackPageGenerator.cs" />
<Compile Include="FrmAddRecord.cs"> <Compile Include="FrmAddRecord.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
-1
View File
@@ -54,7 +54,6 @@
this.shrinkAcceptButton.TabIndex = 1; this.shrinkAcceptButton.TabIndex = 1;
this.shrinkAcceptButton.Text = "Accept"; this.shrinkAcceptButton.Text = "Accept";
this.shrinkAcceptButton.UseVisualStyleBackColor = true; this.shrinkAcceptButton.UseVisualStyleBackColor = true;
this.shrinkAcceptButton.Click += new System.EventHandler(this.shrinkAcceptButton_Click);
// //
// FrmChangeShrink // FrmChangeShrink
// //
@@ -18,11 +18,5 @@ namespace AdvertsingProfitControl
shrinkNumericUpDown.Value = shrink; shrinkNumericUpDown.Value = shrink;
Shrink = shrink; Shrink = shrink;
} }
private void shrinkAcceptButton_Click(object sender, System.EventArgs e)
{
Shrink = int.Parse(shrinkNumericUpDown.Text);
Close();
}
} }
} }
@@ -6,6 +6,7 @@ using System.Linq;
using System.Transactions; using System.Transactions;
using System.Windows.Forms; using System.Windows.Forms;
using AdvertisingProfitControlData; using AdvertisingProfitControlData;
using DataTableParsingEngine;
namespace AdvertsingProfitControl namespace AdvertsingProfitControl
{ {
+3 -3
View File
@@ -203,7 +203,7 @@
this.createNewRecordEditMainMenu.Name = "createNewRecordEditMainMenu"; this.createNewRecordEditMainMenu.Name = "createNewRecordEditMainMenu";
this.createNewRecordEditMainMenu.Size = new System.Drawing.Size(283, 34); this.createNewRecordEditMainMenu.Size = new System.Drawing.Size(283, 34);
this.createNewRecordEditMainMenu.Text = "&Create New Record"; this.createNewRecordEditMainMenu.Text = "&Create New Record";
this.createNewRecordEditMainMenu.Click += new System.EventHandler(this.createNewRecordEditMainMenu_Click); this.createNewRecordEditMainMenu.Click += new System.EventHandler(this.CreateNewRecordEditMainMenuOnClick);
// //
// helpMainMenu // helpMainMenu
// //
@@ -972,7 +972,7 @@
this.addRecordButton.TabIndex = 26; this.addRecordButton.TabIndex = 26;
this.addRecordButton.Text = "Update Record"; this.addRecordButton.Text = "Update Record";
this.addRecordButton.UseVisualStyleBackColor = true; this.addRecordButton.UseVisualStyleBackColor = true;
this.addRecordButton.Click += new System.EventHandler(this.addRecordButton_Click); this.addRecordButton.Click += new System.EventHandler(this.SaveRecordOnAddRecordButtonClick);
// //
// NewModifyRecord // NewModifyRecord
// //
@@ -985,7 +985,7 @@
this.Name = "NewModifyRecord"; this.Name = "NewModifyRecord";
this.Text = "Modify Record"; this.Text = "Modify Record";
this.WindowState = System.Windows.Forms.FormWindowState.Maximized; this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.NewModifyRecord_FormClosing); this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.CheckFormStateOnClosing);
this.mainLayoutPanel.ResumeLayout(false); this.mainLayoutPanel.ResumeLayout(false);
this.mainLayoutPanel.PerformLayout(); this.mainLayoutPanel.PerformLayout();
this.mainMenuStrip.ResumeLayout(false); this.mainMenuStrip.ResumeLayout(false);
+325 -313
View File
@@ -46,19 +46,6 @@ namespace AdvertsingProfitControl
private int _selectedRowIndex = -1; private int _selectedRowIndex = -1;
public NewModifyRecord(DateTime date)
{
InitializeComponent();
//
weekEndingCalendar.SelectionStart = date;
_currentActiveDate = date;
InitializeForm();
mainTabControl.TabPages.Remove(mainTabControl.TabPages[4]);
Text = @"Modify Record (Current Record: " + date.ToShortDateString() + @")";
_isModifyingRecord = true;
LoadDate(date);
}
public NewModifyRecord() public NewModifyRecord()
{ {
InitializeComponent(); InitializeComponent();
@@ -84,121 +71,17 @@ namespace AdvertsingProfitControl
addRecordButton.Text = @"Add Record"; addRecordButton.Text = @"Add Record";
} }
public void InitializeForm() public NewModifyRecord(DateTime date)
{ {
var db = new AdvertisingProfitControlDbContext(); InitializeComponent();
weekEndingCalendar.BoldedDates = db.WeekEndingDates.Select(zdate => zdate.EndingDate).ToArray(); //
weekEndingCalendar.DateChanged += ValidateDateChanged; weekEndingCalendar.SelectionStart = date;
//next pull all the ad items into memory. _currentActiveDate = date;
_adItemCollection = db.AdItems.Select(x => x.Name).ToList(); InitializeForm();
//Now pull all the suppliers and the ad special list into memory. mainTabControl.TabPages.Remove(mainTabControl.TabPages[4]);
_supplierCollection.AddRange(db.Suppliers.Select(x => x.Name).ToArray()); Text = @"Modify Record (Current Record: " + date.ToShortDateString() + @")";
_adSpecialList.AddRange(db.AdSpecials.Select(x => x.Name).ToArray()); _isModifyingRecord = true;
//Initialize the used ad item collection. LoadDate(date);
_usedAdItems[0] = new List<string>();
_usedAdItems[1] = new List<string>();
//Assign the events for the comments text box and display the remaining character count for the user.
commentsTextBox.TextChanged += DisplayRemainingCommentCharacterCount;
commentsGroupBox.Text = @"Comments (Characters Remaining: " + commentsTextBox.MaxLength + @")";
//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..
//Hook the row add event so we can paint a row number in the header cell of the row.
projectionsDataGridView.RowsAdded += DisplayRowNumbers;
inventoryDataGridView.RowsAdded += DisplayRowNumbers;
actualSalesDataGridView.RowsAdded += DisplayRowNumbers;
//Assign all the tables to store the cell's contents on enter so changes (if any) can be detected and flagged (marked as dirty).
projectionsDataGridView.CellEnter += StoreBeginningCellValue;
inventoryDataGridView.CellEnter += StoreBeginningCellValue;
actualSalesDataGridView.CellEnter += StoreBeginningCellValue;
//Update the selected row index field.
projectionsDataGridView.RowEnter += UpdateSelectedRowIndexOnEnter;
inventoryDataGridView.RowEnter += UpdateSelectedRowIndexOnEnter;
actualSalesDataGridView.RowEnter += UpdateSelectedRowIndexOnEnter;
//Update the contents of the used as item list on row leave.
projectionsDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
inventoryDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
actualSalesDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
//Validate, clean and format the contents of the cell that fires the cell validating event.
projectionsDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
inventoryDataGridView.CellValidating += ValidateInventoryCellContents;
actualSalesDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
//Validate that the row the user is trying to leave is legal (has at least an ad item entered) and prevent the user from leaving the row is its not.
projectionsDataGridView.RowValidating += ValidateProjectedRow;
inventoryDataGridView.RowValidating += ValidateInventoryRow;
actualSalesDataGridView.RowValidating += ValidateActualSalesRow;
//Update the used ad item collection by removing the contents of the ad item column when a row is deleted.
projectionsDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
inventoryDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
actualSalesDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
//Once a row has been removed update the other tables keep them uniform.
projectionsDataGridView.RowsRemoved += ProjectionRowRemoved;
inventoryDataGridView.RowsRemoved += InventoryRowRemoved;
actualSalesDataGridView.RowsRemoved += ActualSalesRowRemoved;
//Grab the underlying text box object in the ad item cell, and build an auto complete list for the user.
projectionsDataGridView.EditingControlShowing += DisplayAutoCompleteOnEditingControlShowing;
inventoryDataGridView.EditingControlShowing += DisplayAutoCompleteOnEditingControlShowing;
actualSalesDataGridView.EditingControlShowing += DisplayAutoCompleteOnEditingControlShowing;
//After all events have been set, construct the DataGridVeiws for use.
ConstructApcDataGridViews();
//Set-up events for the Invoice table.
invoicesDataGridView.CellEnter += StoreBeginningCellValue;
//Validate that the row the user is trying to leave is legal (has at least an ad item entered) and prevent the user from leaving the row is its not.
invoicesDataGridView.RowValidating += ValidateInvoiceRow;
//Validate, clean and format the contents of the cell that fires the cell validating event.
invoicesDataGridView.CellValidating += ValidateInvoicesCellContents;
//Grab the underlying text box object in the ad item cell, and build an auto complete list for the user.
invoicesDataGridView.EditingControlShowing += DisplaySupplierAutoComleteOnEditingShadowControl;
//Subscribe the method to allow the user to delete saved rows from the Invoices table.
invoicesDataGridView.UserDeletingRow += UpdateInvoicesOnRowDeleting;
//Finally build the last DataGridView for the form.
ConstructInvoicesDataGridView();//No weekly sales table is nice.
//Subscribe the comments text box to check if changes have been made on leave.
commentsTextBox.Enter += StoreBeginningTextBoxValue;
commentsTextBox.KeyDown += CheckForKeyCommand;
commentsTextBox.Leave += CheckForTextChangeOnLeave;
//Subscribe the weekly sales text boxes to validation, update required checks and auto-complete methods.
sundayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
sundayWeeklySalesTextBox.Validating += ValidateWeeklySales;
mondayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
mondayWeeklySalesTextBox.Validating += ValidateWeeklySales;
tuesdayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
tuesdayWeeklySalesTextBox.Validating += ValidateWeeklySales;
wednesdayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
wednesdayWeeklySalesTextBox.Validating += ValidateWeeklySales;
thursdayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
thursdayWeeklySalesTextBox.Validating += ValidateWeeklySales;
fridayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
fridayWeeklySalesTextBox.Validating += ValidateWeeklySales;
saturdayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
saturdayWeeklySalesTextBox.Validating += ValidateWeeklySales;
totalWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
totalWeeklySalesTextBox.Validating += ValidateWeeklySales;
//Subscribe the taxable text boxes to validation and update events.
sundayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
sundayTaxableTextBox.Validating += ValidateTaxableFields;
mondayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
mondayTaxableTextBox.Validating += ValidateTaxableFields;
tuesdayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
tuesdayTaxableTextBox.Validating += ValidateTaxableFields;
wednesdayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
wednesdayTaxableTextBox.Validating += ValidateTaxableFields;
thursdayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
thursdayTaxableTextBox.Validating += ValidateTaxableFields;
fridayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
fridayTaxableTextBox.Validating += ValidateTaxableFields;
saturdayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
saturdayTaxableTextBox.Validating += ValidateTaxableFields;
totalTaxableTextBox.Enter += StoreBeginningTextBoxValue;
totalTaxableTextBox.Validating += ValidateTaxableFields;
//Subscribe the Cost Analysis text boxes to the validation and update events.
salesPerManHourTextBox.Enter += StoreBeginningTextBoxValue;
salesPerManHourTextBox.Validating += ValidateCostAnalysisValues;
salaryPercentageTextBox.Enter += StoreBeginningTextBoxValue;
salaryPercentageTextBox.Validating += ValidateCostAnalysisValues;
salaryDollarsTextBox.Enter += StoreBeginningTextBoxValue;
salaryDollarsTextBox.Validating += ValidateCostAnalysisValues;
suppliesTextBox.Enter += StoreBeginningTextBoxValue;
suppliesTextBox.Validating += ValidateCostAnalysisValues;
} }
public sealed override string Text public sealed override string Text
@@ -2666,6 +2549,125 @@ out double beginningBinCount, out string _))
#endregion #endregion
#region Form State Methods
public void InitializeForm()
{
var db = new AdvertisingProfitControlDbContext();
weekEndingCalendar.BoldedDates = db.WeekEndingDates.Select(zdate => zdate.EndingDate).ToArray();
weekEndingCalendar.DateChanged += ValidateDateChanged;
//next pull all the ad items into memory.
_adItemCollection = db.AdItems.Select(x => x.Name).ToList();
//Now pull all the suppliers and the ad special list into memory.
_supplierCollection.AddRange(db.Suppliers.Select(x => x.Name).ToArray());
_adSpecialList.AddRange(db.AdSpecials.Select(x => x.Name).ToArray());
//Initialize the used ad item collection.
_usedAdItems[0] = new List<string>();
_usedAdItems[1] = new List<string>();
//Assign the events for the comments text box and display the remaining character count for the user.
commentsTextBox.TextChanged += DisplayRemainingCommentCharacterCount;
commentsGroupBox.Text = @"Comments (Characters Remaining: " + commentsTextBox.MaxLength + @")";
//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..
//Hook the row add event so we can paint a row number in the header cell of the row.
projectionsDataGridView.RowsAdded += DisplayRowNumbers;
inventoryDataGridView.RowsAdded += DisplayRowNumbers;
actualSalesDataGridView.RowsAdded += DisplayRowNumbers;
//Assign all the tables to store the cell's contents on enter so changes (if any) can be detected and flagged (marked as dirty).
projectionsDataGridView.CellEnter += StoreBeginningCellValue;
inventoryDataGridView.CellEnter += StoreBeginningCellValue;
actualSalesDataGridView.CellEnter += StoreBeginningCellValue;
//Update the selected row index field.
projectionsDataGridView.RowEnter += UpdateSelectedRowIndexOnEnter;
inventoryDataGridView.RowEnter += UpdateSelectedRowIndexOnEnter;
actualSalesDataGridView.RowEnter += UpdateSelectedRowIndexOnEnter;
//Update the contents of the used as item list on row leave.
projectionsDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
inventoryDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
actualSalesDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
//Validate, clean and format the contents of the cell that fires the cell validating event.
projectionsDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
inventoryDataGridView.CellValidating += ValidateInventoryCellContents;
actualSalesDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
//Validate that the row the user is trying to leave is legal (has at least an ad item entered) and prevent the user from leaving the row is its not.
projectionsDataGridView.RowValidating += ValidateProjectedRow;
inventoryDataGridView.RowValidating += ValidateInventoryRow;
actualSalesDataGridView.RowValidating += ValidateActualSalesRow;
//Update the used ad item collection by removing the contents of the ad item column when a row is deleted.
projectionsDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
inventoryDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
actualSalesDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
//Once a row has been removed update the other tables keep them uniform.
projectionsDataGridView.RowsRemoved += ProjectionRowRemoved;
inventoryDataGridView.RowsRemoved += InventoryRowRemoved;
actualSalesDataGridView.RowsRemoved += ActualSalesRowRemoved;
//Grab the underlying text box object in the ad item cell, and build an auto complete list for the user.
projectionsDataGridView.EditingControlShowing += DisplayAutoCompleteOnEditingControlShowing;
inventoryDataGridView.EditingControlShowing += DisplayAutoCompleteOnEditingControlShowing;
actualSalesDataGridView.EditingControlShowing += DisplayAutoCompleteOnEditingControlShowing;
//After all events have been set, construct the DataGridVeiws for use.
ConstructApcDataGridViews();
//Set-up events for the Invoice table.
invoicesDataGridView.CellEnter += StoreBeginningCellValue;
//Validate that the row the user is trying to leave is legal (has at least an ad item entered) and prevent the user from leaving the row is its not.
invoicesDataGridView.RowValidating += ValidateInvoiceRow;
//Validate, clean and format the contents of the cell that fires the cell validating event.
invoicesDataGridView.CellValidating += ValidateInvoicesCellContents;
//Grab the underlying text box object in the ad item cell, and build an auto complete list for the user.
invoicesDataGridView.EditingControlShowing += DisplaySupplierAutoComleteOnEditingShadowControl;
//Subscribe the method to allow the user to delete saved rows from the Invoices table.
invoicesDataGridView.UserDeletingRow += UpdateInvoicesOnRowDeleting;
//Finally build the last DataGridView for the form.
ConstructInvoicesDataGridView();//No weekly sales table is nice.
//Subscribe the comments text box to check if changes have been made on leave.
commentsTextBox.Enter += StoreBeginningTextBoxValue;
commentsTextBox.KeyDown += CheckForKeyCommand;
commentsTextBox.Leave += CheckForTextChangeOnLeave;
//Subscribe the weekly sales text boxes to validation, update required checks and auto-complete methods.
sundayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
sundayWeeklySalesTextBox.Validating += ValidateWeeklySales;
mondayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
mondayWeeklySalesTextBox.Validating += ValidateWeeklySales;
tuesdayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
tuesdayWeeklySalesTextBox.Validating += ValidateWeeklySales;
wednesdayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
wednesdayWeeklySalesTextBox.Validating += ValidateWeeklySales;
thursdayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
thursdayWeeklySalesTextBox.Validating += ValidateWeeklySales;
fridayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
fridayWeeklySalesTextBox.Validating += ValidateWeeklySales;
saturdayWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
saturdayWeeklySalesTextBox.Validating += ValidateWeeklySales;
totalWeeklySalesTextBox.Enter += StoreBeginningTextBoxValue;
totalWeeklySalesTextBox.Validating += ValidateWeeklySales;
//Subscribe the taxable text boxes to validation and update events.
sundayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
sundayTaxableTextBox.Validating += ValidateTaxableFields;
mondayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
mondayTaxableTextBox.Validating += ValidateTaxableFields;
tuesdayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
tuesdayTaxableTextBox.Validating += ValidateTaxableFields;
wednesdayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
wednesdayTaxableTextBox.Validating += ValidateTaxableFields;
thursdayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
thursdayTaxableTextBox.Validating += ValidateTaxableFields;
fridayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
fridayTaxableTextBox.Validating += ValidateTaxableFields;
saturdayTaxableTextBox.Enter += StoreBeginningTextBoxValue;
saturdayTaxableTextBox.Validating += ValidateTaxableFields;
totalTaxableTextBox.Enter += StoreBeginningTextBoxValue;
totalTaxableTextBox.Validating += ValidateTaxableFields;
//Subscribe the Cost Analysis text boxes to the validation and update events.
salesPerManHourTextBox.Enter += StoreBeginningTextBoxValue;
salesPerManHourTextBox.Validating += ValidateCostAnalysisValues;
salaryPercentageTextBox.Enter += StoreBeginningTextBoxValue;
salaryPercentageTextBox.Validating += ValidateCostAnalysisValues;
salaryDollarsTextBox.Enter += StoreBeginningTextBoxValue;
salaryDollarsTextBox.Validating += ValidateCostAnalysisValues;
suppliesTextBox.Enter += StoreBeginningTextBoxValue;
suppliesTextBox.Validating += ValidateCostAnalysisValues;
}
private void ClearFormState() private void ClearFormState()
{ {
projectionsDataGridView.CellEnter -= StoreBeginningCellValue; projectionsDataGridView.CellEnter -= StoreBeginningCellValue;
@@ -2856,6 +2858,191 @@ out double beginningBinCount, out string _))
suppliesTextBox.Validating += ValidateCostAnalysisValues; suppliesTextBox.Validating += ValidateCostAnalysisValues;
} }
private void ClearRow(int rowIndex)
{
foreach (DataGridViewCell cell in projectionsDataGridView.Rows[rowIndex].Cells)
{
if (cell.ColumnIndex == (int)TableGroupParser.SalesTableColumns.AdItem) continue;
var actualSalesCell = actualSalesDataGridView.Rows[rowIndex].Cells[cell.ColumnIndex];
if (cell.ColumnIndex < (int)TableGroupParser.SalesTableColumns.IsHeaderRow)
{
cell.Value = string.Empty;
actualSalesCell.Value = string.Empty;
}
else
{
cell.Value = false;
actualSalesCell.Value = false;
}
}
foreach (DataGridViewCell cell in inventoryDataGridView.Rows[rowIndex].Cells)
{
if (cell.ColumnIndex == (int)TableGroupParser.InventoryTableColumns.AdItem) continue;
if (cell.ColumnIndex < (int)TableGroupParser.InventoryTableColumns.IsHeaderRow)
{
cell.Value = string.Empty;
}
else
{
cell.Value = false;
}
}
}
private void NormalizeApcTables()
{
//Disable validation events in the APC tables.
projectionsDataGridView.CellEnter -= StoreBeginningCellValue;
inventoryDataGridView.CellEnter -= StoreBeginningCellValue;
actualSalesDataGridView.CellEnter -= StoreBeginningCellValue;
projectionsDataGridView.RowLeave -= UpdateUsedAdItemCollectionOnRowLeave;
inventoryDataGridView.RowLeave -= UpdateUsedAdItemCollectionOnRowLeave;
actualSalesDataGridView.RowLeave -= UpdateUsedAdItemCollectionOnRowLeave;
projectionsDataGridView.CellValidating -= ValidateSalesDataGridViewCellContents;
inventoryDataGridView.CellValidating -= ValidateInventoryCellContents;
actualSalesDataGridView.CellValidating -= ValidateSalesDataGridViewCellContents;
projectionsDataGridView.RowValidating -= ValidateProjectedRow;
inventoryDataGridView.RowValidating -= ValidateInventoryRow;
actualSalesDataGridView.RowValidating -= ValidateActualSalesRow;
//END DISABLE EVENTS
informationLabel.Text = string.Empty;
errorLabel.Text = @"Tables unbalanced, attempting repairs.";
var dataGridView = projectionsDataGridView.RowCount > inventoryDataGridView.RowCount
? projectionsDataGridView
: inventoryDataGridView;
dataGridView = dataGridView.RowCount > actualSalesDataGridView.RowCount
? dataGridView
: actualSalesDataGridView;
var maxRowCount = dataGridView.RowCount;
//MessageBox.Show(dataGridView.Name);
var rowParser = new RowParser();
for (var i = 0; i < maxRowCount; i++)
{
if (rowParser.GetRowAttribute(dataGridView.Rows[i]) == RowParser.RowAttribute.AdSpecialRow)
{
_adSpecialIndex = i;
}
if (maxRowCount != projectionsDataGridView.RowCount)
{
if (i < projectionsDataGridView.RowCount)
{
//Force update the existing row with whatever the fuller table has.
if (
projectionsDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue !=
dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue)
{
//Force the creation of the NewRow in the DataGridView.
projectionsDataGridView.Rows.Add();
}
}
else
{
//Add the new row to the projections DataGridView
projectionsDataGridView.Rows.Insert(i - 1);
}
projectionsDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue;
projectionsDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.IsDirty].Value = true;
if (i != _adSpecialIndex)
{
projectionsDataGridView.Rows[i].HeaderCell.Style.BackColor = TableColors.PendingEdit;
}
if (dataGridView == actualSalesDataGridView)
{
projectionsDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.SalePrice].Value =
dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.SalePrice].EditedFormattedValue;
projectionsDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.Cost].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.Cost].EditedFormattedValue;
projectionsDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.ProfitReturn].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.ProfitReturn].EditedFormattedValue;
}
}
if (maxRowCount != inventoryDataGridView.RowCount)
{
if (i < inventoryDataGridView.RowCount)
{
//Force update the existing row with whatever the fuller table has.
if (
inventoryDataGridView.Rows[i].Cells[(int)TableGroupParser.InventoryTableColumns.AdItem].EditedFormattedValue !=
dataGridView.Rows[i].Cells[(int)TableGroupParser.InventoryTableColumns.AdItem].EditedFormattedValue)
{
inventoryDataGridView.Rows.Add();
}
}
else
{
//Add the new row to the projections DataGridView
inventoryDataGridView.Rows.Insert(i - 1);
}
inventoryDataGridView.Rows[i].Cells[(int)TableGroupParser.InventoryTableColumns.AdItem].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.InventoryTableColumns.AdItem].EditedFormattedValue;
inventoryDataGridView.Rows[i].Cells[(int)TableGroupParser.InventoryTableColumns.IsDirty].Value = true;
if (i != _adSpecialIndex)
{
inventoryDataGridView.Rows[i].HeaderCell.Style.BackColor = TableColors.PendingEdit;
}
}
if (maxRowCount != actualSalesDataGridView.RowCount)
{
if (i < actualSalesDataGridView.RowCount)
{
//Force update the existing row with whatever the fuller table has.
if (
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue !=
dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue)
{
//Force the creation of the NewRow in the DataGridView.
actualSalesDataGridView.Rows.Add();
}
}
else
{
//Add the new row to the projections DataGridView
actualSalesDataGridView.Rows.Insert(i - 1);
}
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue;
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.IsDirty].Value = true;
if (i != _adSpecialIndex)
{
actualSalesDataGridView.Rows[i].HeaderCell.Style.BackColor = TableColors.PendingEdit;
}
if (dataGridView == projectionsDataGridView)
{
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.SalePrice].Value =
dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.SalePrice].EditedFormattedValue;
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.Cost].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.Cost].EditedFormattedValue;
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.ProfitReturn].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.ProfitReturn].EditedFormattedValue;
}
}
}
informationLabel.Text = @"Tables balanced.";
//Update the NewRow's header cell text.
projectionsDataGridView.Rows[projectionsDataGridView.RowCount - 1].HeaderCell.Value = projectionsDataGridView.RowCount.ToString();
inventoryDataGridView.Rows[inventoryDataGridView.RowCount - 1].HeaderCell.Value = inventoryDataGridView.RowCount.ToString();
actualSalesDataGridView.Rows[actualSalesDataGridView.RowCount - 1].HeaderCell.Value = actualSalesDataGridView.RowCount.ToString();
//Enable validation events in the APC tables.
projectionsDataGridView.CellEnter += StoreBeginningCellValue;
inventoryDataGridView.CellEnter += StoreBeginningCellValue;
actualSalesDataGridView.CellEnter += StoreBeginningCellValue;
projectionsDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
inventoryDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
actualSalesDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
projectionsDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
inventoryDataGridView.CellValidating += ValidateInventoryCellContents;
actualSalesDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
projectionsDataGridView.RowValidating += ValidateProjectedRow;
inventoryDataGridView.RowValidating += ValidateInventoryRow;
actualSalesDataGridView.RowValidating += ValidateActualSalesRow;
//END ENABLE EVENTS
}
#endregion
#region Data Loading Methods #region Data Loading Methods
private void LoadDate(DateTime date) private void LoadDate(DateTime date)
@@ -4415,6 +4602,8 @@ out double beginningBinCount, out string _))
#endregion #endregion
#region Sales Table Calculation Methods
private static void CalculateTotalPofitReturn(DataGridViewRow salesTableRow) private static void CalculateTotalPofitReturn(DataGridViewRow salesTableRow)
{ {
var sold = salesTableRow.Cells[(int) TableGroupParser.SalesTableColumns.Sold].EditedFormattedValue.ToString(); var sold = salesTableRow.Cells[(int) TableGroupParser.SalesTableColumns.Sold].EditedFormattedValue.ToString();
@@ -4460,12 +4649,16 @@ out double beginningBinCount, out string _))
} }
} }
private void addRecordButton_Click(object sender, EventArgs e) #endregion
private void SaveRecordOnAddRecordButtonClick(object sender, EventArgs e)
{ {
SaveRecords(); SaveRecords();
} }
private void NewModifyRecord_FormClosing(object sender, FormClosingEventArgs e) #region Menu Item Click Events
private void CheckFormStateOnClosing(object sender, FormClosingEventArgs e)
{ {
if (!_isFormDirty) return; if (!_isFormDirty) return;
var result = MessageBox.Show(@"Would you like to save the changes you have made?", @"Save Changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); var result = MessageBox.Show(@"Would you like to save the changes you have made?", @"Save Changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
@@ -4480,7 +4673,7 @@ out double beginningBinCount, out string _))
} }
} }
private void createNewRecordEditMainMenu_Click(object sender, EventArgs e) private void CreateNewRecordEditMainMenuOnClick(object sender, EventArgs e)
{ {
if (_isFormDirty) if (_isFormDirty)
{ {
@@ -4513,189 +4706,6 @@ out double beginningBinCount, out string _))
_isModifyingRecord = false; _isModifyingRecord = false;
} }
private void NormalizeApcTables()
{
//Disable validation events in the APC tables.
projectionsDataGridView.CellEnter -= StoreBeginningCellValue;
inventoryDataGridView.CellEnter -= StoreBeginningCellValue;
actualSalesDataGridView.CellEnter -= StoreBeginningCellValue;
projectionsDataGridView.RowLeave -= UpdateUsedAdItemCollectionOnRowLeave;
inventoryDataGridView.RowLeave -= UpdateUsedAdItemCollectionOnRowLeave;
actualSalesDataGridView.RowLeave -= UpdateUsedAdItemCollectionOnRowLeave;
projectionsDataGridView.CellValidating -= ValidateSalesDataGridViewCellContents;
inventoryDataGridView.CellValidating -= ValidateInventoryCellContents;
actualSalesDataGridView.CellValidating -= ValidateSalesDataGridViewCellContents;
projectionsDataGridView.RowValidating -= ValidateProjectedRow;
inventoryDataGridView.RowValidating -= ValidateInventoryRow;
actualSalesDataGridView.RowValidating -= ValidateActualSalesRow;
//END DISABLE EVENTS
informationLabel.Text = string.Empty;
errorLabel.Text = @"Tables unbalanced, attempting repairs.";
var dataGridView = projectionsDataGridView.RowCount > inventoryDataGridView.RowCount
? projectionsDataGridView
: inventoryDataGridView;
dataGridView = dataGridView.RowCount > actualSalesDataGridView.RowCount
? dataGridView
: actualSalesDataGridView;
var maxRowCount = dataGridView.RowCount;
//MessageBox.Show(dataGridView.Name);
var rowParser = new RowParser();
for (var i = 0; i < maxRowCount; i++)
{
if (rowParser.GetRowAttribute(dataGridView.Rows[i]) == RowParser.RowAttribute.AdSpecialRow)
{
_adSpecialIndex = i;
}
if (maxRowCount != projectionsDataGridView.RowCount)
{
if (i < projectionsDataGridView.RowCount)
{
//Force update the existing row with whatever the fuller table has.
if (
projectionsDataGridView.Rows[i].Cells[(int) TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue !=
dataGridView.Rows[i].Cells[(int) TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue)
{
//Force the creation of the NewRow in the DataGridView.
projectionsDataGridView.Rows.Add();
}
}
else
{
//Add the new row to the projections DataGridView
projectionsDataGridView.Rows.Insert(i - 1);
}
projectionsDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue;
projectionsDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.IsDirty].Value = true;
if (i != _adSpecialIndex)
{
projectionsDataGridView.Rows[i].HeaderCell.Style.BackColor = TableColors.PendingEdit;
}
if (dataGridView == actualSalesDataGridView)
{
projectionsDataGridView.Rows[i].Cells[(int) TableGroupParser.SalesTableColumns.SalePrice].Value =
dataGridView.Rows[i].Cells[(int) TableGroupParser.SalesTableColumns.SalePrice].EditedFormattedValue;
projectionsDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.Cost].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.Cost].EditedFormattedValue;
projectionsDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.ProfitReturn].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.ProfitReturn].EditedFormattedValue;
}
}
if (maxRowCount != inventoryDataGridView.RowCount)
{
if (i < inventoryDataGridView.RowCount)
{
//Force update the existing row with whatever the fuller table has.
if (
inventoryDataGridView.Rows[i].Cells[(int)TableGroupParser.InventoryTableColumns.AdItem].EditedFormattedValue !=
dataGridView.Rows[i].Cells[(int)TableGroupParser.InventoryTableColumns.AdItem].EditedFormattedValue)
{
inventoryDataGridView.Rows.Add();
}
}
else
{
//Add the new row to the projections DataGridView
inventoryDataGridView.Rows.Insert(i - 1);
}
inventoryDataGridView.Rows[i].Cells[(int)TableGroupParser.InventoryTableColumns.AdItem].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.InventoryTableColumns.AdItem].EditedFormattedValue;
inventoryDataGridView.Rows[i].Cells[(int)TableGroupParser.InventoryTableColumns.IsDirty].Value = true;
if (i != _adSpecialIndex)
{
inventoryDataGridView.Rows[i].HeaderCell.Style.BackColor = TableColors.PendingEdit;
}
}
if (maxRowCount != actualSalesDataGridView.RowCount)
{
if (i < actualSalesDataGridView.RowCount)
{
//Force update the existing row with whatever the fuller table has.
if (
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue !=
dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue)
{
//Force the creation of the NewRow in the DataGridView.
actualSalesDataGridView.Rows.Add();
}
}
else
{
//Add the new row to the projections DataGridView
actualSalesDataGridView.Rows.Insert(i - 1);
}
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.AdItem].EditedFormattedValue;
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.IsDirty].Value = true;
if (i != _adSpecialIndex)
{
actualSalesDataGridView.Rows[i].HeaderCell.Style.BackColor = TableColors.PendingEdit;
}
if (dataGridView == projectionsDataGridView)
{
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.SalePrice].Value =
dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.SalePrice].EditedFormattedValue;
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.Cost].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.Cost].EditedFormattedValue;
actualSalesDataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.ProfitReturn].Value = dataGridView.Rows[i].Cells[(int)TableGroupParser.SalesTableColumns.ProfitReturn].EditedFormattedValue;
}
}
}
informationLabel.Text = @"Tables balanced.";
//Update the NewRow's header cell text.
projectionsDataGridView.Rows[projectionsDataGridView.RowCount - 1].HeaderCell.Value = projectionsDataGridView.RowCount.ToString();
inventoryDataGridView.Rows[inventoryDataGridView.RowCount - 1].HeaderCell.Value = inventoryDataGridView.RowCount.ToString();
actualSalesDataGridView.Rows[actualSalesDataGridView.RowCount - 1].HeaderCell.Value = actualSalesDataGridView.RowCount.ToString();
//Enable validation events in the APC tables.
projectionsDataGridView.CellEnter += StoreBeginningCellValue;
inventoryDataGridView.CellEnter += StoreBeginningCellValue;
actualSalesDataGridView.CellEnter += StoreBeginningCellValue;
projectionsDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
inventoryDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
actualSalesDataGridView.RowLeave += UpdateUsedAdItemCollectionOnRowLeave;
projectionsDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
inventoryDataGridView.CellValidating += ValidateInventoryCellContents;
actualSalesDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
projectionsDataGridView.RowValidating += ValidateProjectedRow;
inventoryDataGridView.RowValidating += ValidateInventoryRow;
actualSalesDataGridView.RowValidating += ValidateActualSalesRow;
//END ENABLE EVENTS
}
private void ClearRow(int rowIndex)
{
foreach (DataGridViewCell cell in projectionsDataGridView.Rows[rowIndex].Cells)
{
if (cell.ColumnIndex == (int) TableGroupParser.SalesTableColumns.AdItem) continue;
var actualSalesCell = actualSalesDataGridView.Rows[rowIndex].Cells[cell.ColumnIndex];
if (cell.ColumnIndex < (int) TableGroupParser.SalesTableColumns.IsHeaderRow)
{
cell.Value = string.Empty;
actualSalesCell.Value = string.Empty;
}
else
{
cell.Value = false;
actualSalesCell.Value = false;
}
}
foreach (DataGridViewCell cell in inventoryDataGridView.Rows[rowIndex].Cells)
{
if (cell.ColumnIndex == (int)TableGroupParser.InventoryTableColumns.AdItem) continue;
if (cell.ColumnIndex < (int)TableGroupParser.InventoryTableColumns.IsHeaderRow)
{
cell.Value = string.Empty;
}
else
{
cell.Value = false;
}
}
}
private void ViewLogFiles(object sender, EventArgs e) private void ViewLogFiles(object sender, EventArgs e)
{ {
var form = new FrmLogFileViewer(); var form = new FrmLogFileViewer();
@@ -4713,5 +4723,7 @@ out double beginningBinCount, out string _))
LogConsole.Show(); LogConsole.Show();
} }
} }
#endregion
} }
} }
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("3.4.1.0")] [assembly: AssemblyVersion("3.5.1.0")]
[assembly: AssemblyFileVersion("3.4.1.0")] [assembly: AssemblyFileVersion("3.5.1.0")]
@@ -54,6 +54,7 @@
<Compile Include="TableGroupParser.cs" /> <Compile Include="TableGroupParser.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RowParser.cs" /> <Compile Include="RowParser.cs" />
<Compile Include="TextFormat.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\AdvertisingProfitControlData\AdvertisingProfitControlData.csproj"> <ProjectReference Include="..\AdvertisingProfitControlData\AdvertisingProfitControlData.csproj">
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.6.0.0")] [assembly: AssemblyVersion("1.6.1.0")]
[assembly: AssemblyFileVersion("1.6.0.0")] [assembly: AssemblyFileVersion("1.6.1.0")]
@@ -3,12 +3,12 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
namespace AdvertsingProfitControl namespace DataTableParsingEngine
{ {
/// <summary> /// <summary>
/// Contains methods that assist with managing ad item names. /// Contains methods that assist with managing ad item names.
/// </summary> /// </summary>
internal static class TextFormat public static class TextFormat
{ {
//private static readonly FrmLogConsole LogConsole = FrmLogConsole.GetStaticInstance; //private static readonly FrmLogConsole LogConsole = FrmLogConsole.GetStaticInstance;
@@ -22,8 +22,6 @@ namespace AdvertsingProfitControl
{ {
//Trim all beginning and trailing whitespace characters to start. //Trim all beginning and trailing whitespace characters to start.
adItemText = adItemText.Trim(); adItemText = adItemText.Trim();
var abbreviations = new List<string>();
var words = new List<string>();
var isInsideBrackets = false; var isInsideBrackets = false;
//This just makes the code a bit more readable rather then doing "adItemText[currentCharacter - 1]" to access the previous character. //This just makes the code a bit more readable rather then doing "adItemText[currentCharacter - 1]" to access the previous character.
var isPreviousCharWhiteSpace = false; var isPreviousCharWhiteSpace = false;
@@ -85,6 +83,8 @@ namespace AdvertsingProfitControl
} }
//IF the current character is not a number and the previous character is a white space character //IF the current character is not a number and the previous character is a white space character
//then capitalize the current character and add it to the string. //then capitalize the current character and add it to the string.
List<string> abbreviations;
List<string> words;
if (!char.IsNumber(adItemText[currentCharacter]) && isPreviousCharWhiteSpace) if (!char.IsNumber(adItemText[currentCharacter]) && isPreviousCharWhiteSpace)
{ {
//Check to see the length of the string and determine if the word with the number needs to be capitalized. //Check to see the length of the string and determine if the word with the number needs to be capitalized.
@@ -311,7 +311,7 @@ namespace AdvertsingProfitControl
/// <summary> /// <summary>
/// Determines whether or not a string is an abbreviation or a word. /// Determines whether or not a string is an abbreviation or a word.
/// A word is defined as being at least three (3) characters long and having /// A word is defined as being at least three (3) characters long and having
/// at least one (1) vowel. Where as an abbreviation is defined as less then /// at least one (1) vowel. Where as an abbreviation is defined as less then or equal to
/// three (3) characters long but has at least one (1) character, whether or not /// three (3) characters long but has at least one (1) character, whether or not
/// the string that is two (2) or one (1) characters long has a vowel is meaningless /// the string that is two (2) or one (1) characters long has a vowel is meaningless
/// or being exactly three characters long but having zero (0) vowels. /// or being exactly three characters long but having zero (0) vowels.