diff --git a/.vs/AdvertsingProfitControl/v14/.suo b/.vs/AdvertsingProfitControl/v14/.suo
index 181ff20..33e7f55 100644
Binary files a/.vs/AdvertsingProfitControl/v14/.suo and b/.vs/AdvertsingProfitControl/v14/.suo differ
diff --git a/AdvertsingProfitControl/APCDatabaseWriter.cs b/AdvertsingProfitControl/APCDatabaseWriter.cs
index d68ee8d..21457cd 100644
--- a/AdvertsingProfitControl/APCDatabaseWriter.cs
+++ b/AdvertsingProfitControl/APCDatabaseWriter.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Data.OleDb;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -9,5 +10,8 @@ namespace AdvertsingProfitControl
internal class ApcDatabaseWriter
{
private readonly FrmLogConsole _logConsole = FrmLogConsole.GetStaticInstance;
+ private OleDbConnection oleDbConnection;
+
+
}
}
diff --git a/AdvertsingProfitControl/AdvertsingProfitControl.csproj b/AdvertsingProfitControl/AdvertsingProfitControl.csproj
index 05f7cb7..676fc85 100644
--- a/AdvertsingProfitControl/AdvertsingProfitControl.csproj
+++ b/AdvertsingProfitControl/AdvertsingProfitControl.csproj
@@ -104,6 +104,8 @@
+
+
diff --git a/AdvertsingProfitControl/DatabaseReader.cs b/AdvertsingProfitControl/DatabaseReader.cs
index b9657cc..a3dbd24 100644
--- a/AdvertsingProfitControl/DatabaseReader.cs
+++ b/AdvertsingProfitControl/DatabaseReader.cs
@@ -250,6 +250,63 @@ namespace AdvertsingProfitControl
#region Ad Item Functions
+ public Dictionary GetAdItemsSuggestionDictionary(string connectionString)
+ {
+ var adItemDictionary = new Dictionary();
+
+ var oleDbCommand = new OleDbCommand()
+ {
+ CommandText = "SELECT AdItem.ID, AdItem.AdItem FROM AdItem ORDER BY AdItem.AdItem ASC"
+ };
+ var connection = new OleDbConnection(connectionString);
+ oleDbCommand.Connection = connection;
+
+ using (connection)
+ {
+ using (oleDbCommand)
+ {
+ connection.Open();
+ using (var reader = oleDbCommand.ExecuteReader())
+ {
+ while (reader != null && reader.Read())
+ {
+ adItemDictionary.Add(int.Parse(reader["ID"].ToString()), reader["AdItem"].ToString());
+ }
+ }
+ }
+ }
+
+ return adItemDictionary;
+ }
+
+ public int GetLargestKeyValueForAdItems(string connectionString)
+ {
+ var id = -1;
+ var oleDbCommand = new OleDbCommand()
+ {
+ CommandText = "SELECT MAX(AdItem.ID) FROM AdItem"
+ };
+ var connection = new OleDbConnection(connectionString);
+ oleDbCommand.Connection = connection;
+
+ using (connection)
+ {
+ using (oleDbCommand)
+ {
+ connection.Open();
+ using (var reader = oleDbCommand.ExecuteReader())
+ {
+ while (reader != null && reader.Read())
+ {
+ int.TryParse(reader[0].ToString(), out id);
+ }
+ }
+ }
+ }
+
+ return id;
+ }
+
public string RetrieveAdItemId(string adItemName, string connectionString)
{
var id = "0";
@@ -283,7 +340,7 @@ namespace AdvertsingProfitControl
var adItemList = new List();
var oleDbCommand = new OleDbCommand
{
- CommandText = "SELECT AdItem.AdItem, APC.RowAttribute, APC.FK_AdSpecialName FROM (APC INNER JOIN AdItem ON APC.FK_AdItemID = AdItem.ID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
+ CommandText = "SELECT AdItem.AdItem, ActualSales.RowAttribute, ActualSales.FK_AdSpecialGroupName FROM (ActualSales INNER JOIN AdItem ON ActualSales.FK_AdItemID = AdItem.ID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
};
oleDbCommand.Parameters.AddWithValue("DateID", dateId);
var connection = new OleDbConnection(connectionString);
@@ -297,7 +354,7 @@ namespace AdvertsingProfitControl
{
while (reader != null && reader.Read())
{
- if (reader["FK_AdSpecialName"].ToString() != "" && int.Parse(reader["FK_AdSpecialName"].ToString()) >= 3)
+ if (reader["FK_AdSpecialGroupName"].ToString() != "" && int.Parse(reader["FK_AdSpecialGroupName"].ToString()) >= 3)
{
adItemList.Add(reader[0] + ":2");
}
@@ -620,7 +677,7 @@ namespace AdvertsingProfitControl
var dataTable = new DataTable();
var oleDbCommand = new OleDbCommand()
{
- CommandText = "SELECT AdItem.AdItem, APC.ProjectionSold, APC.ProjectionSalePrice, APC.ProjectionTotalSales, APC.ProjectionCost, APC.ProjectionProfitReturn, APC.ProjectionTotalProfitReturn, APC.GroupNumber, APC.FK_AdSpecialName FROM (AdItem INNER JOIN APC ON AdItem.ID = APC.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
+ CommandText = "SELECT AdItem.AdItem, Projections.Sold, Projections.SalePrice, Projections.TotalSales, Projections.Cost, Projections.ProfitReturn, Projections.TotalProfitReturn, Projections.RowAttribute, Projections.FK_AdSpecialGroupName FROM (AdItem INNER JOIN Projections ON AdItem.ID = Projections.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
};
oleDbCommand.Parameters.AddWithValue("DateID", dateId);
var connection = new OleDbConnection(connectionString);
@@ -645,7 +702,7 @@ namespace AdvertsingProfitControl
var dataTable = new DataTable();
var oleDbCommand = new OleDbCommand()
{
- CommandText = "SELECT AdItem.AdItem, APC.ActualSold, APC.ActualSalePrice, APC.ActualTotalSales, APC.ActualCost, APC.ActualProfitReturn, APC.ActualTotalProfitReturn, APC.GroupNumber, APC.FK_AdSpecialName FROM (AdItem INNER JOIN APC ON AdItem.ID = APC.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
+ CommandText = "SELECT AdItem.AdItem, ActualSales.Sold, ActualSales.SalePrice, ActualSales.TotalSales, ActualSales.Cost, ActualSales.ProfitReturn, ActualSales.TotalProfitReturn, ActualSales.RowAttribute, ActualSales.FK_AdSpecialGroupName FROM (AdItem INNER JOIN ActualSales ON AdItem.ID = ActualSales.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
};
oleDbCommand.Parameters.AddWithValue("DateID", dateId);
var connection = new OleDbConnection(connectionString);
@@ -670,7 +727,7 @@ namespace AdvertsingProfitControl
var dataTable = new DataTable();
var oleDbCommand = new OleDbCommand()
{
- CommandText = "SELECT AdItem.AdItem, APC.BeginingInventory, APC.Received, APC.TotalInventory, APC.EndingInventory, APC.GroupNumber, APC.FK_AdSpecialName FROM (AdItem INNER JOIN APC ON AdItem.ID = APC.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
+ CommandText = "SELECT AdItem.AdItem, Inventory.BeginningInventory, Inventory.Received, Inventory.TotalInventory, Inventory.EndingInventory, Inventory.RowAttribute, Inventory.FK_AdSpecialGroupName FROM (AdItem INNER JOIN Inventory ON AdItem.ID = Inventory.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
};
oleDbCommand.Parameters.AddWithValue("DateID", dateId);
var connection = new OleDbConnection(connectionString);
diff --git a/AdvertsingProfitControl/DatabaseWriter.cs b/AdvertsingProfitControl/DatabaseWriter.cs
index 3ed3a68..277e794 100644
--- a/AdvertsingProfitControl/DatabaseWriter.cs
+++ b/AdvertsingProfitControl/DatabaseWriter.cs
@@ -1,18 +1,321 @@
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
+using System.Transactions;
+using System.Windows.Forms;
namespace AdvertsingProfitControl
{
- class DatabaseWriter
+ internal class DatabaseWriter
{
- private readonly OleDbConnection _connectionobject = new OleDbConnection();
+ private readonly OleDbConnection _oleDbConnection = new OleDbConnection();
private readonly FrmLogConsole _logConsole = FrmLogConsole.GetStaticInstance;
-
public DatabaseWriter(string connectionString)
{
- _connectionobject.ConnectionString = connectionString;
+ _oleDbConnection.ConnectionString = connectionString;
}
+ #region New Code
+
+ ///
+ /// Inserts new records into the specified sales table.
+ /// Supports rolling back the database to prevent corruption.
+ ///
+ /// The data table that contains the data to be inserted.
+ ///
+ ///
+ public Dictionary InsertIntoSalesTable(DataTable salesTable, string connectionString)
+ {
+ var rowIndex = 0;
+ var rows = new Dictionary();
+ var oleDbConnection = new OleDbConnection(connectionString);
+ //IDs from the database can not be zero (0), so this will be the default value (no group).
+ var oleDbCommand = new OleDbCommand
+ {
+ Connection = oleDbConnection
+ };
+ OleDbTransaction oleDbTransaction = null;
+ try
+ {
+ oleDbConnection.Open();
+ oleDbTransaction = oleDbConnection.BeginTransaction();
+ oleDbCommand.Transaction = oleDbTransaction;
+ for (var i = 0; i < salesTable.Rows.Count; i++)
+ {
+ oleDbCommand.CommandText =
+ "INSERT INTO " + salesTable.TableName + " (Sold, SalePrice, TotalSales, Cost, ProfitReturn, TotalProfitReturn, FK_AdItemID, RowAttribute, FK_AdSpecialGroupName, RowPosition, FK_DateID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ //New Sales Table Layout (Based on the Database's Physical Layout)
+ //0: Sold 1:SalePrice 2:TotalSales 3:cost 4:ProfitReturn 5:TotalProfitReturn
+ //6:FK_AdItemID 7:RowAttribute 8:FK_AdSpecialGroupName (ID) 9:RowPosition (not index based)
+ //10:FK_DateID
+ oleDbCommand.Parameters.AddWithValue("Sold", salesTable.Rows[i][0]);
+ oleDbCommand.Parameters.AddWithValue("SalesPrice", salesTable.Rows[i][1]);
+ oleDbCommand.Parameters.AddWithValue("TotalSales", salesTable.Rows[i][2]);
+ oleDbCommand.Parameters.AddWithValue("Cost", salesTable.Rows[i][3]);
+ oleDbCommand.Parameters.AddWithValue("ProfitReturn", salesTable.Rows[i][4]);
+ oleDbCommand.Parameters.AddWithValue("TotalProfitReturn", salesTable.Rows[i][5]);
+ oleDbCommand.Parameters.AddWithValue("adItemID", int.Parse(salesTable.Rows[i][6].ToString()));
+ oleDbCommand.Parameters.AddWithValue("RowAttribute", int.Parse(salesTable.Rows[i][7].ToString()));
+ oleDbCommand.Parameters.AddWithValue("adSpecialID", int.Parse(salesTable.Rows[i][8].ToString()));
+ oleDbCommand.Parameters.AddWithValue("RowPosition", int.Parse(salesTable.Rows[i][9].ToString()));
+ oleDbCommand.Parameters.AddWithValue("dateID", salesTable.Rows[i][10]);
+ oleDbCommand.ExecuteNonQuery();
+ oleDbCommand.Parameters.Clear();
+ rowIndex++;
+ }
+ oleDbTransaction.Commit();
+ foreach (DataRow row in salesTable.Rows)
+ {
+ var rowId = RetrieveRowId(salesTable.TableName, int.Parse(row[6].ToString()), int.Parse(row[10].ToString()));
+ if (int.Parse(row[8].ToString()) != 0)
+ {
+ //Account for the ad special row.
+ rows.Add(int.Parse(row[9].ToString()) + 1, rowId);
+ }
+ else
+ {
+ rows.Add(int.Parse(row[9].ToString()), rowId);
+ }
+ }
+ }
+ catch (OleDbException ex)
+ {
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to write to database: " + ex.Message);
+ if (rowIndex <= 0)
+ {
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Failed to begin parsing data rows, var dump of erroneous row unavailable.");
+ }
+ else
+ {
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Failed on row " + (rowIndex + 1) + " due to the above error. Dumping contents of row " + (rowIndex + 1) + " from " + salesTable.TableName + ".");
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Ad Item ID: \"" +
+ salesTable.Rows[rowIndex][6] + "\" Sold: \"" + salesTable.Rows[rowIndex][0] + "\"");
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Sale Price: \"" + salesTable.Rows[rowIndex][1] + "\" Total Sales: \"" + salesTable.Rows[rowIndex][2] + "\"");
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Cost: \"" + salesTable.Rows[rowIndex][3] + "\" Profit Return: \"" + salesTable.Rows[rowIndex][4] + "\"");
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Total Profit Return: \"" +
+ salesTable.Rows[rowIndex][5] + "\" Ad Special Group: \"" + salesTable.Rows[rowIndex][8] + "\"");
+ }
+ oleDbTransaction?.Rollback();
+ _logConsole.WriteToLog(FrmLogConsole.Level.Critical, "Rollback completed successfully, " + salesTable.TableName+ " table failed on insertion.");
+ }
+ finally
+ {
+ _oleDbConnection.Close();
+ }
+ return rows;
+ }
+
+ public bool UpdateSalesTable(DataTable salesTable, string connectionString)
+ {
+ var wasSuccessful = false;
+ var rowIndex = 0;
+ var oleDbConnection = new OleDbConnection(connectionString);
+ //IDs from the database can not be zero (0), so this will be the default value (no group).
+ var oleDbCommand = new OleDbCommand
+ {
+ Connection = oleDbConnection
+ };
+ OleDbTransaction oleDbTransaction = null;
+ try
+ {
+ oleDbTransaction = oleDbConnection.BeginTransaction();
+ _oleDbConnection.Open();
+ oleDbCommand.Transaction = oleDbTransaction;
+ for (var i = 0; i < salesTable.Rows.Count; i++)
+ {
+ oleDbCommand.CommandText =
+ "UPDATE " + salesTable.TableName + " SET Sold = ?, SalePrice = ?, TotalSales = ?, Cost = ?, ProfitReturn = ?, TotalProfitReturn = ?, RowAttribute = ?, FK_AdSpecialGroupName = ?, RowPosition = ? WHERE ID = ?";
+ //Update Sales Table Layout (Based on the Database's Physical Layout)
+ //0:ID 1:Sold 2:SalePrice 3:TotalSales 4:cost 5:ProfitReturn 6:TotalProfitReturn
+ //7:FK_AdItemID 8:RowAttribute 9:FK_AdSpecialGroupName (ID) 10:RowPosition (not index based)
+ //11:FK_DateID
+ oleDbCommand.Parameters.AddWithValue("Sold", salesTable.Rows[i][1]);
+ oleDbCommand.Parameters.AddWithValue("SalesPrice", salesTable.Rows[i][2]);
+ oleDbCommand.Parameters.AddWithValue("TotalSales", salesTable.Rows[i][3]);
+ oleDbCommand.Parameters.AddWithValue("Cost", salesTable.Rows[i][4]);
+ oleDbCommand.Parameters.AddWithValue("ProfitReturn", salesTable.Rows[i][5]);
+ oleDbCommand.Parameters.AddWithValue("TotalProfitReturn", salesTable.Rows[i][6]);
+ oleDbCommand.Parameters.AddWithValue("RowAttribute", salesTable.Rows[i][8]);
+ oleDbCommand.Parameters.AddWithValue("adSpecialID", salesTable.Rows[i][9]);
+ oleDbCommand.Parameters.AddWithValue("RowPosition", salesTable.Rows[i][10]);
+ oleDbCommand.Parameters.AddWithValue("ID", salesTable.Rows[i][0]);
+ oleDbCommand.ExecuteNonQuery();
+ oleDbCommand.Parameters.Clear();
+ rowIndex++;
+ }
+ oleDbTransaction.Commit();
+ wasSuccessful = true;
+ }
+ catch (OleDbException ex)
+ {
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to update the database for " + salesTable.TableName + ": " + ex.Message);
+ if (rowIndex <= 0)
+ {
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Failed to begin parsing data rows, var dump of erroneous row unavailable.");
+ }
+ else
+ {
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Failed on row " + (rowIndex + 1) + " due to the above error. Dumping contents of row " + (rowIndex + 1) + " from " + salesTable.TableName + ".");
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Ad Item ID: \"" +
+ salesTable.Rows[rowIndex][7] + "\" Sold: \"" + salesTable.Rows[rowIndex][1] + "\"");
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Sale Price: \"" + salesTable.Rows[rowIndex][2] + "\" Total Sales: \"" + salesTable.Rows[rowIndex][3] + "\"");
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Cost: \"" + salesTable.Rows[rowIndex][4] + "\" Profit Return: \"" + salesTable.Rows[rowIndex][5] + "\"");
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Total Profit Return: \"" +
+ salesTable.Rows[rowIndex][6] + "\" Ad Special Group: \"" + salesTable.Rows[rowIndex][9] + "\"");
+ }
+ oleDbTransaction?.Rollback();
+ _logConsole.WriteToLog(FrmLogConsole.Level.Critical, "Rollback completed successfully, " + salesTable.TableName + " table failed on update.");
+ }
+ finally
+ {
+ _oleDbConnection.Close();
+ }
+
+ return wasSuccessful;
+ }
+
+ ///
+ /// Inserts a new ad item into the database and returns the new item's ID number.
+ /// Supports rolling back as to not corrupt the database.
+ ///
+ /// The ad item's name that is to be added.
+ /// A reference to a command that already has a transaction active.
+ /// The ID number of the ad item that was just added.
+ public int InsertNewAdItem(string adItemName, OleDbCommand oleDbCommand = null)
+ {
+ var adItemId = 0;
+ var needsTransaction = false;
+ if (oleDbCommand == null)
+ {
+ oleDbCommand = new OleDbCommand
+ {
+ Connection = _oleDbConnection
+ };
+ needsTransaction = true;
+ }
+ oleDbCommand.CommandText = "INSERT INTO AdItem (AdItem) VALUES (?)";
+ oleDbCommand.Parameters.Clear();
+ oleDbCommand.Parameters.AddWithValue("AdItem", adItemName);
+ OleDbTransaction oleDbTransaction = null;
+ try
+ {
+ if (needsTransaction)
+ {
+ //If the OleDbCommand object is not supplied, then we'll need to create and assign the transaction object.
+ oleDbCommand.Connection = _oleDbConnection;
+ _oleDbConnection.Open();
+ oleDbTransaction = _oleDbConnection.BeginTransaction();
+ oleDbCommand.Transaction = oleDbTransaction;
+ }
+ if (oleDbCommand.ExecuteNonQuery() == 1)
+ {
+ oleDbCommand.CommandText = "SELECT ID FROM AdItem WHERE AdItem.AdItem = ?";
+ oleDbCommand.Parameters.Clear();
+ oleDbCommand.Parameters.AddWithValue("AdItem", adItemName);
+ var reader = oleDbCommand.ExecuteReader();
+ //Get the ID of the new ad item.
+ while (reader != null && reader.Read())
+ {
+ int.TryParse(reader[0].ToString(), out adItemId);
+ }
+ reader?.Close();
+
+ if (adItemId != 0)
+ {
+ //All was successful.
+ oleDbTransaction?.Commit();
+ }
+ else
+ {
+ //
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Ad item \"" + adItemName + "\" was not found in the database; rolling back changes.");
+ oleDbTransaction?.Rollback();
+ }
+ }
+ else
+ {
+ //Something failed but wasn't caught.
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Failed to add the ad item \"" + adItemName + "\" into the database.");
+ oleDbTransaction?.Rollback();
+ }
+ }
+ catch (OleDbException e)
+ {
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error, e.Message);
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Failed to insert ad item " + adItemName + " into the database.");
+ oleDbTransaction?.Rollback();
+ }
+ finally
+ {
+ if (needsTransaction)
+ {
+ _oleDbConnection.Close();
+ }
+ }
+
+ return adItemId;
+ }
+
+ ///
+ /// Infrastructure for the DatabaseWriter class, not meant to be used with external code.
+ /// Grabs the ID of the specified row.
+ ///
+ /// The name of the table to check for the row in.
+ /// The ID of the ad item in the row.
+ /// The ID of the date in the row.
+ /// The ID of the row, zero(0) if no rows are found.
+ private int RetrieveRowId(string tableName, int adItemId, int dateId)
+ {
+ var id = 0;
+ var rowsEffected = 0;
+ var oleDbCommand = new OleDbCommand
+ {
+ CommandText = "SELECT ID FROM " + tableName + " WHERE FK_AdItemID = ? AND FK_DateID = ?",
+ Connection = _oleDbConnection
+ };
+ oleDbCommand.Parameters.AddWithValue("AdItemID", adItemId);
+ oleDbCommand.Parameters.AddWithValue("DateID", dateId);
+
+ try
+ {
+ _oleDbConnection.Open();
+ var reader = oleDbCommand.ExecuteReader();
+ while (reader != null && reader.Read())
+ {
+ rowsEffected++;
+ int.TryParse(reader[0].ToString(), out id);
+ }
+ reader?.Close();
+
+ if (rowsEffected > 1)
+ {
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error,
+ "Redundancy found row with the ad item ID " + adItemId + " with the date ID " + dateId + ".");
+ }
+ }
+ catch (OleDbException e)
+ {
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to look up the existence of a row with the ad item ID " + adItemId + " with the date ID " + dateId + ".");
+ _logConsole.WriteToLog(FrmLogConsole.Level.Error, e.Message);
+ }
+ _oleDbConnection.Close();
+ return id;
+ }
+ #endregion
//10 to 1 ratio of tries to code
//http://codebetter.com/karlseguin/2006/04/05/understanding-and-using-exceptions/nfrastructure
@@ -27,7 +330,7 @@ namespace AdvertsingProfitControl
CommandText = "INSERT INTO WeekEnding(EndOfWeekDate) VALUES ( dateString )"
};
oleDbCommand.Parameters.AddWithValue("dateString", dateString);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
//Try to execute the query
try
{
@@ -35,8 +338,8 @@ namespace AdvertsingProfitControl
//Check for the existence of the date string that was provided.
oleDbCommand.CommandText = "SELECT ID FROM WeekEnding WHERE EndOfWeekDate = @dateString";
oleDbCommand.Parameters.AddWithValue("@dateString", dateString);
- oleDbCommand.Connection = _connectionobject;
- _connectionobject.Open();
+ oleDbCommand.Connection = _oleDbConnection;
+ _oleDbConnection.Open();
//Execute the SELECT statement and retrieve the row(s) effected.
var reader = oleDbCommand.ExecuteReader();
var recordIndex = 0;
@@ -48,7 +351,7 @@ namespace AdvertsingProfitControl
}
recordIndex++;
}
- if (reader != null) reader.Close();
+ reader?.Close();
//IF one row was affected, then return with "True", since the value is already there.
if (numberOfRowsEffected == 1)
{
@@ -103,7 +406,7 @@ namespace AdvertsingProfitControl
finally
{
//Make certain that the connection is closed before returning.
- _connectionobject.Close();
+ _oleDbConnection.Close();
}
return insertWasSuccessful;
@@ -115,7 +418,7 @@ namespace AdvertsingProfitControl
var insertWasSuccessful = false;
var storedComment = "";
//Set up the command object, SQL command string and parameters.
- var oleDbCommand = new OleDbCommand {Connection = _connectionobject};
+ var oleDbCommand = new OleDbCommand {Connection = _oleDbConnection};
//Try to execute the query
try
{
@@ -127,7 +430,7 @@ namespace AdvertsingProfitControl
oleDbCommand.CommandText = "SELECT Comment FROM Comment WHERE FK_DateID = dateID";
oleDbCommand.Parameters.Clear();
oleDbCommand.Parameters.AddWithValue("dateID", dateIdString);
- _connectionobject.Open();
+ _oleDbConnection.Open();
//OpenConnection();
var reader = oleDbCommand.ExecuteReader();
var recordIndex = 0;
@@ -146,7 +449,7 @@ namespace AdvertsingProfitControl
recordIndex++;
}
}
- if (reader != null) reader.Close();
+ reader?.Close();
//IF there is a comment that has the same date then check to see if it is the same as the one entered.
if (recordIndex == 1)
{
@@ -235,7 +538,7 @@ namespace AdvertsingProfitControl
finally
{
//Make certain that the connection is closed before returning.
- _connectionobject.Close();
+ _oleDbConnection.Close();
}
return insertWasSuccessful;
@@ -257,7 +560,7 @@ namespace AdvertsingProfitControl
var noRowsAdded = new List {0};
return noRowsAdded;
}
- _connectionobject.Open();
+ _oleDbConnection.Open();
var rowsAdded = new List();
var rowNumber = 0;
//DataTable's structure will reflect the APC database table structure.
@@ -309,7 +612,7 @@ namespace AdvertsingProfitControl
oleDbCommand.Parameters.AddWithValue("AdItemID", adItemId);
oleDbCommand.Parameters.AddWithValue("GroupID", row[19]);
oleDbCommand.Parameters.AddWithValue("dateID", row[20]);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
try
{
@@ -328,7 +631,7 @@ namespace AdvertsingProfitControl
{
_logConsole.WriteToLog(FrmLogConsole.Level.Error, "An error occurred trying to write a record to the APC table.");
_logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message);
- _connectionobject.Close();
+ _oleDbConnection.Close();
//Add an error code at the end of array of rows that were added to show an error occurred.
rowsAdded.Add(-1);
return rowsAdded;
@@ -343,7 +646,7 @@ namespace AdvertsingProfitControl
rowsAdded.Add(0);
_logConsole.WriteToLog(FrmLogConsole.Level.Error, "An error occurred trying to update a record APC table.");
_logConsole.WriteToLog(FrmLogConsole.Level.Debug, "An error occurred trying to update ad item ID " + adItemId + " and dateID " + dateId + ".");
- _connectionobject.Close();
+ _oleDbConnection.Close();
return rowsAdded;
}
}
@@ -351,7 +654,7 @@ namespace AdvertsingProfitControl
}
//Close the database connection before returning.
- _connectionobject.Close();
+ _oleDbConnection.Close();
return rowsAdded;
}
@@ -370,15 +673,16 @@ namespace AdvertsingProfitControl
oleDbCommand.CommandText = "SELECT ID FROM APC WHERE FK_AdItemID = adItemID AND FK_DateID = dateID";
oleDbCommand.Parameters.AddWithValue("adItemID", adItemId);
oleDbCommand.Parameters.AddWithValue("dateID", dateId);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
try
{
+ oleDbCommand.Transaction = _oleDbConnection.BeginTransaction();
var reader = oleDbCommand.ExecuteReader();
while (reader != null && reader.Read())
{
rowsEffected++;
}
- if (reader != null) reader.Close();
+ reader?.Close();
}
catch (OleDbException ex)
{
@@ -424,10 +728,12 @@ namespace AdvertsingProfitControl
}
//Record the number of rows affected when the statement is executed, again assume nothing was affected.
var adItemId = "0";
- var oleDbCommand = new OleDbCommand();
- oleDbCommand.CommandText = "INSERT INTO AdItem (AdItem) VALUES (?)";
+ var oleDbCommand = new OleDbCommand
+ {
+ CommandText = "INSERT INTO AdItem (AdItem) VALUES (?)",
+ Connection = _oleDbConnection
+ };
oleDbCommand.Parameters.AddWithValue("adItem", adItemName);
- oleDbCommand.Connection = _connectionobject;
//Attempt to execute the INSERT SQL statement.
try
{
@@ -443,7 +749,7 @@ namespace AdvertsingProfitControl
{
adItemId = reader[0].ToString();
}
- if (reader != null) reader.Close();
+ reader?.Close();
}
//ELSE IF more then one (1) row was affected...
else if (rowsEffected > 1)
@@ -487,7 +793,7 @@ namespace AdvertsingProfitControl
}
var oleDbCommand = new OleDbCommand {CommandText = "SELECT ID FROM AdItem WHERE UCASE(AdItem.AdItem) = UCASE(adItemName)"};
oleDbCommand.Parameters.AddWithValue("adItemName", adItemName);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
try
{
@@ -557,7 +863,7 @@ namespace AdvertsingProfitControl
oleDbCommand.Parameters.AddWithValue("groupID", parameters[19]);
oleDbCommand.Parameters.AddWithValue("dateID", parameters[20]);
oleDbCommand.Parameters.AddWithValue("adItemID", adItemId);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
try
{
@@ -597,22 +903,22 @@ namespace AdvertsingProfitControl
var supplierQueryCommand = new OleDbCommand
{
CommandText = "SELECT ID FROM Supplier WHERE SupplierName = ?",
- Connection = _connectionobject
+ Connection = _oleDbConnection
};
//Grabbing the ID of the invoice by the invoice number and the supplier's ID.
var invoiceCheckCommand = new OleDbCommand
{
CommandText = "SELECT ID FROM Invoice WHERE InvoiceNumber = ? AND FK_Supplier = ?",
- Connection = _connectionobject
+ Connection = _oleDbConnection
};
//Inserting a new record into the Invoice table.
var insertNewInvoice = new OleDbCommand
{
CommandText =
"INSERT INTO Invoice (InvoiceDate, InvoiceNumber, InvoiceNetAmountAtCost, InvoiceNetAmount, InvoiceNote, FK_Supplier, FK_DateID) VALUES (?, ?, ?, ?, ?, ?, ?)",
- Connection = _connectionobject
+ Connection = _oleDbConnection
};
- _connectionobject.Open();
+ _oleDbConnection.Open();
foreach (DataRow row in parameters.Rows)
{
var itemCount = 0;
@@ -736,12 +1042,12 @@ namespace AdvertsingProfitControl
{
_logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to write supplier " + row[1] + " into the invoice table.");
_logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message);
- _connectionobject.Close();
+ _oleDbConnection.Close();
break;
}
}
- _connectionobject.Close();
+ _oleDbConnection.Close();
return rowsAdded;
}
///
@@ -767,7 +1073,7 @@ namespace AdvertsingProfitControl
var supplierNameId = "0";
var oleDbCommand = new OleDbCommand {CommandText = "INSERT INTO Supplier (SupplierName) VALUES (?)"};
oleDbCommand.Parameters.AddWithValue("SupplierName", supplierName);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
try
{
@@ -825,7 +1131,7 @@ namespace AdvertsingProfitControl
oleDbCommand.Parameters.AddWithValue("InvoiceNumber", invoiceField[2]);
oleDbCommand.Parameters.AddWithValue("SupplierID", supplierId);
oleDbCommand.Parameters.AddWithValue("DateID", invoiceField[6]);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
try
{
@@ -863,7 +1169,7 @@ namespace AdvertsingProfitControl
CommandText = "SELECT ID FROM WeeklySales WHERE FK_DateID = ?"
};
weekEndingDateCheck.Parameters.AddWithValue("DateID", parameters[8]);
- weekEndingDateCheck.Connection = _connectionobject;
+ weekEndingDateCheck.Connection = _oleDbConnection;
//Object to update a field with the date supplied, assuming an entry was found with the previous object.
var updateWeeklySales = new OleDbCommand
{
@@ -879,7 +1185,7 @@ namespace AdvertsingProfitControl
updateWeeklySales.Parameters.AddWithValue("Saturday", parameters[6]);
updateWeeklySales.Parameters.AddWithValue("TotalSales", parameters[7]);
updateWeeklySales.Parameters.AddWithValue("DateID", parameters[8]);
- updateWeeklySales.Connection = _connectionobject;
+ updateWeeklySales.Connection = _oleDbConnection;
//Object to insert a new field into the database if no entry is present.
var insertWeeklySales = new OleDbCommand
{
@@ -895,10 +1201,10 @@ namespace AdvertsingProfitControl
insertWeeklySales.Parameters.AddWithValue("Saturday", parameters[6]);
insertWeeklySales.Parameters.AddWithValue("TotalSales", parameters[7]);
insertWeeklySales.Parameters.AddWithValue("DateID", parameters[8]);
- insertWeeklySales.Connection = _connectionobject;
+ insertWeeklySales.Connection = _oleDbConnection;
try
{
- _connectionobject.Open();
+ _oleDbConnection.Open();
//Execute the select statement to check for the presence of an entry with the supplied date (parameters[8]).
var reader = weekEndingDateCheck.ExecuteReader();
@@ -931,7 +1237,7 @@ namespace AdvertsingProfitControl
}
finally
{
- _connectionobject.Close();
+ _oleDbConnection.Close();
}
return rowsEffected;
@@ -947,18 +1253,18 @@ namespace AdvertsingProfitControl
CommandText = "SELECT ID FROM GroupCategory WHERE GroupDescription = ?"
};
categoryDescCheckQueryCommand.Parameters.AddWithValue("GroupName", groupName);
- categoryDescCheckQueryCommand.Connection = _connectionobject;
+ categoryDescCheckQueryCommand.Connection = _oleDbConnection;
//Setting up an object to insert a new ad special keyword.
var insertNewCategoryDesc = new OleDbCommand
{
CommandText = "INSERT INTO GroupCategory (GroupDescription) VALUES (?)"
};
insertNewCategoryDesc.Parameters.AddWithValue("GroupName", groupName);
- insertNewCategoryDesc.Connection = _connectionobject;
+ insertNewCategoryDesc.Connection = _oleDbConnection;
try
{
- _connectionobject.Open();
+ _oleDbConnection.Open();
var reader = categoryDescCheckQueryCommand.ExecuteReader();
while (reader != null && reader.Read())
@@ -985,7 +1291,7 @@ namespace AdvertsingProfitControl
}
finally
{
- _connectionobject.Close();
+ _oleDbConnection.Close();
}
return rowsEffected;
@@ -999,11 +1305,11 @@ namespace AdvertsingProfitControl
CommandText = "DELETE FROM GroupCategory WHERE GroupDescription = ?"
};
oleDbCommand.Parameters.AddWithValue("AdSpecialName", adSpecialName);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
try
{
- _connectionobject.Open();
+ _oleDbConnection.Open();
rowsEffected = oleDbCommand.ExecuteNonQuery();
}
catch (OleDbException e)
@@ -1014,7 +1320,7 @@ namespace AdvertsingProfitControl
}
finally
{
- _connectionobject.Close();
+ _oleDbConnection.Close();
}
return rowsEffected;
@@ -1029,11 +1335,11 @@ namespace AdvertsingProfitControl
};
deleteCommand.Parameters.AddWithValue("AdItemID", adItemId);
deleteCommand.Parameters.AddWithValue("DateID", dateId);
- deleteCommand.Connection = _connectionobject;
+ deleteCommand.Connection = _oleDbConnection;
try
{
- _connectionobject.Open();
+ _oleDbConnection.Open();
recordsDeleted = deleteCommand.ExecuteNonQuery();
}
catch (OleDbException e)
@@ -1043,7 +1349,7 @@ namespace AdvertsingProfitControl
}
finally
{
- _connectionobject.Close();
+ _oleDbConnection.Close();
}
return recordsDeleted;
@@ -1058,11 +1364,11 @@ namespace AdvertsingProfitControl
};
oleDbCommand.Parameters.AddWithValue("InvoiceNumber", invoiceNumber);
oleDbCommand.Parameters.AddWithValue("DateID", dateId);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
try
{
- _connectionobject.Open();
+ _oleDbConnection.Open();
recordsAffected = oleDbCommand.ExecuteNonQuery();
}
catch (OleDbException e)
@@ -1072,7 +1378,7 @@ namespace AdvertsingProfitControl
}
finally
{
- _connectionobject.Close();
+ _oleDbConnection.Close();
}
return recordsAffected;
@@ -1093,39 +1399,39 @@ namespace AdvertsingProfitControl
CommandText = "DELETE FROM APC WHERE FK_DateID = ?"
};
clearApCommand.Parameters.AddWithValue("DateID", dateId);
- clearApCommand.Connection = _connectionobject;
+ clearApCommand.Connection = _oleDbConnection;
//Object to clear comments associated with the date ID.
var clearCommentsCommand = new OleDbCommand()
{
CommandText = "DELETE FROM Comment WHERE FK_DateID = ?"
};
clearCommentsCommand.Parameters.AddWithValue("DateID", dateId);
- clearCommentsCommand.Connection = _connectionobject;
+ clearCommentsCommand.Connection = _oleDbConnection;
//Object to clear the invoices associated with the date ID.
var clearInvoicesCommand = new OleDbCommand()
{
CommandText = "DELETE FROM Invoice WHERE FK_DateID = ?"
};
clearInvoicesCommand.Parameters.AddWithValue("DateID", dateId);
- clearInvoicesCommand.Connection = _connectionobject;
+ clearInvoicesCommand.Connection = _oleDbConnection;
//Object to clear the weekly sales associated with the date ID.
var clearWeeklySalesCommand = new OleDbCommand()
{
CommandText = "DELETE FROM WeeklySales WHERE FK_DateID = ?"
};
clearWeeklySalesCommand.Parameters.AddWithValue("DateID", dateId);
- clearWeeklySalesCommand.Connection = _connectionobject;
+ clearWeeklySalesCommand.Connection = _oleDbConnection;
//Object to clear the date associated with the ID passed in.
var clearEndOfWeekDateCommand = new OleDbCommand()
{
CommandText = "DELETE FROM WeekEnding WHERE ID = ?"
};
clearEndOfWeekDateCommand.Parameters.AddWithValue("DateID", dateId);
- clearEndOfWeekDateCommand.Connection = _connectionobject;
+ clearEndOfWeekDateCommand.Connection = _oleDbConnection;
try
{
- _connectionobject.Open();
+ _oleDbConnection.Open();
recordsRemoved += clearApCommand.ExecuteNonQuery();
recordsRemoved += clearCommentsCommand.ExecuteNonQuery();
recordsRemoved += clearInvoicesCommand.ExecuteNonQuery();
@@ -1139,7 +1445,7 @@ namespace AdvertsingProfitControl
}
finally
{
- _connectionobject.Close();
+ _oleDbConnection.Close();
}
return recordsRemoved;
}
@@ -1161,12 +1467,12 @@ namespace AdvertsingProfitControl
};
oleDbCommand.Parameters.AddWithValue("Comment", comment);
oleDbCommand.Parameters.AddWithValue("DateID", dateId);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
try
{
//IF the delete command deletes more then one row it returns 0.
- _connectionobject.Open();
+ _oleDbConnection.Open();
var recordsEffected = oleDbCommand.ExecuteNonQuery();
if (recordsEffected == 1)
{
@@ -1180,7 +1486,7 @@ namespace AdvertsingProfitControl
}
finally
{
- _connectionobject.Close();
+ _oleDbConnection.Close();
}
return wasSuccessful;
@@ -1194,11 +1500,11 @@ namespace AdvertsingProfitControl
CommandText = "DELETE FROM AdItem WHERE AdItem = ?"
};
oleDbCommand.Parameters.AddWithValue("AdItemName", adItemName);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
try
{
- _connectionobject.Open();
+ _oleDbConnection.Open();
var rowsEffected = oleDbCommand.ExecuteNonQuery();
if(rowsEffected == 1)
@@ -1222,7 +1528,7 @@ namespace AdvertsingProfitControl
}
finally
{
- _connectionobject.Close();
+ _oleDbConnection.Close();
}
return success;
@@ -1236,17 +1542,17 @@ namespace AdvertsingProfitControl
CommandText = "INSERT INTO AdItem (AdItem) VALUES (?)"
};
oleDbCommand.Parameters.AddWithValue("AdItemName", adItemName);
- oleDbCommand.Connection = _connectionobject;
+ oleDbCommand.Connection = _oleDbConnection;
var redundantancyCheck = new OleDbCommand
{
CommandText = "SELECT AdItem FROM AdItem WHERE AdItem = ?"
};
redundantancyCheck.Parameters.AddWithValue("AdItemName", adItemName);
- redundantancyCheck.Connection = _connectionobject;
+ redundantancyCheck.Connection = _oleDbConnection;
try
{
- _connectionobject.Open();
+ _oleDbConnection.Open();
using(var reader = redundantancyCheck.ExecuteReader())
{
var rows = 0;
@@ -1280,7 +1586,7 @@ namespace AdvertsingProfitControl
}
finally
{
- _connectionobject.Close();
+ _oleDbConnection.Close();
}
return success;
diff --git a/AdvertsingProfitControl/FrmAdSpecialRegister.cs b/AdvertsingProfitControl/FrmAdSpecialRegister.cs
index 2a4785a..3d08532 100644
--- a/AdvertsingProfitControl/FrmAdSpecialRegister.cs
+++ b/AdvertsingProfitControl/FrmAdSpecialRegister.cs
@@ -47,7 +47,7 @@ namespace AdvertsingProfitControl
if (rowsEffected == 1)
{
- RowParsing._adSpecialGroups.Add(enterNewKeyWordTextBox.Text);
+ RowParsing.AdSpecialGroups.Add(enterNewKeyWordTextBox.Text);
var groupNameCollection = databaseReader.ReturnGroupNameList(databaseTracker.DatabaseConnectionString);
adSpecialKeyWordsListBox.Items.Clear();
foreach (var groupName in groupNameCollection)
diff --git a/AdvertsingProfitControl/FrmAddRecord.cs b/AdvertsingProfitControl/FrmAddRecord.cs
index 189c2fc..b5f1afc 100644
--- a/AdvertsingProfitControl/FrmAddRecord.cs
+++ b/AdvertsingProfitControl/FrmAddRecord.cs
@@ -53,7 +53,7 @@ namespace AdvertsingProfitControl
_AdSpecialList = databaseReader.RetrieveAdSpecialList(databaseTracker.DatabaseConnectionString);
//Event handlers for the Projections DataGridView
projectionsDataGridView.CellValidating += OnCellValidating;
- projectionsDataGridView.RowEnter += DetectAndDisplayIncompleteRows;
+ //projectionsDataGridView.RowEnter += DetectAndDisplayIncompleteRows;
projectionsDataGridView.RowLeave += OnRowLeave;
projectionsDataGridView.RowsAdded += DisplayRowNumbers;
projectionsDataGridView.RowsRemoved += OnRowRemoved;
@@ -62,14 +62,14 @@ namespace AdvertsingProfitControl
projectionsDataGridView.RowValidating += UpdateInventoryActualSalesDataGridView;
//Event handlers for the Inventory / Actual Sales DataGridView
- actualSalesDataGridView.CellValidating += OnCellValidating;
+ actualSalesDataGridView.CellValidating += OnCellValidating; //
actualSalesDataGridView.RowEnter += DetectAndDisplayIncompleteRows;
- actualSalesDataGridView.RowLeave += OnRowLeave;
- actualSalesDataGridView.RowsAdded += DisplayRowNumbers;
- actualSalesDataGridView.RowsRemoved += OnRowRemoved;
- actualSalesDataGridView.UserDeletingRow += OnRowRemoving;
- actualSalesDataGridView.EditingControlShowing += DisplayAutoCompleteOnEditingControlShowing;
- actualSalesDataGridView.RowValidating += UpdateProjectionsDataGridView;
+ actualSalesDataGridView.RowLeave += OnRowLeave; //
+ actualSalesDataGridView.RowsAdded += DisplayRowNumbers;//
+ actualSalesDataGridView.RowsRemoved += OnRowRemoved;//
+ actualSalesDataGridView.UserDeletingRow += OnRowRemoving; //
+ actualSalesDataGridView.EditingControlShowing += DisplayAutoCompleteOnEditingControlShowing; //
+ actualSalesDataGridView.RowValidating += UpdateProjectionsDataGridView;//
//Event handlers for the Suppliers DataGridView
suppliersDataGridView.CellValidating += SupplierOnCellValidating;
@@ -726,7 +726,7 @@ namespace AdvertsingProfitControl
if (actualSalesDataGridView.Rows[e.RowIndex].Cells[0].EditedFormattedValue.ToString() != "")
{
var parser = new RowParsing();
- var rowContents = new string[11];
+ object[] rowContents = new object[11];
//Check to make sure the user didn't simply leave a row that already exists.
if (projectionsDataGridView.Rows[e.RowIndex].Cells[0].EditedFormattedValue.ToString() == actualSalesDataGridView.Rows[e.RowIndex].Cells[0].EditedFormattedValue.ToString())
{
diff --git a/AdvertsingProfitControl/FrmLogConsole.cs b/AdvertsingProfitControl/FrmLogConsole.cs
index d8738d5..b64acae 100644
--- a/AdvertsingProfitControl/FrmLogConsole.cs
+++ b/AdvertsingProfitControl/FrmLogConsole.cs
@@ -7,8 +7,7 @@ namespace AdvertsingProfitControl
public sealed partial class FrmLogConsole : Form
{
//Source code: https://hashfactor.wordpress.com/2009/03/31/c-winforms-create-a-single-instance-form/
- private static readonly FrmLogConsole gLogConsoleInstance = new FrmLogConsole();
- private static bool gIsShown = false;
+ private static bool _gIsShown;
public FrmLogConsole()
{
@@ -18,16 +17,18 @@ namespace AdvertsingProfitControl
logListView.View = View.Details;
//Information for drawing header columns and sub-items in ListView:
//http://stackoverflow.com/questions/561798/how-do-i-align-text-for-a-single-subitem-in-a-listview-using-c
- ColumnHeader header = new ColumnHeader();
- header.Text = "Advertising Profit Control " + Application.ProductVersion + " Debug Console";
- header.Name = "LogConsoleHeader";
- header.Width = logListView.Width;
+ var header = new ColumnHeader
+ {
+ Text = @"Advertising Profit Control " + Application.ProductVersion + @" Debug Console",
+ Name = "LogConsoleHeader",
+ Width = logListView.Width
+ };
logListView.Columns.Add(header);
}
static FrmLogConsole()
{
- GetStaticInstance.FormClosing += new FormClosingEventHandler(LogConsole_FormClosing);
+ GetStaticInstance.FormClosing += LogConsole_FormClosing;
//Set the maximum and minimum size of the form.
GetStaticInstance.MaximumSize = new Size(900, 900);
GetStaticInstance.MinimumSize = new Size(400, 400);
@@ -35,27 +36,25 @@ namespace AdvertsingProfitControl
public new void Show()
{
- if (gIsShown)
+ if (_gIsShown)
{
base.Show();
}
else
{
base.Show();
- gIsShown = true;
+ _gIsShown = true;
}
}
public new void Hide()
{
- if (gIsShown)
- {
- base.Hide();
- gIsShown = false;
- }
+ if (!_gIsShown) return;
+ base.Hide();
+ _gIsShown = false;
}
- public enum Level : int
+ public enum Level
{
Critical = 0,
Error = 1,
@@ -68,7 +67,6 @@ namespace AdvertsingProfitControl
public void WriteToLog(Level level, string message)
{
Color color;
- int index;
switch (level)
{
@@ -87,14 +85,17 @@ namespace AdvertsingProfitControl
case Level.Verbose:
color = Color.Blue;
break;
+ case Level.Debug:
+ color = Color.Black;
+ break;
default:
color = Color.Black;
break;
}
- index = logListView.Items.Count;
+ var index = logListView.Items.Count;
try
{
- message = String.Format("{0}: {1}", level, message);
+ message = $"{level}: {message}";
if (level != Level.Info)
{
GlobalClasses.WriteToLog(DateTime.Now + ": " + message + Environment.NewLine);
@@ -107,13 +108,17 @@ namespace AdvertsingProfitControl
MessageBox.Show(e.Message);
}
- if (level == Level.Critical)
+ switch (level)
{
- logListView.Items[index].BackColor = Color.Red;
- }
- else
- {
- logListView.Items[index].BackColor = Color.WhiteSmoke;
+ case Level.Critical:
+ logListView.Items[index].BackColor = Color.Red;
+ break;
+ case Level.Error:
+ logListView.Items[index].ForeColor = Color.Maroon;
+ break;
+ default:
+ logListView.Items[index].BackColor = Color.WhiteSmoke;
+ break;
}
}
@@ -121,17 +126,11 @@ namespace AdvertsingProfitControl
{
e.Cancel = true;
GetStaticInstance.Hide();
- gIsShown = false;
+ _gIsShown = false;
}
- public static FrmLogConsole GetStaticInstance
- {
- get { return gLogConsoleInstance; }
- }
+ public static FrmLogConsole GetStaticInstance { get; } = new FrmLogConsole();
- public bool IsVisable
- {
- get { return gIsShown; }
- }
+ public bool IsVisable => _gIsShown;
}
}
diff --git a/AdvertsingProfitControl/FrmMain.Designer.cs b/AdvertsingProfitControl/FrmMain.Designer.cs
index 7c2e4d6..3cd44d8 100644
--- a/AdvertsingProfitControl/FrmMain.Designer.cs
+++ b/AdvertsingProfitControl/FrmMain.Designer.cs
@@ -48,7 +48,7 @@
this.commentMainGroupBox = new System.Windows.Forms.GroupBox();
this.commentsTextBox = new System.Windows.Forms.TextBox();
this.profitAnalysisMainGroupBox = new System.Windows.Forms.GroupBox();
- this.shrinkLabel = new System.Windows.Forms.Label();
+ this.shrinkLinkLabel = new System.Windows.Forms.LinkLabel();
this.totalProfitReturnLabel = new System.Windows.Forms.Label();
this.totalProfitReturnFromRemaingLabel = new System.Windows.Forms.Label();
this.totalProfitFromAdItemsLabel = new System.Windows.Forms.Label();
@@ -286,7 +286,7 @@
//
// profitAnalysisMainGroupBox
//
- this.profitAnalysisMainGroupBox.Controls.Add(this.shrinkLabel);
+ this.profitAnalysisMainGroupBox.Controls.Add(this.shrinkLinkLabel);
this.profitAnalysisMainGroupBox.Controls.Add(this.totalProfitReturnLabel);
this.profitAnalysisMainGroupBox.Controls.Add(this.totalProfitReturnFromRemaingLabel);
this.profitAnalysisMainGroupBox.Controls.Add(this.totalProfitFromAdItemsLabel);
@@ -304,15 +304,19 @@
this.profitAnalysisMainGroupBox.TabStop = false;
this.profitAnalysisMainGroupBox.Text = "Profit Analysis";
//
- // shrinkLabel
+ // shrinkLinkLabel
//
- this.shrinkLabel.AutoSize = true;
- this.shrinkLabel.Location = new System.Drawing.Point(0, 36);
- this.shrinkLabel.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0);
- this.shrinkLabel.Name = "shrinkLabel";
- this.shrinkLabel.Size = new System.Drawing.Size(205, 25);
- this.shrinkLabel.TabIndex = 6;
- this.shrinkLabel.Text = "Assuming 30% Shrink";
+ this.shrinkLinkLabel.AutoSize = true;
+ this.shrinkLinkLabel.LinkArea = new System.Windows.Forms.LinkArea(20, 6);
+ this.shrinkLinkLabel.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
+ this.shrinkLinkLabel.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
+ this.shrinkLinkLabel.Location = new System.Drawing.Point(0, 37);
+ this.shrinkLinkLabel.Name = "shrinkLinkLabel";
+ this.shrinkLinkLabel.Size = new System.Drawing.Size(272, 27);
+ this.shrinkLinkLabel.TabIndex = 6;
+ this.shrinkLinkLabel.TabStop = true;
+ this.shrinkLinkLabel.Text = "Assuming 30% Shrink Change";
+ this.shrinkLinkLabel.UseCompatibleTextRendering = true;
//
// totalProfitReturnLabel
//
@@ -699,7 +703,7 @@
//
// FrmMain
//
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.ClientSize = new System.Drawing.Size(1734, 892);
this.Controls.Add(this.mainTableLayoutPanel);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
@@ -768,7 +772,6 @@
private System.Windows.Forms.Label departmentSalesLabel;
private System.Windows.Forms.TabPage WeeklySalesTabPage;
private System.Windows.Forms.DataGridView weeklySalesDataGridView;
- private System.Windows.Forms.Label shrinkLabel;
private System.Windows.Forms.ToolStripMenuItem helpMainMenu;
private System.Windows.Forms.ToolStripMenuItem showHideConsoleHelpMainMenu;
private System.Windows.Forms.GroupBox taxableGroupBox;
@@ -794,6 +797,7 @@
private System.Windows.Forms.Button printPreviewButton;
private System.Windows.Forms.CheckBox usePreRenderedFilesCheckbox;
private System.Windows.Forms.ToolStripMenuItem newFormTestToolStripMenuItem;
+ private System.Windows.Forms.LinkLabel shrinkLinkLabel;
}
}
diff --git a/AdvertsingProfitControl/FrmMain.cs b/AdvertsingProfitControl/FrmMain.cs
index 3b0d281..54d1727 100644
--- a/AdvertsingProfitControl/FrmMain.cs
+++ b/AdvertsingProfitControl/FrmMain.cs
@@ -45,7 +45,7 @@ namespace AdvertsingProfitControl
MessageBox.Show("The database has been successfully upgraded to version " + versionNumber + ".\nA back up of the old database has been made called APCDatabase.bak in the same location as the current database.", "Half Baked Code For The Win");
}
}
- RowParsing._adSpecialGroups.AddRange(databaseReader.ReturnGroupNameList(databaseTracker.DatabaseConnectionString));
+ RowParsing.AdSpecialGroups.AddRange(databaseReader.ReturnGroupNameList(databaseTracker.DatabaseConnectionString));
FillDateSuggestionComboBoxes();
BuildAndFillDataGridTables();
CalculateProfitAnalysis();
diff --git a/AdvertsingProfitControl/NewAddRecord.Designer.cs b/AdvertsingProfitControl/NewAddRecord.Designer.cs
index 4a2528c..da0ff3f 100644
--- a/AdvertsingProfitControl/NewAddRecord.Designer.cs
+++ b/AdvertsingProfitControl/NewAddRecord.Designer.cs
@@ -37,13 +37,15 @@
this.inventoryTabPage = new System.Windows.Forms.TabPage();
this.inventoryDataGridView = new System.Windows.Forms.DataGridView();
this.actualSalesTabPage = new System.Windows.Forms.TabPage();
- this.actualDataGridView = new System.Windows.Forms.DataGridView();
+ this.actualSalesDataGridView = new System.Windows.Forms.DataGridView();
this.invoicesTabPage = new System.Windows.Forms.TabPage();
this.invoicesDataGridView = new System.Windows.Forms.DataGridView();
- this.tabPage1 = new System.Windows.Forms.TabPage();
+ this.debugTabPage = new System.Windows.Forms.TabPage();
this.mainMenuStrip = new System.Windows.Forms.MenuStrip();
this.FileMainMenu = new System.Windows.Forms.ToolStripMenuItem();
this.exitFileMainMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.debugMainMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.getCellValueDebugMainMenu = new System.Windows.Forms.ToolStripMenuItem();
this.mainLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.costAnalysisGroupBox = new System.Windows.Forms.GroupBox();
this.suppliesTextBox = new System.Windows.Forms.TextBox();
@@ -106,7 +108,7 @@
this.inventoryTabPage.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.inventoryDataGridView)).BeginInit();
this.actualSalesTabPage.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.actualDataGridView)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.actualSalesDataGridView)).BeginInit();
this.invoicesTabPage.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.invoicesDataGridView)).BeginInit();
this.mainMenuStrip.SuspendLayout();
@@ -150,7 +152,7 @@
this.mainTabControl.Controls.Add(this.inventoryTabPage);
this.mainTabControl.Controls.Add(this.actualSalesTabPage);
this.mainTabControl.Controls.Add(this.invoicesTabPage);
- this.mainTabControl.Controls.Add(this.tabPage1);
+ this.mainTabControl.Controls.Add(this.debugTabPage);
this.mainTabControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.mainTabControl.Location = new System.Drawing.Point(4, 39);
this.mainTabControl.Margin = new System.Windows.Forms.Padding(4);
@@ -216,7 +218,7 @@
//
// actualSalesTabPage
//
- this.actualSalesTabPage.Controls.Add(this.actualDataGridView);
+ this.actualSalesTabPage.Controls.Add(this.actualSalesDataGridView);
this.actualSalesTabPage.Location = new System.Drawing.Point(4, 33);
this.actualSalesTabPage.Margin = new System.Windows.Forms.Padding(4);
this.actualSalesTabPage.Name = "actualSalesTabPage";
@@ -225,21 +227,21 @@
this.actualSalesTabPage.Text = "Actual Sales";
this.actualSalesTabPage.UseVisualStyleBackColor = true;
//
- // actualDataGridView
+ // actualSalesDataGridView
//
- this.actualDataGridView.AllowDrop = true;
- this.actualDataGridView.AllowUserToResizeRows = false;
- this.actualDataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
- this.actualDataGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells;
- this.actualDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
- this.actualDataGridView.Dock = System.Windows.Forms.DockStyle.Fill;
- this.actualDataGridView.Location = new System.Drawing.Point(0, 0);
- this.actualDataGridView.Margin = new System.Windows.Forms.Padding(4);
- this.actualDataGridView.MultiSelect = false;
- this.actualDataGridView.Name = "actualDataGridView";
- this.actualDataGridView.RowTemplate.Height = 28;
- this.actualDataGridView.Size = new System.Drawing.Size(1660, 510);
- this.actualDataGridView.TabIndex = 1;
+ this.actualSalesDataGridView.AllowDrop = true;
+ this.actualSalesDataGridView.AllowUserToResizeRows = false;
+ this.actualSalesDataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
+ this.actualSalesDataGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells;
+ this.actualSalesDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ this.actualSalesDataGridView.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.actualSalesDataGridView.Location = new System.Drawing.Point(0, 0);
+ this.actualSalesDataGridView.Margin = new System.Windows.Forms.Padding(4);
+ this.actualSalesDataGridView.MultiSelect = false;
+ this.actualSalesDataGridView.Name = "actualSalesDataGridView";
+ this.actualSalesDataGridView.RowTemplate.Height = 28;
+ this.actualSalesDataGridView.Size = new System.Drawing.Size(1660, 510);
+ this.actualSalesDataGridView.TabIndex = 1;
//
// invoicesTabPage
//
@@ -268,22 +270,23 @@
this.invoicesDataGridView.Size = new System.Drawing.Size(1660, 510);
this.invoicesDataGridView.TabIndex = 1;
//
- // tabPage1
+ // debugTabPage
//
- this.tabPage1.Location = new System.Drawing.Point(4, 33);
- this.tabPage1.Name = "tabPage1";
- this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
- this.tabPage1.Size = new System.Drawing.Size(1660, 510);
- this.tabPage1.TabIndex = 4;
- this.tabPage1.Text = "tabPage1";
- this.tabPage1.UseVisualStyleBackColor = true;
+ this.debugTabPage.Location = new System.Drawing.Point(4, 33);
+ this.debugTabPage.Name = "debugTabPage";
+ this.debugTabPage.Padding = new System.Windows.Forms.Padding(3);
+ this.debugTabPage.Size = new System.Drawing.Size(1660, 510);
+ this.debugTabPage.TabIndex = 4;
+ this.debugTabPage.Text = "DEBUG";
+ this.debugTabPage.UseVisualStyleBackColor = true;
//
// mainMenuStrip
//
this.mainLayoutPanel.SetColumnSpan(this.mainMenuStrip, 4);
this.mainMenuStrip.ImageScalingSize = new System.Drawing.Size(24, 24);
this.mainMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.FileMainMenu});
+ this.FileMainMenu,
+ this.debugMainMenu});
this.mainMenuStrip.Location = new System.Drawing.Point(0, 0);
this.mainMenuStrip.Name = "mainMenuStrip";
this.mainMenuStrip.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2);
@@ -305,6 +308,21 @@
this.exitFileMainMenu.Size = new System.Drawing.Size(138, 34);
this.exitFileMainMenu.Text = "E&xit";
//
+ // debugMainMenu
+ //
+ this.debugMainMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.getCellValueDebugMainMenu});
+ this.debugMainMenu.Name = "debugMainMenu";
+ this.debugMainMenu.Size = new System.Drawing.Size(87, 31);
+ this.debugMainMenu.Text = "Debug";
+ //
+ // getCellValueDebugMainMenu
+ //
+ this.getCellValueDebugMainMenu.Name = "getCellValueDebugMainMenu";
+ this.getCellValueDebugMainMenu.Size = new System.Drawing.Size(233, 34);
+ this.getCellValueDebugMainMenu.Text = "Get Cell Value";
+ this.getCellValueDebugMainMenu.Click += new System.EventHandler(this.getCellValueDebugMainMenu_Click);
+ //
// mainLayoutPanel
//
this.mainLayoutPanel.ColumnCount = 4;
@@ -841,6 +859,7 @@
this.addRecordButton.TabIndex = 26;
this.addRecordButton.Text = "Add Record";
this.addRecordButton.UseVisualStyleBackColor = true;
+ this.addRecordButton.Click += new System.EventHandler(this.AddRecordsButtonClick);
//
// NewAddRecord
//
@@ -865,7 +884,7 @@
this.inventoryTabPage.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.inventoryDataGridView)).EndInit();
this.actualSalesTabPage.ResumeLayout(false);
- ((System.ComponentModel.ISupportInitialize)(this.actualDataGridView)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.actualSalesDataGridView)).EndInit();
this.invoicesTabPage.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.invoicesDataGridView)).EndInit();
this.mainMenuStrip.ResumeLayout(false);
@@ -901,7 +920,7 @@
private System.Windows.Forms.TabPage inventoryTabPage;
private System.Windows.Forms.DataGridView inventoryDataGridView;
private System.Windows.Forms.TabPage actualSalesTabPage;
- private System.Windows.Forms.DataGridView actualDataGridView;
+ private System.Windows.Forms.DataGridView actualSalesDataGridView;
private System.Windows.Forms.TabPage invoicesTabPage;
private System.Windows.Forms.DataGridView invoicesDataGridView;
private System.Windows.Forms.TextBox suppliesTextBox;
@@ -957,9 +976,11 @@
private System.Windows.Forms.Panel dateTimeMaskedTextBoxPanel;
private System.Windows.Forms.MaskedTextBox weekEndingMaskedTextBox;
private System.Windows.Forms.Label weekEndingMaskedTextBoxInstructionLabel;
- private System.Windows.Forms.TabPage tabPage1;
+ private System.Windows.Forms.TabPage debugTabPage;
private System.Windows.Forms.Panel informationPanel;
private System.Windows.Forms.Label errorLabel;
private System.Windows.Forms.Label informationLabel;
+ private System.Windows.Forms.ToolStripMenuItem debugMainMenu;
+ private System.Windows.Forms.ToolStripMenuItem getCellValueDebugMainMenu;
}
}
\ No newline at end of file
diff --git a/AdvertsingProfitControl/NewAddRecord.cs b/AdvertsingProfitControl/NewAddRecord.cs
index c952186..11a98fe 100644
--- a/AdvertsingProfitControl/NewAddRecord.cs
+++ b/AdvertsingProfitControl/NewAddRecord.cs
@@ -5,10 +5,7 @@ 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
@@ -16,36 +13,112 @@ namespace AdvertsingProfitControl
public partial class NewAddRecord : Form
{
private static readonly FrmLogConsole LogConsole = FrmLogConsole.GetStaticInstance;
+ //Create an array that contains all the ad items from the database.
+ //private read only Dictionary _adItemCollectionDictionary;
+ private readonly List _adItemCollection;
+ //This object contains all the unused ad items.
+ private AutoCompleteStringCollection _trimmedAdItemCollection = new AutoCompleteStringCollection();
+ //Contains all the ad specials that are in the database (i.e. "Daily Coupons").
+ private readonly AutoCompleteStringCollection _adSpecialList;
+ //This object contains all the suppliers that were found in the database.
+ private AutoCompleteStringCollection _supplierCollection;
+ //This array keeps track of the number of times an Ad Item is used, if used once then it may only be used AFTER an AdSpecialRow and only once after that.
+ //Once an item has been used twice, it will not appear again in the AutoCompleteSuggestions.
+ //Structure: "SECTIONUSED":"ADITEMID" Section used means what side of the AdSpecialRow, one (1) being before and two (2) being after.
+ //The structure of the used ad item list is as follows:
+ //List(0) is section one and List(1) is section two. Section one is not ad special and section two is.
+ //The dictionary is Dictionary.
+ //private readonly List> usedAdItems = new List>(2);
+ private readonly List _usedAdItems = new List(); //ADITEM:SECTIONUSED
+ //This string keeps track of the last ad item used. This item can then be used to safely remove an ad item from the list of used items.
+ //Used in the OnCellValidating event to store the last ad item used in the event that the user changes a row that already exists.
+ private string _beginningCellValue = "";
+ //Flag showing whether or not the AdSpecialRow has been made in this session.
+ private int _adSpecialIndex = -1;
+ //Set the starting value for temporary IDs for ad items that have yet to be added to the database.
+ //private int _temporaryKey;
+ private readonly AdvertisingProfitControlTableHelper _tableHelperFunctions = new AdvertisingProfitControlTableHelper();
+ //Set flags to indicate whether or not a DataGridView needs to be painted.
+ private bool _projectionsRequirePainting;
+ //Inventory never needs to be parsed on tab page change since no data gets copied over from the other tables.
+ private bool _actualSalesRequiresPainting;
public NewAddRecord()
{
InitializeComponent();
- //Assign the events that all APC DataGridViews will use.
- projectionsDataGridView.RowsAdded += DisplayRowNumbers;
- inventoryDataGridView.RowsAdded += DisplayRowNumbers;
- actualDataGridView.RowsAdded += DisplayRowNumbers;
-
+ //Start by grabbing all the AdItems and putting them into memory.
+ var databaseTracker = new DatabaseTracker();
+ var databaseReader = new DatabaseReader();
+ //Start by pulling the all the ad items into memory.
+ _adItemCollection = databaseReader.GetAdItemsSuggestionList(databaseTracker.DatabaseConnectionString);
+ //Now pull all the suppliers and the ad special list into memory.
+ _supplierCollection = databaseReader.GetSupplierSuggestionList(databaseTracker.DatabaseConnectionString);
+ _adSpecialList = databaseReader.RetrieveAdSpecialList(databaseTracker.DatabaseConnectionString);
//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..
+ //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 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;
- actualDataGridView.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;
+ //Setup the event to handle painting the DataGridView on tab page change.
+ mainTabControl.SelectedIndexChanged += PaintDataGridViewOnTabPageChange;
+ //After all events have been set, construct the DataGridVeiws for use.
+ ConstructApcDataGridViews();
+ ConstructInvoicesDataGridView();//No weekly sales table is nice.
+ }
+
+ private void PaintDataGridViewOnTabPageChange(object sender, EventArgs e)
+ {
+ var helper = new AdvertisingProfitControlTableHelper();
+ switch (mainTabControl.SelectedIndex)
+ {
+ case 0:
+ if (_projectionsRequirePainting)
+ {
+ helper.PaintRowGroupsFromIndex(0, (DataGridView) mainTabControl.TabPages[0].Controls[0]);
+ _projectionsRequirePainting = false;
+ }
+ break;
+ //There is no need to deal with the inventory table here since no data is ever copied over beyond the ad item (or ad special).
+ case 2:
+ if (_actualSalesRequiresPainting)
+ {
+ helper.PaintRowGroupsFromIndex(0, (DataGridView)mainTabControl.TabPages[2].Controls[0]);
+ _actualSalesRequiresPainting = false;
+ }
+ break;
+ }
}
#region APC DataGridView Events
@@ -56,12 +129,274 @@ namespace AdvertsingProfitControl
///
///
///
- private static void DisplayRowNumbers(object sender, DataGridViewRowsAddedEventArgs e)
+ private void DisplayRowNumbers(object sender, DataGridViewRowsAddedEventArgs e)
{
var table = ((DataGridView)sender);
+ //Set a flag based on what tab page is currently being used to indicate whether or not a DataGridView needs painting.
+ switch (mainTabControl.SelectedIndex)
+ {
+ case 0:
+ _projectionsRequirePainting = false;
+ _actualSalesRequiresPainting = true;
+ break;
+ case 1:
+ _projectionsRequirePainting = true;
+ _actualSalesRequiresPainting = true;
+ break;
+ case 2:
+ _projectionsRequirePainting = true;
+ _actualSalesRequiresPainting = false;
+ break;
+ }
table.Rows[e.RowIndex].HeaderCell.Value = (e.RowIndex + 1).ToString();
}
+ ///
+ /// Event Used: CellEnter
+ /// Stores the initial contents of the cell being entered to be compared later
+ /// to see if the user has made any changes (IsDirty).
+ ///
+ ///
+ ///
+ private void StoreBeginningCellValue(object sender, DataGridViewCellEventArgs e)
+ {
+ var dataGridView = (DataGridView) sender;
+ _beginningCellValue = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString();
+ }
+
+ ///
+ /// Event Used: OnRowLeave
+ /// Adds the ad items to the used ad item collection if they are not already in the collection.
+ ///
+ ///
+ ///
+ private void UpdateUsedAdItemCollectionOnRowLeave(object sender, DataGridViewCellEventArgs e)
+ {
+ var dataGridView = ((DataGridView)sender);
+ if (dataGridView.Rows[e.RowIndex].IsNewRow) {return;} //Return if the row is a new row as nothing needs to be done here.
+ int adItemIndex;
+
+ switch (dataGridView.Name)
+ {
+ case "projectionsDataGridView":
+ adItemIndex = (int) SalesTableColumns.AdItem;
+ break;
+ case "actualSalesDataGridView":
+ adItemIndex = (int)SalesTableColumns.AdItem;
+ break;
+ default:
+ adItemIndex = (int) InventoryTableColumns.AdItem;
+ break;
+ }
+ var userInput = dataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString();
+ //Paint the rows to identify what group they belong to.
+ _tableHelperFunctions.PaintRowGroupsFromIndex(e.RowIndex, dataGridView);
+ //Add in used Ad Items to the list.
+ if (userInput == "") return;
+ //Clear the old ad item out of the used ad item collection.
+ var parser = new RowParsing();
+ if (parser.GetRowAttribute(dataGridView.Rows[e.RowIndex]) == RowAttribute.AdSpecialRow)
+ {
+ _adSpecialIndex = e.RowIndex;
+ return;
+ }
+ //Section one (1) detected.
+ if (_adSpecialIndex == -1 || e.RowIndex < _adSpecialIndex)
+ {
+ if (_usedAdItems.Contains(userInput + ":1")) return;
+ _usedAdItems.Add(userInput + ":1");
+ LogConsole.WriteToLog(FrmLogConsole.Level.Debug, "Adding \"" + userInput + "\" to section one (1).");
+ }
+ //Section two (2) detected.
+ else
+ {
+ if (_usedAdItems.Contains(userInput + ":2")) return;
+ _usedAdItems.Add(userInput + ":2");
+ LogConsole.WriteToLog(FrmLogConsole.Level.Debug, "Adding \"" + userInput + "\" to section two (2).");
+ }
+ }
+
+ ///
+ /// Event Used: OnEditingControlShowing
+ /// Configures the auto complete collection and how it will be shown to the user. This method detects the section,
+ /// either one (1) or two (2), based on the gAdSpecialIndex and removes items from the auto complete accordingly.
+ /// Just a measure to help reduce redundancy in the tables.
+ ///
+ ///
+ ///
+ private void DisplayAutoCompleteOnEditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
+ {
+ var dataGridView = ((DataGridView)sender);
+ var autoText = e.Control as TextBox;
+ //Get the index of the ad item column
+ const int adItemIndex = (int)SalesTableColumns.AdItem;
+ if (e.Control is DataGridViewTextBoxEditingControl && dataGridView.CurrentCell.ColumnIndex == adItemIndex)
+ {
+ //Create a copy of the main ad item list that can be freely manipulated.
+ var customAutoComplete = new AutoCompleteStringCollection();
+ var customList = _adItemCollection.ToList();
+
+ //IF the current row is less than the AdSpecialRow, remove all used items with the section 1 attribute.
+ if (_adSpecialIndex == -1 || dataGridView.CurrentCell.RowIndex < _adSpecialIndex)
+ {
+ foreach (var adItem in _usedAdItems)
+ {
+ var adItemString = adItem.Split(':');
+ var section = adItemString[1];
+ var adItemToRemove = adItemString[0];
+ if (section == "1")
+ {
+ customList.RemoveAll(
+ w => w.Equals(adItemToRemove, StringComparison.OrdinalIgnoreCase));
+ }
+ }
+ }
+ //Occurs AFTER the AdSpecial row.
+ else if (dataGridView.CurrentCell.RowIndex > _adSpecialIndex)
+ {
+ foreach (var adItem in _usedAdItems)
+ {
+ var adItemString = adItem.Split(':');
+ var section = adItemString[1];
+ var adItemToRemove = adItemString[0];
+ if (section == "2")
+ {
+ customList.RemoveAll(
+ w => w.Equals(adItemToRemove, StringComparison.OrdinalIgnoreCase));
+ }
+ }
+ }
+ foreach (var item in customList)
+ {
+ customAutoComplete.Add(item);
+ }
+ autoText.KeyDown += ChangeAutoCompleteListOnKeyCombo;
+ _trimmedAdItemCollection = customAutoComplete; //Make a temporary copy of the list for use with the TextBox event handler.
+ autoText.AutoCompleteMode = AutoCompleteMode.Suggest;
+ autoText.AutoCompleteSource = AutoCompleteSource.CustomSource;
+ autoText.AutoCompleteCustomSource = customAutoComplete;
+ }
+ else if (e.Control is DataGridViewTextBoxEditingControl && dataGridView.CurrentCell.ColumnIndex != adItemIndex)
+ {
+ autoText.AutoCompleteMode = AutoCompleteMode.None;
+ }
+ }
+
+ ///
+ /// Event Used: UserDeleteingRow
+ /// This function is responsible for removing ad Items from the gUsedAdItem array; this must be done during the row removing
+ /// event handler so the data in the row can be grabbed and used.
+ ///
+ /// The DataGridView that fired the event.
+ /// Parameters, mainly allowing for canceling the event.
+ private void UpdateUsedAdItemCollectionOnRowRemoving(object sender, CancelEventArgs e)
+ {
+ //Create an object that represents the DataGridView that fired the event.
+ var dataGridView = ((DataGridView)sender);
+ if (dataGridView.CurrentRow == null) return;
+ var currentRowIndex = dataGridView.CurrentRow.Index;
+ //Remove the ad item from the gUsedAdItem collection, if it exists.
+ if (_adSpecialIndex == -1 || currentRowIndex < _adSpecialIndex)
+ {
+ //If the ad item entered in the first cell is in the gUsedAdItems collection, then remove it from there.
+ if (_usedAdItems.Contains(dataGridView.Rows[currentRowIndex].Cells[(int) SalesTableColumns.AdItem].EditedFormattedValue + ":1"))
+ {
+ _usedAdItems.Remove(dataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue + ":1");
+ }
+ }
+ else if (currentRowIndex > _adSpecialIndex)
+ {
+ //If the ad item entered in the first cell is in the gUsedAdItems collection, then remove it from there.
+ if (_usedAdItems.Contains(dataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue + ":2"))
+ {
+ _usedAdItems.Remove(dataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue + ":2");
+ }
+ }
+ else if (currentRowIndex == _adSpecialIndex)
+ {
+ //Handle removing the AdSpecial row.
+ var result = MessageBox.Show(@"Deleting the Ad Special row will remove all rows beneath it. Do you wish to continue?", @"Clear " + dataGridView.Rows[currentRowIndex].Cells[1].EditedFormattedValue, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
+ if (result == DialogResult.Yes)
+ {
+ //Clear all events that handle row removal from both DataGridViews.
+ //Projections table
+ projectionsDataGridView.RowsRemoved -= ProjectionRowRemoved;
+ projectionsDataGridView.UserDeletingRow -= UpdateUsedAdItemCollectionOnRowRemoving;
+ //Inventory table
+ inventoryDataGridView.RowsRemoved -= InventoryRowRemoved;
+ inventoryDataGridView.UserDeletingRow -= UpdateUsedAdItemCollectionOnRowRemoving;
+ //Actual Sales table
+ actualSalesDataGridView.RowsRemoved -= ActualSalesRowRemoved;
+ actualSalesDataGridView.UserDeletingRow -= UpdateUsedAdItemCollectionOnRowRemoving;
+
+ //Now for-each through each row that is underneath the Ad Special row.
+ for (var rowIndex = dataGridView.RowCount; currentRowIndex != rowIndex; rowIndex--)
+ {
+ //If the ad item entered in the first cell is in the gUsedAdItems collection, then remove it from there.
+ if (_usedAdItems.Contains(dataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue + ":2"))
+ {
+ _usedAdItems.Remove(dataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue + ":2");
+ }
+ if (projectionsDataGridView.Rows[currentRowIndex].IsNewRow != true)
+ {
+ projectionsDataGridView.Rows.RemoveAt(currentRowIndex);
+ }
+ if (inventoryDataGridView.Rows[currentRowIndex].IsNewRow != true)
+ {
+ inventoryDataGridView.Rows.RemoveAt(currentRowIndex);
+ }
+ if (actualSalesDataGridView.Rows[currentRowIndex].IsNewRow != true)
+ {
+ actualSalesDataGridView.Rows.RemoveAt(currentRowIndex);
+ }
+ }
+ //Re-enable all row removal events on both tables.
+ //Projections table
+ projectionsDataGridView.RowsRemoved += ProjectionRowRemoved;
+ projectionsDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
+ //Inventory table
+ inventoryDataGridView.RowsRemoved += InventoryRowRemoved;
+ inventoryDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
+ //Actual Sales table
+ actualSalesDataGridView.RowsRemoved += ActualSalesRowRemoved;
+ actualSalesDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
+ //Reset the gAdSpecialIndex to -1.
+ _adSpecialIndex = -1;
+ e.Cancel = true; //Prevent the new row from being removed.
+ }
+ else
+ {
+ e.Cancel = true;
+ }
+ }
+ }
+
+ private void ChangeAutoCompleteListOnKeyCombo(object sender, KeyEventArgs e)
+ {
+ var textBox = (TextBox)sender;
+ informationLabel.Text = "";
+
+ if (e.Modifiers == Keys.Alt && e.KeyCode == Keys.S)
+ {
+ if (_adSpecialIndex == -1)
+ {
+ textBox.AutoCompleteCustomSource = _adSpecialList;
+ informationLabel.Text = @"Auto complete mode changed to Ad Special.";
+ }
+ else
+ {
+ textBox.AutoCompleteCustomSource = _trimmedAdItemCollection;
+ informationLabel.Text = @"An Ad Special row already exists, auto complete mode\n can not be changed.";
+ }
+ }
+ else if (e.Modifiers == Keys.Alt && e.KeyCode == Keys.A)
+ {
+ textBox.AutoCompleteCustomSource = _trimmedAdItemCollection;
+ informationLabel.Text = @"Auto complete mode changed to Ad Items.";
+ }
+ e.Handled = false;
+ }
+
#endregion
#region Sales DataGridView Events
@@ -77,109 +412,1102 @@ namespace AdvertsingProfitControl
{
//Grab the DataGirdView that fired the event and make it into a local variable.
var dataGridView = ((DataGridView)sender);
- //
+ var userInput = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString();
+ //TODO: Write a custom parsing engine for detecting when bins are entered.
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)
+ //Check to make sure we're not in the boolean fields or the ID field.
+ if(e.ColumnIndex >= (int)SalesTableColumns.IsHeaderRow || e.ColumnIndex == (int)SalesTableColumns.Id)
{
- 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"));
+ //Cell validating gets to handle updating the used ad item list since it handles cells on by one, instead by a whole row.
+ if (userInput != _beginningCellValue && e.ColumnIndex == (int) SalesTableColumns.AdItem)
+ {
+ //The user is trying to change the ad special text to something else.
+ if (e.RowIndex == _adSpecialIndex)
+ {
+ var parser = new RowParsing();
+ if (parser.CheckForGroupKeyWord(userInput) == "NoGroupFound")
+ {
+ MessageBox.Show(
+ @"The Ad Special row's column one (1) cannot be changed. You must delete this row by clicking on the header cell and pressing 'Delete'.",
+ @"Invalid Operation on Ad Special Row", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = _beginningCellValue;
+ dataGridView.RefreshEdit();
+ return;
+ }
+ //Mark all ad special members as dirty since the user changed the ad special.
+ for (var index = _adSpecialIndex + 1; index < dataGridView.RowCount; index++)
+ {
+ //Add overflow protection
+ if (index < projectionsDataGridView.RowCount)
+ {
+ projectionsDataGridView.Rows[index].Cells[(int) SalesTableColumns.IsDirty].Value = true;
+ }
+ if (index < actualSalesDataGridView.RowCount)
+ {
+ actualSalesDataGridView.Rows[index].Cells[(int)SalesTableColumns.IsDirty].Value = true;
+ }
+ if (index < inventoryDataGridView.RowCount)
+ {
+ inventoryDataGridView.Rows[index].Cells[(int)InventoryTableColumns.IsDirty].Value = true;
+ }
+ }
+ }
+ _usedAdItems.Remove(_beginningCellValue + (_adSpecialIndex == -1 || e.RowIndex < _adSpecialIndex ? ":1" : ":2"));
+ dataGridView.Rows[e.RowIndex].Cells[(int) SalesTableColumns.IsDirty].Value = true;
+ }
+ double parsedNumber;
+ //Check to see if the current column is the ad item column.
+ switch (e.ColumnIndex)
+ {
+ case (int)SalesTableColumns.AdItem: //Ad Item
+ //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(userInput, @"\s+", "")))
+ {
+ var parser = new RowParsing();
+ if (parser.CheckForGroupKeyWord(userInput) != "NoGroupFound")
+ {
+ _adSpecialIndex = e.RowIndex;
+ }
+ //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[e.ColumnIndex].Value = TextFormat.FormatAdItemText(userInput);
+ //Force a refresh so the cell's text updates and displays for the user.
+ dataGridView.RefreshEdit();
+ return;
+ }
+ //Otherwise, show an error.
+ dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "Ad Item needed";
+ break;
+ case (int) SalesTableColumns.Sold: //Sold
+ //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.
+ dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = textInfo.ToTitleCase(userInput);
+ dataGridView.RefreshEdit();
+ return;
+ }
+ //Try parsing the text entered as a number and if that fails then break out and clear the value entered.
+ if (double.TryParse(userInput, out parsedNumber))
+ {
+ //Add the formatted value to the cell.
+ dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Math.Round(parsedNumber, 2).ToString("N", new CultureInfo("en-US"));
+ }
+ else
+ {
+ if (userInput == "")
+ {
+ return;
+ }
+ 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;
+ }
+ break;
+ case (int) SalesTableColumns.SalePrice:
+ //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 (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.
+ }
+ //Try parsing the text entered as a number and if that fails then break out and clear the value entered.
+ if (double.TryParse(userInput, out parsedNumber))
+ {
+ dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Math.Round(parsedNumber, 2).ToString("N", new CultureInfo("en-US"));
+ }
+ else
+ {
+ if (userInput == "")
+ {
+ return;
+ }
+ 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;
+ }
+ break;
+ default:
+ //Purely here for protection against parsing the Boolean columns by mistake.
+ if (e.ColumnIndex >= (int) SalesTableColumns.IsAdSpecialRow) {return;}
+ //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.
+ if (double.TryParse(userInput, out parsedNumber))
+ {
+ dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Math.Round(parsedNumber, 2).ToString("N", new CultureInfo("en-US"));
+ }
+ else
+ {
+ if (userInput == "")
+ {
+ return;
+ }
+ 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;
+ }
+ break;
+ }
//Always refresh edit so the new value shows up to the user.
dataGridView.RefreshEdit();
}
#endregion
+ #region Projected Sales DataGridView Events
+
+ ///
+ /// Event Used: RowValidating
+ /// Checks to make sure the row is valid (has an ad item) and
+ /// then copies the contents where possible over to the inventory
+ /// and actual sales DataGridViews.
+ ///
+ ///
+ ///
+ private void ValidateProjectedRow(object sender, DataGridViewCellCancelEventArgs e)
+ {
+ //Grab the index of the ad item, assuming the Sales tables and the Inventory table stay in the same position.
+ const int adItemIndex = (int) SalesTableColumns.AdItem;
+ //Do not even attempt anything since this is a new row and nothing to worry about.
+ if (projectionsDataGridView.Rows[e.RowIndex].IsNewRow)
+ {
+ return;
+ }
+ //Clear all whitespace and check for a null value in the ad item column.
+ if (Regex.Replace(projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString(), @"\s+", "") == "")
+ {
+ MessageBox.Show(@"An ad item is required.", @"No Ad Item Specified");
+ e.Cancel = true;
+ }
+ //Check to see if the user left a row that already exists and doesn't require being copied over.
+ if (projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString() == actualSalesDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString())
+ {
+ return;
+ }
+ //Now check to make sure there is an ad item present, otherwise throw an error and block the user from leaving the current row.
+ if (projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString() != "")
+ {
+ //Next check to see if the user changed the ad item is the corresponding row.
+ if (projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString() != actualSalesDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString())
+ {
+ if (projectionsDataGridView.RowCount == actualSalesDataGridView.RowCount)
+ {
+ var adItemText = projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString();
+ actualSalesDataGridView.Rows[e.RowIndex].Cells[adItemIndex].Value = adItemText;
+ inventoryDataGridView.Rows[e.RowIndex].Cells[adItemIndex].Value = adItemText;
+ projectionsDataGridView.RefreshEdit();
+ //Remove the last ad item from the UsedAdItem array, the new one will be added in the OnRowLeave event handler.
+ if (_adSpecialIndex == -1 || e.RowIndex < _adSpecialIndex)
+ {
+ _usedAdItems.RemoveAll(I => I.Equals(_beginningCellValue + ":1", StringComparison.OrdinalIgnoreCase));
+ }
+ else
+ {
+ _usedAdItems.RemoveAll(I => I.Equals(_beginningCellValue + ":2", StringComparison.OrdinalIgnoreCase));
+ }
+
+ return;
+ }
+ }
+ var rowContents = new object[projectionsDataGridView.ColumnCount];
+ //Spin through the DataGridViewCells in the row and add their contents to an array.
+ for (var i = 0; i < projectionsDataGridView.ColumnCount; i++)
+ {
+ //Grab the Ad Item in the first cell and add it into the array.
+ switch (i)
+ {
+ case (int) SalesTableColumns.AdItem:
+ rowContents[i] = projectionsDataGridView.Rows[e.RowIndex].Cells[i].EditedFormattedValue.ToString();
+ break;
+ case (int) SalesTableColumns.SalePrice:
+ //IF the Sale Price cell is empty then place 0.00 into the array as a place holder value (assuming this row is a HeaderRow).
+ if (projectionsDataGridView.Rows[e.RowIndex].Cells[i].EditedFormattedValue.ToString() == "")
+ {
+ rowContents[i] = "";
+ }
+ //ELSE place the value from the Projections table into the array, since Sale Price can be determined before actual data is used.
+ else
+ {
+ rowContents[i] = projectionsDataGridView.Rows[e.RowIndex].Cells[i].EditedFormattedValue.ToString();
+ }
+ break;
+ case (int) SalesTableColumns.Cost:
+ //IF the Cost cell is empty then place 0.00 into the array as a place holder value (assuming this row is a HeaderRow).
+ if (projectionsDataGridView.Rows[e.RowIndex].Cells[i].EditedFormattedValue.ToString() == "")
+ {
+ rowContents[i] = "";
+ }
+ //ELSE place the value from the Projections table into the array, since Cost can be determined before actual data is used.
+ else
+ {
+ rowContents[i] = projectionsDataGridView.Rows[e.RowIndex].Cells[i].EditedFormattedValue.ToString();
+ }
+ break;
+ case (int)SalesTableColumns.IsHeaderRow:
+ rowContents[i] = projectionsDataGridView.Rows[e.RowIndex].Cells[(int)SalesTableColumns.IsHeaderRow].Value;
+ break;
+ case (int)SalesTableColumns.IsMemberRow:
+ rowContents[i] = projectionsDataGridView.Rows[e.RowIndex].Cells[(int)SalesTableColumns.IsMemberRow].Value;
+ break;
+ case (int)SalesTableColumns.IsAdSpecialRow:
+ //Determine if the current row is the special row.
+ projectionsDataGridView.Rows[e.RowIndex].Cells[(int) SalesTableColumns.IsAdSpecialRow].Value =
+ e.RowIndex == _adSpecialIndex;
+ rowContents[i] = e.RowIndex == _adSpecialIndex;
+ break;
+ case (int)SalesTableColumns.IsAdSpecialMember:
+ //Check if this is a member of the ad special group.
+ if (_adSpecialIndex != -1)
+ {
+ projectionsDataGridView.Rows[e.RowIndex].Cells[(int) SalesTableColumns.IsAdSpecialMember
+ ].Value = e.RowIndex > _adSpecialIndex;
+ rowContents[i] = e.RowIndex > _adSpecialIndex;
+ }
+ else
+ {
+ rowContents[i] = false;
+ }
+ break;
+ case (int)SalesTableColumns.IsDirty:
+ rowContents[i] = true;
+ break;
+ case (int)SalesTableColumns.IsInDatabase:
+ rowContents[i] = false;
+ break;
+ default:
+ rowContents[i] = "";
+ break;
+ }
+ }
+ actualSalesDataGridView.Rows.Add(rowContents);
+ //Build a collection of objects for the inventory table to use.
+ var inventoryNewRow = new object[inventoryDataGridView.ColumnCount];
+ //Spin through the DataGridViewCells in the row and add their contents to an array.
+ for (var i = 0; i < projectionsDataGridView.ColumnCount; i++)
+ {
+ //Grab the Ad Item in the first cell and add it into the array.
+ switch (i)
+ {
+ case (int)SalesTableColumns.Id:
+ inventoryNewRow[(int)InventoryTableColumns.Id] = "";
+ break;
+ case (int)SalesTableColumns.AdItem:
+ inventoryNewRow[(int)InventoryTableColumns.AdItem] =
+ projectionsDataGridView.Rows[e.RowIndex].Cells[i].EditedFormattedValue.ToString();
+ break;
+ case (int)SalesTableColumns.IsHeaderRow:
+ rowContents[(int)InventoryTableColumns.IsHeaderRow] = projectionsDataGridView.Rows[e.RowIndex].Cells[(int)SalesTableColumns.IsHeaderRow].Value;
+ break;
+ case (int)SalesTableColumns.IsMemberRow:
+ rowContents[(int)InventoryTableColumns.IsMemberRow] = projectionsDataGridView.Rows[e.RowIndex].Cells[(int)SalesTableColumns.IsMemberRow].Value;
+ break;
+ case (int)SalesTableColumns.IsAdSpecialRow:
+ //Determine if the current row is the special row.
+ inventoryNewRow[(int)InventoryTableColumns.IsAdSpecialRow] = (e.RowIndex == _adSpecialIndex);
+ break;
+ case (int)SalesTableColumns.IsAdSpecialMember:
+ //Check if this is a member of the ad special group.
+ if (_adSpecialIndex != -1)
+ {
+ inventoryNewRow[(int)InventoryTableColumns.IsAdSpecialMember] = (e.RowIndex > _adSpecialIndex);
+ }
+ else
+ {
+ inventoryNewRow[(int)InventoryTableColumns.IsAdSpecialMember] = false;
+ }
+ break;
+ case (int)SalesTableColumns.IsDirty:
+ inventoryNewRow[(int)InventoryTableColumns.IsDirty] = true;
+ break;
+ case (int)SalesTableColumns.IsInDatabase:
+ inventoryNewRow[(int) InventoryTableColumns.IsInDatabase] = false;
+ break;
+ default:
+ if (i < (int) InventoryTableColumns.IsHeaderRow)
+ {
+ inventoryNewRow[i] = "";
+ }
+ break;
+ }
+ }
+ inventoryDataGridView.Rows.Add(inventoryNewRow);
+ }
+ else
+ {
+ MessageBox.Show(@"An Ad Item is required.", @"Invalid Ad Item");
+ projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].Selected = true;
+ e.Cancel = true;
+ }
+ }
+
+ private void ProjectionRowRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
+ {
+ var dataGridView = ((DataGridView)sender);
+ //Provide protection against overflows
+ if ((e.RowIndex + 1) > dataGridView.Rows.Count)
+ {
+ return;
+ }
+ //Disable all row removing events from the other two tables to prevent interference.
+ inventoryDataGridView.UserDeletingRow -= UpdateUsedAdItemCollectionOnRowRemoving;
+ inventoryDataGridView.RowsRemoved -= InventoryRowRemoved;
+
+ actualSalesDataGridView.UserDeletingRow -= UpdateUsedAdItemCollectionOnRowRemoving;
+ actualSalesDataGridView.RowsRemoved -= ActualSalesRowRemoved;
+
+ //IF the row count on the passed DataGridView is less then the other table's row count...
+ if (projectionsDataGridView.RowCount <= actualSalesDataGridView.RowCount && projectionsDataGridView.RowCount <= actualSalesDataGridView.RowCount)
+ {
+ //... it is lower so its safe to assume that both tables have the same row that can be removed.
+ if (!actualSalesDataGridView.Rows[e.RowIndex].IsNewRow)
+ {
+ actualSalesDataGridView.Rows.RemoveAt(e.RowIndex);
+ }
+
+ if (!inventoryDataGridView.Rows[e.RowIndex].IsNewRow)
+ {
+ inventoryDataGridView.Rows.RemoveAt(e.RowIndex);
+ }
+ }
+ //ELSE IF the row count is larger then the other table's row count...
+ else
+ {
+ //... Log the error and then what?
+ //TODO: Figure out if this is an error condition.
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "The Projections table has more rows then the Actual Sales table.");
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "Projections Row Count: " + projectionsDataGridView.RowCount);
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "Inventory Row Count: " + inventoryDataGridView.RowCount);
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "Actual Sales Row Count: " + actualSalesDataGridView.RowCount);
+ errorLabel.Text = @"Error removing rows from Actual Sales and Inventory.";
+ }
+ //... After all the row removal has been finished re-enable the row removal events.
+ inventoryDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
+ inventoryDataGridView.RowsRemoved += InventoryRowRemoved;
+
+ actualSalesDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
+ actualSalesDataGridView.RowsRemoved += ActualSalesRowRemoved;
+
+ //Reset the row numbers in the tables.
+ for (var i = e.RowIndex; i < (dataGridView.RowCount); i++)
+ {
+ projectionsDataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
+ inventoryDataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
+ actualSalesDataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
+ }
+ //Refresh the DataGridViews so the header cell's number get repainted properly and repaint the rows in case any groups get messed up during row removal.
+ projectionsDataGridView.RefreshEdit();
+ inventoryDataGridView.RefreshEdit();
+ actualSalesDataGridView.RefreshEdit();
+ _tableHelperFunctions.PaintRowGroups(dataGridView);
+ }
+
+ #endregion
+
+ #region Inventory DataGridView Events
+
+ ///
+ /// Event Used: CellValidating
+ /// Validates the contents of the cell that the user is attempting to leave. Applies formatting
+ /// to text as needed and prevents the user from leaving invalid cells.
+ ///
+ ///
+ ///
+ private void ValidateInventoryCellContents(object sender, DataGridViewCellValidatingEventArgs e)
+ {
+ //Grab the DataGirdView that fired the event and make it into a local variable.
+ var dataGridView = ((DataGridView)sender);
+ var userInput = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString();
+ //TODO: Write a custom parsing engine for detecting when bins are entered.
+ 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 make sure we're not in the boolean fields or the ID field.
+ if (e.ColumnIndex >= (int)InventoryTableColumns.IsHeaderRow || e.ColumnIndex == (int)InventoryTableColumns.Id)
+ {
+ return;
+ }
+ //Cell validating gets to handle updating the used ad item list since it handles cells on by one, instead by a whole row.
+ if (userInput != _beginningCellValue && e.ColumnIndex == (int)InventoryTableColumns.AdItem)
+ {
+ //The user is trying to change the ad special text to something else.
+ if (e.RowIndex == _adSpecialIndex)
+ {
+ var parser = new RowParsing();
+ if (parser.CheckForGroupKeyWord(userInput) == "NoGroupFound")
+ {
+ MessageBox.Show(@"The Ad Special row's column one (1) cannot be changed. You must delete this row by clicking on the header cell and pressing 'Delete'.", @"Invalid Operation on Ad Special Row", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = _beginningCellValue;
+ dataGridView.RefreshEdit();
+ return;
+ }
+ else
+ {
+ //Mark all ad special members as dirty since the user changed the ad special.
+ for (var index = _adSpecialIndex + 1; index < dataGridView.RowCount; index++)
+ {
+ //Add overflow protection
+ if (index < projectionsDataGridView.RowCount)
+ {
+ projectionsDataGridView.Rows[index].Cells[(int)SalesTableColumns.IsDirty].Value = true;
+ }
+ if (index < actualSalesDataGridView.RowCount)
+ {
+ actualSalesDataGridView.Rows[index].Cells[(int)SalesTableColumns.IsDirty].Value = true;
+ }
+ if (index < inventoryDataGridView.RowCount)
+ {
+ inventoryDataGridView.Rows[index].Cells[(int)InventoryTableColumns.IsDirty].Value = true;
+ }
+ }
+ }
+ }
+ dataGridView.Rows[e.RowIndex].Cells[(int) InventoryTableColumns.IsDirty].Value = true;
+ _usedAdItems.Remove(_beginningCellValue + (_adSpecialIndex == -1 || e.RowIndex < _adSpecialIndex ? ":1" : ":2"));
+ }
+ //Check to see if the current column is the ad item column.
+ switch (e.ColumnIndex)
+ {
+ case (int) InventoryTableColumns.AdItem:
+ //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(userInput, @"\s+", "")))
+ {
+ var parser = new RowParsing();
+ if (parser.CheckForGroupKeyWord(userInput) != "NoGroupFound")
+ {
+ _adSpecialIndex = e.RowIndex;
+ }
+ //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[e.ColumnIndex].Value = TextFormat.FormatAdItemText(userInput);
+ //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.
+ dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "Ad Item needed";
+ break;
+ default:
+ //Purely here for protection against parsing the Boolean columns by mistake.
+ if (e.ColumnIndex >= (int)InventoryTableColumns.IsAdSpecialRow) { return; }
+ //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.
+ dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = textInfo.ToTitleCase(userInput);
+ dataGridView.RefreshEdit();
+ return;
+ }
+ double parsedNumber;
+ //Try parsing the text entered as a number and if that fails then break out and clear the value entered.
+ if (userInput != "" && !double.TryParse(userInput, out parsedNumber))
+ {
+ 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;
+ }
+ //Add the value to the cell.
+ dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = userInput;
+ break;
+ }
+ //Always refresh edit so the new value shows up to the user.
+ dataGridView.RefreshEdit();
+ }
+
+ ///
+ /// Event Used: RowValidating
+ /// Checks to make sure the row is valid (has an ad item) and
+ /// then copies the contents where possible over to the projections
+ /// and actual sales DataGridViews.
+ ///
+ ///
+ ///
+ private void ValidateInventoryRow(object sender, DataGridViewCellCancelEventArgs e)
+ {
+ //Grab the index of the ad item, assuming the Sales tables and the Inventory table stay in the same position.
+ const int adItemIndex = (int)SalesTableColumns.AdItem;
+ //Do not even attempt anything since this is a new row and nothing to worry about.
+ if (inventoryDataGridView.Rows[e.RowIndex].IsNewRow)
+ {
+ return;
+ }
+ //Check to see if the user left a row that already exists and doesn't require being copied over.
+ if (inventoryDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString() == actualSalesDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString())
+ {
+ return;
+ }
+ //Clear all whitespace and check for a null value in the ad item column.
+ if (Regex.Replace(projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString(), @"\s+", "") == "")
+ {
+ MessageBox.Show(@"An ad item is required.", @"No Ad Item Specified");
+ e.Cancel = true;
+ }
+ //Now check to make sure there is an ad item present, otherwise throw an error and block the user from leaving the current row.
+ if (inventoryDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString() != "")
+ {
+ //Next check to see if the user changed the ad item is the corresponding row.
+ if (inventoryDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString() != actualSalesDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString())
+ {
+ if (inventoryDataGridView.RowCount == actualSalesDataGridView.RowCount)
+ {
+ var adItemText = inventoryDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString();
+ projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].Value = adItemText;
+ actualSalesDataGridView.Rows[e.RowIndex].Cells[adItemIndex].Value = adItemText;
+ //inventoryDataGridView.RefreshEdit();
+ //Remove the last ad item from the UsedAdItem array, the new one will be added in the OnRowLeave event handler.
+ if (_adSpecialIndex == -1 || e.RowIndex < _adSpecialIndex)
+ {
+ _usedAdItems.RemoveAll(I => I.Equals(_beginningCellValue + ":1", StringComparison.OrdinalIgnoreCase));
+ }
+ else
+ {
+ _usedAdItems.RemoveAll(I => I.Equals(_beginningCellValue + ":2", StringComparison.OrdinalIgnoreCase));
+ }
+
+ return;
+ }
+ }
+ var rowContents = new object[actualSalesDataGridView.ColumnCount];
+ //Spin through the DataGridViewCells in the row and add their contents to an array.
+ for (var i = 0; i < actualSalesDataGridView.ColumnCount; i++)
+ {
+ //Grab the Ad Item in the first cell and add it into the array.
+ switch (i)
+ {
+ case (int)SalesTableColumns.AdItem:
+ rowContents[i] = inventoryDataGridView.Rows[e.RowIndex].Cells[(int)InventoryTableColumns.AdItem].EditedFormattedValue.ToString();
+ break;
+ case (int)SalesTableColumns.IsHeaderRow:
+ rowContents[i] = inventoryDataGridView.Rows[e.RowIndex].Cells[(int)InventoryTableColumns.IsHeaderRow].Value;
+ break;
+ case (int)SalesTableColumns.IsMemberRow:
+ rowContents[i] = projectionsDataGridView.Rows[e.RowIndex].Cells[(int)InventoryTableColumns.IsMemberRow].Value;
+ break;
+ case (int)SalesTableColumns.IsAdSpecialRow:
+ //Determine if the current row is the special row.
+ inventoryDataGridView.Rows[e.RowIndex].Cells[(int)InventoryTableColumns.IsAdSpecialRow].Value =
+ e.RowIndex == _adSpecialIndex;
+ rowContents[i] = e.RowIndex == _adSpecialIndex;
+ break;
+ case (int)SalesTableColumns.IsAdSpecialMember:
+ //Check if this is a member of the ad special group.
+ if (_adSpecialIndex != -1)
+ {
+ inventoryDataGridView.Rows[e.RowIndex].Cells[(int)InventoryTableColumns.IsAdSpecialMember].Value = e.RowIndex > _adSpecialIndex;
+ rowContents[i] = e.RowIndex > _adSpecialIndex;
+ }
+ else
+ {
+ rowContents[i] = false;
+ }
+ break;
+ case (int)SalesTableColumns.IsDirty:
+ rowContents[i] = true;
+ break;
+ case (int)SalesTableColumns.IsInDatabase:
+ rowContents[i] = false;
+ break;
+ default:
+ rowContents[i] = "";
+ break;
+ }
+ }
+ projectionsDataGridView.Rows.Add(rowContents);
+ actualSalesDataGridView.Rows.Add(rowContents);
+ }
+ else
+ {
+ MessageBox.Show(@"An Ad Item is required.", @"Invalid Ad Item");
+ projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].Selected = true;
+ e.Cancel = true;
+ }
+ }
+
+ private void InventoryRowRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
+ {
+ var dataGridView = ((DataGridView)sender);
+ //Provide protection against overflows
+ if ((e.RowIndex + 1) > dataGridView.Rows.Count)
+ {
+ return;
+ }
+ //Disable all row removing events from the other two tables to prevent interference.
+ projectionsDataGridView.UserDeletingRow -= UpdateUsedAdItemCollectionOnRowRemoving;
+ projectionsDataGridView.RowsRemoved -= ProjectionRowRemoved;
+
+ actualSalesDataGridView.UserDeletingRow -= UpdateUsedAdItemCollectionOnRowRemoving;
+ actualSalesDataGridView.RowsRemoved -= ActualSalesRowRemoved;
+
+ //IF the row count on the passed DataGridView is less then the other table's row count...
+ if (inventoryDataGridView.RowCount <= projectionsDataGridView.RowCount && inventoryDataGridView.RowCount <= actualSalesDataGridView.RowCount)
+ {
+ //... it is lower so its safe to assume that both tables have the same row that can be removed.
+ if (!projectionsDataGridView.Rows[e.RowIndex].IsNewRow)
+ {
+ projectionsDataGridView.Rows.RemoveAt(e.RowIndex);
+ }
+
+ if (!actualSalesDataGridView.Rows[e.RowIndex].IsNewRow)
+ {
+ actualSalesDataGridView.Rows.RemoveAt(e.RowIndex);
+ }
+ }
+ //ELSE IF the row count is larger then the other table's row count...
+ else
+ {
+ //... Log the error and then what?
+ //TODO: Figure out if this is an error condition.
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "The Inventory table has more rows then the Actual Sales table.");
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "Projections Row Count: " + projectionsDataGridView.RowCount);
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "Inventory Row Count: " + inventoryDataGridView.RowCount);
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "Actual Sales Row Count: " + actualSalesDataGridView.RowCount);
+ errorLabel.Text = @"Error removing rows from Actual Sales and Inventory.";
+ }
+ //... After all the row removal has been finished re-enable the row removal events.
+ projectionsDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
+ projectionsDataGridView.RowsRemoved += ProjectionRowRemoved;
+
+ actualSalesDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
+ actualSalesDataGridView.RowsRemoved += ActualSalesRowRemoved;
+
+ //Reset the row numbers in each table.
+ for (var i = e.RowIndex; i < (dataGridView.RowCount); i++)
+ {
+ projectionsDataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
+ inventoryDataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
+ actualSalesDataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
+ }
+ //Refresh the DataGridViews so the header cell's number get repainted properly and repaint the rows in case any groups get messed up during row removal.
+ projectionsDataGridView.RefreshEdit();
+ inventoryDataGridView.RefreshEdit();
+ actualSalesDataGridView.RefreshEdit();
+ _tableHelperFunctions.PaintRowGroups(dataGridView);
+ }
+
+ #endregion
+
+ #region Actual Sales DataGridView Events
+
+ ///
+ /// Event Used: RowValidating
+ /// Checks to make sure the row is valid (has an ad item) and
+ /// then copies the contents where possible over to the inventory
+ /// and actual sales DataGridViews.
+ ///
+ ///
+ ///
+ private void ValidateActualSalesRow(object sender, DataGridViewCellCancelEventArgs e)
+ {
+ //Grab the index of the ad item, assuming the Sales tables and the Inventory table stay in the same position.
+ const int adItemIndex = (int)SalesTableColumns.AdItem;
+ //Do not even attempt anything since this is a new row and nothing to worry about.
+ if (actualSalesDataGridView.Rows[e.RowIndex].IsNewRow)
+ {
+ return;
+ }
+ //Check to see if the user left a row that already exists and doesn't require being copied over.
+ if (actualSalesDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString() == projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString())
+ {
+ return;
+ }
+ //Clear all whitespace and check for a null value in the ad item column.
+ if (Regex.Replace(actualSalesDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString(), @"\s+", "") == "")
+ {
+ MessageBox.Show(@"An ad item is required.", @"No Ad Item Specified");
+ e.Cancel = true;
+ }
+ //Now check to make sure there is an ad item present, otherwise throw an error and block the user from leaving the current row.
+ if (actualSalesDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString() != "")
+ {
+ //Next check to see if the user changed the ad item is the corresponding row.
+ if (actualSalesDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString() != projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString())
+ {
+ if (actualSalesDataGridView.RowCount == projectionsDataGridView.RowCount)
+ {
+ var adItemText = actualSalesDataGridView.Rows[e.RowIndex].Cells[adItemIndex].EditedFormattedValue.ToString();
+ projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].Value = adItemText;
+ inventoryDataGridView.Rows[e.RowIndex].Cells[adItemIndex].Value = adItemText;
+ //projectionsDataGridView.RefreshEdit();
+ //Remove the last ad item from the UsedAdItem array, the new one will be added in the OnRowLeave event handler.
+ if (_adSpecialIndex == -1 || e.RowIndex < _adSpecialIndex)
+ {
+ _usedAdItems.RemoveAll(I => I.Equals(_beginningCellValue + ":1", StringComparison.OrdinalIgnoreCase));
+ }
+ else
+ {
+ _usedAdItems.RemoveAll(I => I.Equals(_beginningCellValue + ":2", StringComparison.OrdinalIgnoreCase));
+ }
+
+ return;
+ }
+ }
+ var rowContents = new object[actualSalesDataGridView.ColumnCount];
+ //Spin through the DataGridViewCells in the row and add their contents to an array.
+ for (var i = 0; i < actualSalesDataGridView.ColumnCount; i++)
+ {
+ //Grab the Ad Item in the first cell and add it into the array.
+ switch (i)
+ {
+ case (int)SalesTableColumns.AdItem:
+ rowContents[i] = actualSalesDataGridView.Rows[e.RowIndex].Cells[i].EditedFormattedValue.ToString();
+ break;
+ case (int)SalesTableColumns.SalePrice:
+ rowContents[i] = actualSalesDataGridView.Rows[e.RowIndex].Cells[i].EditedFormattedValue.ToString();
+ break;
+ case (int)SalesTableColumns.Cost:
+ rowContents[i] = actualSalesDataGridView.Rows[e.RowIndex].Cells[i].EditedFormattedValue.ToString();
+ break;
+ case (int)SalesTableColumns.IsHeaderRow:
+ rowContents[i] = actualSalesDataGridView.Rows[e.RowIndex].Cells[(int) SalesTableColumns.IsHeaderRow].Value;
+ break;
+ case (int)SalesTableColumns.IsMemberRow:
+ rowContents[i] = actualSalesDataGridView.Rows[e.RowIndex].Cells[(int)SalesTableColumns.IsMemberRow].Value;
+ break;
+ case (int)SalesTableColumns.IsAdSpecialRow:
+ //Determine if the current row is the special row.
+ actualSalesDataGridView.Rows[e.RowIndex].Cells[(int)SalesTableColumns.IsAdSpecialRow].Value =
+ e.RowIndex == _adSpecialIndex;
+ rowContents[i] = e.RowIndex == _adSpecialIndex;
+ break;
+ case (int)SalesTableColumns.IsAdSpecialMember:
+ //Check if this is a member of the ad special group.
+ if (_adSpecialIndex != -1)
+ {
+ actualSalesDataGridView.Rows[e.RowIndex].Cells[(int)SalesTableColumns.IsAdSpecialMember
+ ].Value = e.RowIndex > _adSpecialIndex;
+ rowContents[i] = e.RowIndex > _adSpecialIndex;
+ }
+ else
+ {
+ rowContents[i] = false;
+ }
+ break;
+ case (int)SalesTableColumns.IsDirty:
+ rowContents[i] = true;
+ break;
+ case (int)SalesTableColumns.IsInDatabase:
+ rowContents[i] = false;
+ break;
+ default:
+ rowContents[i] = "";
+ break;
+ }
+ }
+ projectionsDataGridView.Rows.Add(rowContents);
+ //Build a collection of objects for the inventory table to use.
+ var inventoryNewRow = new object[inventoryDataGridView.ColumnCount];
+ //Spin through the DataGridViewCells in the row and add their contents to an array.
+ for (var i = 0; i < actualSalesDataGridView.ColumnCount; i++)
+ {
+ //Grab the Ad Item in the first cell and add it into the array.
+ switch (i)
+ {
+ case (int)SalesTableColumns.AdItem:
+ inventoryNewRow[(int)InventoryTableColumns.AdItem] =
+ actualSalesDataGridView.Rows[e.RowIndex].Cells[i].EditedFormattedValue.ToString();
+ break;
+ case (int)SalesTableColumns.IsHeaderRow:
+ rowContents[(int)InventoryTableColumns.IsHeaderRow] = actualSalesDataGridView.Rows[e.RowIndex].Cells[(int)SalesTableColumns.IsHeaderRow].Value;
+ break;
+ case (int)SalesTableColumns.IsMemberRow:
+ rowContents[(int)InventoryTableColumns.IsMemberRow] = actualSalesDataGridView.Rows[e.RowIndex].Cells[(int)SalesTableColumns.IsMemberRow].Value;
+ break;
+ case (int)SalesTableColumns.IsAdSpecialRow:
+ //Determine if the current row is the special row.
+ inventoryNewRow[(int)InventoryTableColumns.IsAdSpecialRow] = e.RowIndex == _adSpecialIndex;
+ break;
+ case (int)SalesTableColumns.IsAdSpecialMember:
+ //Check if this is a member of the ad special group.
+ if (_adSpecialIndex != -1)
+ {
+ inventoryNewRow[(int) InventoryTableColumns.IsAdSpecialMember] = e.RowIndex > _adSpecialIndex;
+ }
+ else
+ {
+ inventoryNewRow[(int)InventoryTableColumns.IsAdSpecialMember] = false;
+ }
+ break;
+ case (int)SalesTableColumns.IsDirty:
+ inventoryNewRow[(int)InventoryTableColumns.IsDirty] = true;
+ break;
+ case (int)SalesTableColumns.IsInDatabase:
+ inventoryNewRow[(int)InventoryTableColumns.IsInDatabase] = false;
+ break;
+ default:
+ if (i > (int)InventoryTableColumns.AdItem && i < (int)InventoryTableColumns.IsHeaderRow || i == (int)InventoryTableColumns.Id)
+ {
+ inventoryNewRow[i] = "";
+ }
+ break;
+ }
+ }
+ inventoryDataGridView.Rows.Add(inventoryNewRow);
+ }
+ else
+ {
+ MessageBox.Show(@"An Ad Item is required.", @"Invalid Ad Item");
+ projectionsDataGridView.Rows[e.RowIndex].Cells[adItemIndex].Selected = true;
+ e.Cancel = true;
+ }
+ }
+
+ private void ActualSalesRowRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
+ {
+ var dataGridView = ((DataGridView)sender);
+ //Provide protection against overflows
+ if ((e.RowIndex + 1) > dataGridView.Rows.Count)
+ {
+ return;
+ }
+ //Disable all row removing events from the other two tables to prevent interference.
+ projectionsDataGridView.UserDeletingRow -= UpdateUsedAdItemCollectionOnRowRemoving;
+ projectionsDataGridView.RowsRemoved -= ProjectionRowRemoved;
+
+ inventoryDataGridView.UserDeletingRow -= UpdateUsedAdItemCollectionOnRowRemoving;
+ inventoryDataGridView.RowsRemoved -= InventoryRowRemoved;
+
+ //IF the row count on the passed DataGridView is less then the other table's row count...
+ if (actualSalesDataGridView.RowCount <= projectionsDataGridView.RowCount && actualSalesDataGridView.RowCount <= inventoryDataGridView.RowCount)
+ {
+ //... it is lower so its safe to assume that both tables have the same row that can be removed.
+ if (!projectionsDataGridView.Rows[e.RowIndex].IsNewRow)
+ {
+ projectionsDataGridView.Rows.RemoveAt(e.RowIndex);
+ }
+
+ if (!inventoryDataGridView.Rows[e.RowIndex].IsNewRow)
+ {
+ inventoryDataGridView.Rows.RemoveAt(e.RowIndex);
+ }
+ }
+ //ELSE IF the row count is larger then the other table's row count...
+ else
+ {
+ //... Log the error and then what?
+ //TODO: Figure out if this is an error condition.
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "The Actual Sales table has more rows then the Projections table.");
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "Projections Row Count: " + projectionsDataGridView.RowCount);
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "Inventory Row Count: " + inventoryDataGridView.RowCount);
+ LogConsole.WriteToLog(FrmLogConsole.Level.Error, "Actual Sales Row Count: " + actualSalesDataGridView.RowCount);
+ errorLabel.Text = @"Error removing rows from Actual Sales and Inventory.";
+ }
+ //... After all the row removal has been finished re-enable the row removal events.
+ projectionsDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
+ projectionsDataGridView.RowsRemoved += ProjectionRowRemoved;
+
+ inventoryDataGridView.UserDeletingRow += UpdateUsedAdItemCollectionOnRowRemoving;
+ inventoryDataGridView.RowsRemoved += InventoryRowRemoved;
+
+ //Reset the row numbers in the tables.
+ for (var i = e.RowIndex; i < (dataGridView.RowCount); i++)
+ {
+ projectionsDataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
+ inventoryDataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
+ actualSalesDataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
+ }
+ //Refresh the DataGridViews so the header cell's number get repainted properly and repaint the rows in case any groups get messed up during row removal.
+ projectionsDataGridView.RefreshEdit();
+ inventoryDataGridView.RefreshEdit();
+ actualSalesDataGridView.RefreshEdit();
+ _tableHelperFunctions.PaintRowGroups(dataGridView);
+ }
+
+ #endregion
+
+ #region DataGridView Construction Functions
+
+ ///
+ /// Fills the APC DataGridViews with the appropriate columns and starting row for the user to start
+ /// entering data.
+ ///
+ private void ConstructApcDataGridViews()
+ {
+ //Construct a list of column names for the projections/actual sales DataGridViews and the inventory DataGirdView.
+ string[] saleColumnNames =
+ {
+ "ID", "AdItem", "Sold", "SalePrice", "TotalSales", "Cost", "ProfitReturn",
+ "TotalProfitReturn", "IsHeader", "IsMember", "IsAdSpecialRow", "IsAdSpecialMember", "IsDirty", "IsInDatabase"
+ };
+ string[] inventoryColumnNames =
+ {
+ "ID", "AdItem", "BeginningInventory", "Received", "Total", "EndingInventory", "IsHeader", "IsMember", "IsAdSpecialRow", "IsAdSpecialMember", "IsDirty", "IsInDatabase"
+ };
+
+ foreach (var name in saleColumnNames)
+ {
+ if (!name.StartsWith("Is"))
+ {
+ var column = new DataGridViewTextBoxColumn
+ {
+ Name = name,
+ HeaderText = TextFormat.AddSpacesToSentence(name, false),
+ ValueType = typeof(string),
+ SortMode = DataGridViewColumnSortMode.NotSortable,
+ MaxInputLength = 20
+ };
+ if (name.Contains("ID"))
+ {
+ //column.Visible = false;
+ }
+ projectionsDataGridView.Columns.Add(column);
+ }
+ else
+ {
+ var column = new DataGridViewCheckBoxColumn
+ {
+ Name = name,
+ HeaderText = TextFormat.AddSpacesToSentence(name, false),
+ ValueType = typeof(bool),
+ //Visible = false,
+ SortMode = DataGridViewColumnSortMode.NotSortable
+ };
+ projectionsDataGridView.Columns.Add(column);
+ }
+ }
+ //Add the columns into the inventory DataGridView after setting their types.
+ foreach (var name in inventoryColumnNames)
+ {
+ if (!name.StartsWith("Is"))
+ {
+ var column = new DataGridViewTextBoxColumn
+ {
+ Name = name,
+ HeaderText = TextFormat.AddSpacesToSentence(name, false),
+ ValueType = typeof(string),
+ SortMode = DataGridViewColumnSortMode.NotSortable,
+ MaxInputLength = 20
+ };
+ inventoryDataGridView.Columns.Add(column);
+ }
+ else
+ {
+ var column = new DataGridViewCheckBoxColumn
+ {
+ Name = name,
+ HeaderText = TextFormat.AddSpacesToSentence(name, false),
+ ValueType = typeof(bool),
+ //Visible = false,
+ SortMode = DataGridViewColumnSortMode.NotSortable
+ };
+ inventoryDataGridView.Columns.Add(column);
+ }
+ }
+ //
+ foreach (var name in saleColumnNames)
+ {
+ if (!name.StartsWith("Is"))
+ {
+ var column = new DataGridViewTextBoxColumn
+ {
+ Name = name,
+ HeaderText = TextFormat.AddSpacesToSentence(name, false),
+ ValueType = typeof(string),
+ SortMode = DataGridViewColumnSortMode.NotSortable,
+ MaxInputLength = 20
+ };
+ actualSalesDataGridView.Columns.Add(column);
+ }
+ else
+ {
+ var column = new DataGridViewCheckBoxColumn
+ {
+ Name = name,
+ HeaderText = TextFormat.AddSpacesToSentence(name, false),
+ ValueType = typeof(bool),
+ //Visible = false,
+ SortMode = DataGridViewColumnSortMode.NotSortable
+ };
+ actualSalesDataGridView.Columns.Add(column);
+ }
+ }
+ }
+
+ ///
+ /// Constructs the invoices DataGridView.
+ ///
+ private void ConstructInvoicesDataGridView()
+ {
+ string[] invoicesColumnNames = { "InvoiceDate", "Supplier", "InvoiceNumber", "InvoiceNetAmountAtCost", "InvoiceNetAmount", "InvoiceNote", "IsDirty", "IsInDatabase"};
+
+ foreach (var name in invoicesColumnNames)
+ {
+ var column = new DataGridViewColumn { Name = name };
+ if (!name.StartsWith("Is"))
+ {
+ column.HeaderText = TextFormat.AddSpacesToSentence(name, false);
+ column.ValueType = typeof(string);
+ }
+ else
+ {
+ column.HeaderText = TextFormat.AddSpacesToSentence(name, false);
+ column.Visible = false;
+ column.ValueType = typeof(bool);
+ }
+ column.CellTemplate = new DataGridViewTextBoxCell();
+ invoicesDataGridView.Columns.Add(column);
+ }
+ }
+
+ #endregion
+
#region Comments TextBox Events
///
- /// Event Used: KeyUp
- /// Calculates and displays the remaining number of characters left available for the user to enter,
+ /// Event Used: TextChanged
+ /// Calculates and displays the remaining number of characters 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.
+ //If the amount of characters left is less then 20% (or 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
+ #region DateTime Events
///
/// Updates the week ending masked text box with the selected date
/// using the format (MM/DD/YYYY).
@@ -201,16 +1529,721 @@ namespace AdvertsingProfitControl
weekEndingMaskedTextBoxInstructionLabel.Text = @"... or manually enter it here:";
errorLabel.Text = "";
}
+
weekEndingMaskedTextBox.Text = selectedDate.ToString("MM-dd-yyyy");
}
#endregion
- #region Data Grid View Construction Functions
+ private void getCellValueDebugMainMenu_Click(object sender, EventArgs e)
+ {
+ var dataGridView = (DataGridView)mainTabControl.TabPages[0].Controls[0];
+ MessageBox.Show(dataGridView.CurrentRow.DefaultCellStyle.BackColor.Name);
+ }
+ private void AddRecordsButtonClick(object sender, EventArgs e)
+ {
+ //Make sure the mask in the text box is completed.
+ if (!weekEndingMaskedTextBox.MaskCompleted)
+ {
+ MessageBox.Show(@"A valid date must be specified.", @"Invalid Date", MessageBoxButtons.OK,
+ MessageBoxIcon.Error);
+ return;
+ }
+ //Create the database interaction objects.
+ var dbT = new DatabaseTracker();
+ var dbW = new DatabaseWriter(dbT.DatabaseConnectionString);
+ var dbR = new DatabaseReader();
+ DateTime dateTime;
+ //Attempt to parse the date entered to verify it's integrity.
+ if (DateTime.TryParseExact(weekEndingMaskedTextBox.Text, "MM/dd/yyyy", CultureInfo.InvariantCulture,
+ DateTimeStyles.None, out dateTime))
+ {
+ //Check to see if the date is before the store was even founded, though I think a date range starting at 2014 would work but eh.
+ if (dateTime.Year < 1958)
+ {
+ var result =
+ MessageBox.Show(
+ @"Fairly certain Allen's wasn't even founded at this time... Maybe try another date or year at least?",
+ @"Let Alone Used Computers This Fast", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
+ if (result == DialogResult.Yes)
+ {
+ weekEndingMaskedTextBox.Focus();
+ return;
+ }
+ MessageBox.Show(@"Alright if you insist since technically this date is valid.",
+ @"Technically Correct Is The Best Correct", MessageBoxButtons.OK);
+ }
+ }
+ else
+ {
+ MessageBox.Show(@"The date " + weekEndingMaskedTextBox.Text + @" is an invalid date.", @"Invalid Date", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ //Obtain the date ID.
+ int dateId;
+ if (
+ int.TryParse(dbR.RetrieveDateIdByDateString(dateTime.ToString("MM/dd/yyyy"),
+ dbT.DatabaseConnectionString), out dateId))
+ {
+ //If the ID is zero (0) that means the date isn't in the database so simply insert it.
+ if (dateId == 0)
+ {
+ //Try inserting the date string.
+ if (dbW.InsertIntoWeekEnding(dateTime.ToString("MM/dd/yyyy")))
+ {
+ if (
+ int.TryParse(
+ dbR.RetrieveDateIdByDateString(dateTime.ToString("MM/dd/yyyy"),
+ dbT.DatabaseConnectionString), out dateId))
+ {
+ //Now if its still zero (0) then that means something went really wrong and failed to insert.
+ if (dateId == 0)
+ {
+ MessageBox.Show(
+ @"Failed to retrieve date ID after supposedly inserting the date into the database.",
+ @"Failed To Get Date ID", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ }
+ else
+ {
+ MessageBox.Show(
+ @"You really should not be able to see this message. If you are well that means something really weird happened converting text into a number, that is hard-coded to not fail on conversion. Either way I couldn't get the date ID due to some error, check the logs if you're curious.",
+ @"Well This Is Awkwardly Nested...", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ }
+ else
+ {
+ //The above method reports that it failed to insert the date into the database.
+ MessageBox.Show(@"Failed insert the date " + weekEndingMaskedTextBox.Text + @" into the database.", @"Failed To Get Date ID", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ }
+ }
+ else
+ {
+ //Seriously don't think this will happen, but eh might as well.
+ MessageBox.Show(
+ @"You really should not be able to see this message. If you are well that means something really weird happened converting text into a number, that is hard-coded to not fail on conversion. Either way I couldn't get the date ID due to some error, check the logs if you're curious.",
+ @"Well This Is Awkward...", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ //Run the row parsing engine on all the APC tables.
+ //Create the cleaned table objects that will be sent to the database.
+ var trimmedProjectionsTable = ConstructCleanedProjectionsTable(dateId);
+ //var trimmedInventoryTable = ConstructCleanedInventoryTable(dateId);
+ //var trimmedActualSalesTable = ConstructCleanedActualSalesTable(dateId);
+ //Create the transaction scope.
+ //By default the TransactionScopeOption is "Required", so if an ambient transaction does not
+ //exist then the new transaction that is made (in the first method) becomes the root transaction.
+ //Transaction Scope: https://msdn.microsoft.com/en-us/library/ms172152.aspx
+ var projectionsAdditions = dbW.InsertIntoSalesTable(trimmedProjectionsTable.ElementAt(0), dbT.DatabaseConnectionString);
+ foreach (var rowIndex in projectionsAdditions)
+ {
+ projectionsDataGridView.Rows[rowIndex.Key - 1].Cells[(int) SalesTableColumns.Id].Value = rowIndex.Value;
+ projectionsDataGridView.Rows[rowIndex.Key - 1].Cells[(int)SalesTableColumns.IsDirty].Value = false;
+ projectionsDataGridView.Rows[rowIndex.Key - 1].Cells[(int)SalesTableColumns.IsInDatabase].Value = true;
+ }
+ //dbW.UpdateSalesTable(trimmedProjectionsTable.ElementAt(1), dbT.DatabaseConnectionString);
+ }
+ #region APC Table Trimming
+
+ private IEnumerable ConstructCleanedProjectionsTable(int dateId)
+ {
+ //Create two DataTables one for the new items to be added to the database
+ //and one for items that have to be updated.
+ //New Sales Table Layout (Based on the Database's Physical Layout)
+ //0:Sold 1:SalePrice 2:TotalSales 3:cost 4:ProfitReturn 5:TotalProfitReturn
+ //6:FK_AdItemID 7:RowAttribute 8:FK_AdSpecialGroupName (ID) 9:RowPosition (not index based)
+ //10:FK_DateID
+ var trimmedNewProjectionsTable = new DataTable("Projections");
+ //Update Sales Table Layout (Based on the Database's Physical Layout)
+ //0:ID 1:Sold 2:SalePrice 3:TotalSales 4:cost 5:ProfitReturn 6:TotalProfitReturn
+ //7:FK_AdItemID 8:RowAttribute 9:FK_AdSpecialGroupName (ID) 10:RowPosition (not index based)
+ //11:FK_DateID
+ var trimmedUpdateProjectionsTable = new DataTable("Projections");
+ DataTable[] trimmedTables = { trimmedNewProjectionsTable, trimmedUpdateProjectionsTable };
+ //Construct a list of column names for the projections/actual sales DataGridViews and the inventory DataGirdView.
+ string[] saleColumnNames =
+ {
+ "ID", "Sold", "SalePrice", "TotalSales", "Cost", "ProfitReturn",
+ "TotalProfitReturn", "AdItemID", "RowAttribute", "AdSpecialID", "RowPosition", "DateID"
+ };
+ foreach (var columnName in saleColumnNames)
+ {
+ if (columnName == "ID") continue;
+ var column = new DataColumn(columnName);
+ trimmedTables[0].Columns.Add(column);
+ }
+ foreach (var columnName in saleColumnNames)
+ {
+ var column = new DataColumn(columnName);
+ trimmedTables[1].Columns.Add(column);
+ }
+ //Create the database interaction objects.
+ var databaseTracker = new DatabaseTracker();
+ var databaseReader = new DatabaseReader();
+ var databaseWriter = new DatabaseWriter(databaseTracker.DatabaseConnectionString);
+ var adSpecialId = 0; //Entries in the database are not allowed to be zero (unique ID wise that is).
+ //Dictionary The table ID is zero (0) for the new table and one (1) for the update table.
+ var usedAdItems = new Dictionary(); //Contains ad items that are used in section one, used for checking for repeats.
+ //Grab the ad special ID, assuming there is one.
+ if (_adSpecialIndex != -1)
+ {
+ //An ad special does exist so grab its ID from the database.
+ int.TryParse(databaseReader.RetrieveGroupIdByString(
+ projectionsDataGridView.Rows[_adSpecialIndex].Cells[(int)SalesTableColumns.AdItem]
+ .EditedFormattedValue.ToString(), databaseTracker.DatabaseConnectionString), out adSpecialId);
+ }
+ //Begin spinning through all the rows in the projections table.
+ foreach (DataGridViewRow row in projectionsDataGridView.Rows)
+ {
+ //Always check for new row.
+ if (row.IsNewRow) break;
+ //Check to see if the current row is the ad special row.
+ if (row.Index == _adSpecialIndex)
+ {
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Ad Special Row found at index " + row.Index + ".");
+ continue;
+ }
+ //Check to see if the row is dirty.
+ if (!(bool)row.Cells[(int)SalesTableColumns.IsDirty].Value)
+ {
+ //If it is not then continue on to the next row.
+ continue;
+ }
+ //Try grabbing the row's ID number (the number that it is in the database).
+ var rowIdNumber = row.Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString() == "" ? 0 : int.Parse(row.Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString());
+ //Grab the ad item ID.
+ var adItemId = int.Parse(databaseReader.RetrieveAdItemId(row.Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue.ToString(), databaseTracker.DatabaseConnectionString));
+ //If the return value is zero (0) then the ad item is not in the database so try to add it.
+ if (adItemId == 0)
+ {
+ //Add the item to the database.
+ adItemId = databaseWriter.InsertNewAdItem(row.Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue.ToString());
+ if (adItemId == 0)
+ {
+ errorLabel.Text = @"Failed to insert new ad item.";
+ //TODO: Throw an exception, this can not be allowed.
+ //AdItemInsertionFailedException
+ trimmedTables[0].Rows.Clear(); //Work around for now
+ trimmedTables[1].Rows.Clear();
+ //throw new InvalidOperationException("Failed to add ad item.");
+ //break;
+ }
+ }
+ int tableIndex;
+ //Check for repeated ad items in the ad special section
+ if (usedAdItems.TryGetValue(adItemId, out tableIndex))
+ {
+ //If the ad item is being used in section one then locate it and update it in the trimmed table.
+ var foundRow = trimmedTables[tableIndex].Select("AdItemID = '" + adItemId + "'");
+ if (foundRow.Length == 1)
+ {
+ LogConsole.WriteToLog(FrmLogConsole.Level.Info,
+ "Ad item '" + row.Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue +
+ "' found in the trimmed table.");
+ }
+ else
+ {
+ //TODO: Throw an exception, this can not be allowed.
+ //InvalidTrimmedRowCountException
+ trimmedTables[0].Rows.Clear(); //Work around for now
+ trimmedTables[1].Rows.Clear();
+ break;
+ }
+ //Begin spinning through all the rows to find the one selected above.
+ for (var i = 0; i < trimmedTables[tableIndex].Rows.Count; i++)
+ {
+ //Check to see if the selected row is equal.
+ if (foundRow[0] != trimmedTables[tableIndex].Rows[i]) continue;
+ //If so then update that row index with the group ID number.
+ if (tableIndex == 0)
+ {
+ trimmedTables[0].Rows[i][8] = adSpecialId;
+ }
+ else
+ {
+ trimmedTables[1].Rows[i][9] = adSpecialId;
+ }
+ }
+ //Once ad special ID has been updated jump to the next row.
+ continue;
+ }
+ //Determine the row's attribute.
+ var rowAttribute = 0; //Zero (0) means no grouping, its not a header nor a member.
+ if ((bool)row.Cells[(int)SalesTableColumns.IsHeaderRow].Value && !(bool)row.Cells[(int)SalesTableColumns.IsMemberRow].Value)
+ {
+ rowAttribute = 1;
+ }
+ else if ((bool)row.Cells[(int)SalesTableColumns.IsMemberRow].Value && !(bool)row.Cells[(int)SalesTableColumns.IsHeaderRow].Value)
+ {
+ rowAttribute = 2;
+ }
+ //Since we've made it this far, add the ad item into the dictionary if we're not in the ad special group.
+ if (_adSpecialIndex != -1 && row.Index > _adSpecialIndex)
+ {
+ usedAdItems.Add(row.Index, adItemId);
+ }
+ //Add the values to their respective data table.
+ if (rowIdNumber == 0)
+ {
+ //This table is full of data not in the database so the ID column isn't needed.
+ var newRow = new object[11];
+ newRow[0] = row.Cells[(int)SalesTableColumns.Sold].EditedFormattedValue.ToString();//Sold, is string
+ newRow[1] = row.Cells[(int)SalesTableColumns.SalePrice].EditedFormattedValue.ToString();//SalePrice, is string
+ newRow[2] = row.Cells[(int)SalesTableColumns.TotalSales].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.TotalSales].EditedFormattedValue.ToString());//TotalSales, must be a number
+ newRow[3] = row.Cells[(int)SalesTableColumns.Cost].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.Cost].EditedFormattedValue.ToString());//Cost, must be a number
+ newRow[4] = row.Cells[(int)SalesTableColumns.ProfitReturn].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.ProfitReturn].EditedFormattedValue.ToString());//ProfitReturn, must be a number
+ newRow[5] = row.Cells[(int)SalesTableColumns.TotalProfitReturn].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.TotalProfitReturn].EditedFormattedValue.ToString());//TotalProfitReturn, must be a number
+ newRow[6] = adItemId;
+ newRow[7] = rowAttribute;
+ if (_adSpecialIndex != -1 && row.Index > _adSpecialIndex)
+ {
+ newRow[8] = adSpecialId;
+ newRow[9] = row.Index; //"Subtract" one since we don't need to acknowledge the Ad Special Row's existence.
+ }
+ else
+ {
+ newRow[8] = 0;
+ newRow[9] = row.Index + 1;
+ }
+ newRow[10] = dateId;
+ trimmedTables[0].Rows.Add(newRow);
+ usedAdItems.Add(adItemId, 0);
+ }
+ else
+ {
+ //This table is full of data that is already in the database.
+ var newRow = new object[12];
+ newRow[0] = rowIdNumber;
+ newRow[1] = row.Cells[(int)SalesTableColumns.Sold].EditedFormattedValue.ToString();//Sold, is string
+ newRow[2] = row.Cells[(int)SalesTableColumns.SalePrice].EditedFormattedValue.ToString();//SalePrice, is string
+ newRow[3] = row.Cells[(int)SalesTableColumns.TotalSales].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.TotalSales].EditedFormattedValue.ToString());//TotalSales, must be a number
+ newRow[4] = row.Cells[(int)SalesTableColumns.Cost].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.Cost].EditedFormattedValue.ToString());//Cost, must be a number
+ newRow[5] = row.Cells[(int)SalesTableColumns.ProfitReturn].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.ProfitReturn].EditedFormattedValue.ToString());//ProfitReturn, must be a number
+ newRow[6] = row.Cells[(int)SalesTableColumns.TotalProfitReturn].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.TotalProfitReturn].EditedFormattedValue.ToString());//TotalProfitReturn, must be a number
+ newRow[7] = adItemId;
+ newRow[8] = rowAttribute;
+ if (_adSpecialIndex != -1 && row.Index > _adSpecialIndex)
+ {
+ newRow[9] = adSpecialId;
+ newRow[10] = row.Index; //"Subtract" one since we don't need to acknowledge the Ad Special Row's existence.
+ }
+ else
+ {
+ newRow[9] = 0;
+ newRow[10] = row.Index + 1;
+ }
+ newRow[11] = dateId;
+ trimmedTables[1].Rows.Add(newRow);
+ usedAdItems.Add(adItemId, 1);
+ }
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Row Dump for row number " + (row.Index + 1) + ".");
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "ID : " + rowIdNumber + " Sold: " + row.Cells[(int)SalesTableColumns.Sold].EditedFormattedValue);
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Sale Price : " + row.Cells[(int)SalesTableColumns.SalePrice].EditedFormattedValue + " Total Sales: " + row.Cells[(int)SalesTableColumns.TotalSales].EditedFormattedValue);
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Cost: " + row.Cells[(int)SalesTableColumns.Cost].EditedFormattedValue + " Profit Return: " + row.Cells[(int)SalesTableColumns.ProfitReturn].EditedFormattedValue);
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Total Profit Return: " + row.Cells[(int)SalesTableColumns.TotalProfitReturn].EditedFormattedValue + " Ad Item ID: " + adItemId);
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Row Attribute: " + rowAttribute + " Ad Special ID: " + adSpecialId);
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Row Position: " + row.Index + (_adSpecialIndex != -1 && row.Index > _adSpecialIndex ? 1 : 0) + " Date ID: " + dateId);
+ }
+
+ return trimmedTables;
+ }
+
+ private IEnumerable ConstructCleanedInventoryTable(int dateId)
+ {
+ //Create two DataTables one for the new items to be added to the database
+ //and one for items that have to be updated.
+ //New Sales Table Layout (Based on the Database's Physical Layout)
+ //0:BeginingInventory 1:Received 2:TotalInventory 3:EndingInventory 4:AdItemID 5:RowAttribute
+ //6:FK_AdSpecialGroupName (ID) 7:RowPosition (not index based) 8:DateID
+ var trimmedNewInventoryTable = new DataTable("Inventory");
+ //Update Sales Table Layout (Based on the Database's Physical Layout)
+ //0:ID 1:BeginingInventory 2:Received 3:TotalInventory 4:EndingInventory 5:AdItemID 6:RowAttribute
+ //7:FK_AdSpecialGroupName (ID) 8:RowPosition (not index based) 9:DateID
+ var trimmedUpdateInventoryTable = new DataTable("Inventory");
+ DataTable[] trimmedTables = { trimmedNewInventoryTable, trimmedUpdateInventoryTable };
+ //Construct a list of column names for the projections/actual sales DataGridViews and the inventory DataGirdView.
+ string[] saleColumnNames =
+ {
+ "ID", "BeginingInventory", "Received", "TotalInventory", "EndingInventory", "AdItemID", "RowAttribute", "AdSpecialID", "RowPosition", "DateID"
+ };
+ foreach (var columnName in saleColumnNames)
+ {
+ if (columnName == "ID") continue;
+ var column = new DataColumn(columnName);
+ trimmedTables[0].Columns.Add(column);
+ }
+ foreach (var columnName in saleColumnNames)
+ {
+ var column = new DataColumn(columnName);
+ trimmedTables[1].Columns.Add(column);
+ }
+ //Create the database interaction objects.
+ var databaseTracker = new DatabaseTracker();
+ var databaseReader = new DatabaseReader();
+ var databaseWriter = new DatabaseWriter(databaseTracker.DatabaseConnectionString);
+ var adSpecialId = 0; //Entries in the database are not allowed to be zero (unique ID wise that is).
+ //Dictionary The table ID is zero (0) for the new table and one (1) for the update table.
+ var usedAdItems = new Dictionary(); //Contains ad items that are used in section one, used for checking for repeats.
+ //Grab the ad special ID, assuming there is one.
+ if (_adSpecialIndex != -1)
+ {
+ //An ad special does exist so grab its ID from the database.
+ int.TryParse(databaseReader.RetrieveGroupIdByString(
+ inventoryDataGridView.Rows[_adSpecialIndex].Cells[(int)InventoryTableColumns.AdItem]
+ .EditedFormattedValue.ToString(), databaseTracker.DatabaseConnectionString), out adSpecialId);
+ }
+ //Begin spinning through all the rows in the projections table.
+ foreach (DataGridViewRow row in inventoryDataGridView.Rows)
+ {
+ //Always check for new row.
+ if (row.IsNewRow) break;
+ //Check to see if the current row is the ad special row.
+ if (row.Index == _adSpecialIndex)
+ {
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Ad Special Row found at index " + row.Index + ".");
+ continue;
+ }
+ //Check to see if the row is not dirty.
+ if (!(bool)row.Cells[(int)InventoryTableColumns.IsDirty].Value)
+ {
+ //If so simply continue.
+ continue;
+ }
+ //Try grabbing the row's ID number (the number that it is in the database).
+ var rowIdNumber = row.Cells[(int)InventoryTableColumns.Id].EditedFormattedValue.ToString() == "" ? 0 : int.Parse(row.Cells[(int)InventoryTableColumns.Id].EditedFormattedValue.ToString());
+ //Grab the ad item ID.
+ var adItemId = int.Parse(databaseReader.RetrieveAdItemId(row.Cells[(int)InventoryTableColumns.AdItem].EditedFormattedValue.ToString(), databaseTracker.DatabaseConnectionString));
+ //If the return value is zero (0) then the ad item is not in the database so try to add it.
+ if (adItemId == 0)
+ {
+ //Add the item to the database.
+ adItemId = databaseWriter.InsertNewAdItem(row.Cells[(int)InventoryTableColumns.AdItem].EditedFormattedValue.ToString());
+ if (adItemId == 0)
+ {
+ errorLabel.Text = @"Failed to insert new ad item.";
+ //TODO: Throw an exception, this can not be allowed.
+ //AdItemInsertionFailedException
+ trimmedTables[0].Rows.Clear(); //Work around for now
+ trimmedTables[1].Rows.Clear();
+ break;
+ }
+ }
+ int tableIndex;
+ //Check for repeated ad items in the ad special section
+ if (usedAdItems.TryGetValue(adItemId, out tableIndex))
+ {
+ //If the ad item is being used in section one then locate it and update it in the trimmed table.
+ var foundRow = trimmedTables[tableIndex].Select("AdItemID = '" + adItemId + "'");
+ if (foundRow.Length == 1)
+ {
+ LogConsole.WriteToLog(FrmLogConsole.Level.Info,
+ "Ad item '" + row.Cells[(int)InventoryTableColumns.AdItem].EditedFormattedValue +
+ "' found in the trimmed table.");
+ }
+ else
+ {
+ //TODO: Throw an exception, this can not be allowed.
+ //InvalidTrimmedRowCountException
+ trimmedTables[0].Rows.Clear(); //Work around for now
+ trimmedTables[1].Rows.Clear();
+ break;
+ }
+ //Begin spinning through all the rows to find the one selected above.
+ for (var i = 0; i < trimmedTables[tableIndex].Rows.Count; i++)
+ {
+ //Check to see if the selected row is equal.
+ if (foundRow[0] != trimmedTables[tableIndex].Rows[i]) continue;
+ //If so then update that row index with the group ID number.
+ if (tableIndex == 0)
+ {
+ trimmedTables[0].Rows[i][8] = adSpecialId;
+ }
+ else
+ {
+ trimmedTables[1].Rows[i][9] = adSpecialId;
+ }
+ }
+ //Once ad special ID has been updated jump to the next row.
+ continue;
+ }
+ //Determine the row's attribute.
+ var rowAttribute = 0; //Zero (0) means no grouping, its not a header nor a member.
+ if ((bool)row.Cells[(int)InventoryTableColumns.IsHeaderRow].Value && !(bool)row.Cells[(int)InventoryTableColumns.IsMemberRow].Value)
+ {
+ rowAttribute = 1;
+ }
+ else if ((bool)row.Cells[(int)InventoryTableColumns.IsMemberRow].Value && !(bool)row.Cells[(int)InventoryTableColumns.IsHeaderRow].Value)
+ {
+ rowAttribute = 2;
+ }
+ //Since we've made it this far, add the ad item into the dictionary if we're not in the ad special group.
+ if (_adSpecialIndex != -1 && row.Index < _adSpecialIndex)
+ {
+ usedAdItems.Add(row.Index, adItemId);
+ }
+ //Add the values to their respective data table.
+ if (rowIdNumber == 0)
+ {
+ //This table is full of data not in the database so the ID column isn't needed.
+ var newRow = new object[11];
+ newRow[0] = row.Cells[(int)InventoryTableColumns.BeginningInventory].EditedFormattedValue.ToString();//Sold, is string
+ newRow[1] = row.Cells[(int)InventoryTableColumns.Recieved].EditedFormattedValue.ToString();//Received, is string
+ newRow[2] = row.Cells[(int)InventoryTableColumns.Total].EditedFormattedValue.ToString();//Total, is string
+ newRow[3] = row.Cells[(int)InventoryTableColumns.EndingInventory].EditedFormattedValue.ToString();//EndingInventory, is string
+ newRow[4] = adItemId;
+ newRow[5] = rowAttribute;
+ if (_adSpecialIndex != -1 && row.Index > _adSpecialIndex)
+ {
+ newRow[6] = adSpecialId;
+ newRow[7] = row.Index; //"Subtract" one since we don't need to acknowledge the Ad Special Row's existence.
+ }
+ else
+ {
+ newRow[6] = 0;
+ newRow[7] = row.Index + 1;
+ }
+ newRow[8] = dateId;
+ trimmedTables[0].Rows.Add(newRow);
+ usedAdItems.Add(adItemId, 0);
+ }
+ else
+ {
+ //This table is full of data that is already in the database.
+ var newRow = new object[12];
+ newRow[0] = rowIdNumber;
+ newRow[1] = row.Cells[(int)InventoryTableColumns.BeginningInventory].EditedFormattedValue.ToString();//Sold, is string
+ newRow[2] = row.Cells[(int)InventoryTableColumns.Recieved].EditedFormattedValue.ToString();//Received, is string
+ newRow[3] = row.Cells[(int)InventoryTableColumns.Total].EditedFormattedValue.ToString();//Total, is string
+ newRow[4] = row.Cells[(int)InventoryTableColumns.EndingInventory].EditedFormattedValue.ToString();//EndingInventory, is string
+ newRow[5] = adItemId;
+ newRow[6] = rowAttribute;
+ if (_adSpecialIndex != -1 && row.Index > _adSpecialIndex)
+ {
+ newRow[7] = adSpecialId;
+ newRow[8] = row.Index; //"Subtract" one since we don't need to acknowledge the Ad Special Row's existence.
+ }
+ else
+ {
+ newRow[7] = 0;
+ newRow[8] = row.Index + 1;
+ }
+ newRow[9] = dateId;
+ trimmedTables[1].Rows.Add(newRow);
+ usedAdItems.Add(adItemId, 1);
+ }
+ }
+
+ return trimmedTables;
+ }
+
+ private IEnumerable ConstructCleanedActualSalesTable(int dateId)
+ {
+ //Create two DataTables one for the new items to be added to the database
+ //and one for items that have to be updated.
+ //New Sales Table Layout (Based on the Database's Physical Layout)
+ //0:Sold 1:SalePrice 2:TotalSales 3:cost 4:ProfitReturn 5:TotalProfitReturn
+ //6:FK_AdItemID 7:RowAttribute 8:FK_AdSpecialGroupName (ID) 9:RowPosition (not index based)
+ //10:FK_DateID
+ var trimmedNewProjectionsTable = new DataTable("ACtualSales");
+ //Update Sales Table Layout (Based on the Database's Physical Layout)
+ //0:ID 1:Sold 2:SalePrice 3:TotalSales 4:cost 5:ProfitReturn 6:TotalProfitReturn
+ //7:FK_AdItemID 8:RowAttribute 9:FK_AdSpecialGroupName (ID) 10:RowPosition (not index based)
+ //11:FK_DateID
+ var trimmedUpdateProjectionsTable = new DataTable("ActualSales");
+ DataTable[] trimmedTables = { trimmedNewProjectionsTable, trimmedUpdateProjectionsTable };
+ //Construct a list of column names for the projections/actual sales DataGridViews and the inventory DataGirdView.
+ string[] saleColumnNames =
+ {
+ "ID", "Sold", "SalePrice", "TotalSales", "Cost", "ProfitReturn",
+ "TotalProfitReturn", "AdItemID", "RowAttribute", "AdSpecialID", "RowPosition", "DateID"
+ };
+ foreach (var columnName in saleColumnNames)
+ {
+ if (columnName == "ID") continue;
+ var column = new DataColumn(columnName);
+ trimmedTables[0].Columns.Add(column);
+ }
+ foreach (var columnName in saleColumnNames)
+ {
+ var column = new DataColumn(columnName);
+ trimmedTables[1].Columns.Add(column);
+ }
+ //Create the database interaction objects.
+ var databaseTracker = new DatabaseTracker();
+ var databaseReader = new DatabaseReader();
+ var databaseWriter = new DatabaseWriter(databaseTracker.DatabaseConnectionString);
+ var adSpecialId = 0; //Entries in the database are not allowed to be zero (unique ID wise that is).
+ //Dictionary The table ID is zero (0) for the new table and one (1) for the update table.
+ var usedAdItems = new Dictionary(); //Contains ad items that are used in section one, used for checking for repeats.
+ //Grab the ad special ID, assuming there is one.
+ if (_adSpecialIndex != -1)
+ {
+ //An ad special does exist so grab its ID from the database.
+ int.TryParse(databaseReader.RetrieveGroupIdByString(
+ projectionsDataGridView.Rows[_adSpecialIndex].Cells[(int)SalesTableColumns.AdItem]
+ .EditedFormattedValue.ToString(), databaseTracker.DatabaseConnectionString), out adSpecialId);
+ }
+ //Begin spinning through all the rows in the projections table.
+ foreach (DataGridViewRow row in actualSalesDataGridView.Rows)
+ {
+ //Always check for new row.
+ if (row.IsNewRow) break;
+ //Check to see if the current row is the ad special row.
+ if (row.Index == _adSpecialIndex)
+ {
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Ad Special Row found at index " + row.Index + ".");
+ continue;
+ }
+ //Check to see if the row is not dirty.
+ if (!(bool)row.Cells[(int)SalesTableColumns.IsDirty].Value)
+ {
+ //If so simply continue.
+ continue;
+ }
+ //Try grabbing the row's ID number (the number that it is in the database).
+ var rowIdNumber = row.Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString() == "" ? 0 : int.Parse(row.Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString());
+ //Grab the ad item ID.
+ var adItemId = int.Parse(databaseReader.RetrieveAdItemId(row.Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue.ToString(), databaseTracker.DatabaseConnectionString));
+ //If the return value is zero (0) then the ad item is not in the database so try to add it.
+ if (adItemId == 0)
+ {
+ //Add the item to the database.
+ adItemId = databaseWriter.InsertNewAdItem(row.Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue.ToString());
+ if (adItemId == 0)
+ {
+ errorLabel.Text = @"Failed to insert new ad item.";
+ //TODO: Throw an exception, this can not be allowed.
+ //AdItemInsertionFailedException
+ trimmedTables[0].Rows.Clear(); //Work around for now
+ trimmedTables[1].Rows.Clear();
+ break;
+ }
+ }
+ int tableIndex;
+ //Check for repeated ad items in the ad special section
+ if (usedAdItems.TryGetValue(adItemId, out tableIndex))
+ {
+ //If the ad item is being used in section one then locate it and update it in the trimmed table.
+ var foundRow = trimmedTables[tableIndex].Select("AdItemID = '" + adItemId + "'");
+ if (foundRow.Length == 1)
+ {
+ LogConsole.WriteToLog(FrmLogConsole.Level.Info,
+ "Ad item '" + row.Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue +
+ "' found in the trimmed table.");
+ }
+ else
+ {
+ //TODO: Throw an exception, this can not be allowed.
+ //InvalidTrimmedRowCountException
+ trimmedTables[0].Rows.Clear(); //Work around for now
+ trimmedTables[1].Rows.Clear();
+ break;
+ }
+ //Begin spinning through all the rows to find the one selected above.
+ for (var i = 0; i < trimmedTables[tableIndex].Rows.Count; i++)
+ {
+ //Check to see if the selected row is equal.
+ if (foundRow[0] != trimmedTables[tableIndex].Rows[i]) continue;
+ //If so then update that row index with the group ID number.
+ if (tableIndex == 0)
+ {
+ trimmedTables[0].Rows[i][8] = adSpecialId;
+ }
+ else
+ {
+ trimmedTables[1].Rows[i][9] = adSpecialId;
+ }
+ }
+ //Once ad special ID has been updated jump to the next row.
+ continue;
+ }
+ //Determine the row's attribute.
+ var rowAttribute = 0; //Zero (0) means no grouping, its not a header nor a member.
+ if ((bool)row.Cells[(int)SalesTableColumns.IsHeaderRow].Value && !(bool)row.Cells[(int)SalesTableColumns.IsMemberRow].Value)
+ {
+ rowAttribute = 1;
+ }
+ else if ((bool)row.Cells[(int)SalesTableColumns.IsMemberRow].Value && !(bool)row.Cells[(int)SalesTableColumns.IsHeaderRow].Value)
+ {
+ rowAttribute = 2;
+ }
+ //Since we've made it this far, add the ad item into the dictionary if we're not in the ad special group.
+ if (_adSpecialIndex != -1 && row.Index < _adSpecialIndex)
+ {
+ usedAdItems.Add(row.Index, adItemId);
+ }
+ //Add the values to their respective data table.
+ if (rowIdNumber == 0)
+ {
+ //This table is full of data not in the database so the ID column isn't needed.
+ var newRow = new object[11];
+ newRow[0] = row.Cells[(int)SalesTableColumns.Sold].EditedFormattedValue.ToString();//Sold, is string
+ newRow[1] = row.Cells[(int)SalesTableColumns.SalePrice].EditedFormattedValue.ToString();//SalePrice, is string
+ newRow[2] = row.Cells[(int)SalesTableColumns.TotalSales].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.TotalSales].EditedFormattedValue.ToString());//TotalSales, must be a number
+ newRow[3] = row.Cells[(int)SalesTableColumns.Cost].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.Cost].EditedFormattedValue.ToString());//Cost, must be a number
+ newRow[4] = row.Cells[(int)SalesTableColumns.ProfitReturn].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.ProfitReturn].EditedFormattedValue.ToString());//ProfitReturn, must be a number
+ newRow[5] = row.Cells[(int)SalesTableColumns.TotalProfitReturn].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.TotalProfitReturn].EditedFormattedValue.ToString());//TotalProfitReturn, must be a number
+ newRow[6] = adItemId;
+ newRow[7] = rowAttribute;
+ if (_adSpecialIndex != -1 && row.Index > _adSpecialIndex)
+ {
+ newRow[8] = adSpecialId;
+ newRow[9] = row.Index; //"Subtract" one since we don't need to acknowledge the Ad Special Row's existence.
+ }
+ else
+ {
+ newRow[8] = 0;
+ newRow[9] = row.Index + 1;
+ }
+ newRow[10] = dateId;
+ trimmedTables[0].Rows.Add(newRow);
+ usedAdItems.Add(adItemId, 0);
+ }
+ else
+ {
+ //This table is full of data that is already in the database.
+ var newRow = new object[12];
+ newRow[0] = rowIdNumber;
+ newRow[1] = row.Cells[(int)SalesTableColumns.Sold].EditedFormattedValue.ToString();//Sold, is string
+ newRow[2] = row.Cells[(int)SalesTableColumns.SalePrice].EditedFormattedValue.ToString();//SalePrice, is string
+ newRow[3] = row.Cells[(int)SalesTableColumns.TotalSales].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.TotalSales].EditedFormattedValue.ToString());//TotalSales, must be a number
+ newRow[4] = row.Cells[(int)SalesTableColumns.Cost].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.Cost].EditedFormattedValue.ToString());//Cost, must be a number
+ newRow[5] = row.Cells[(int)SalesTableColumns.ProfitReturn].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.ProfitReturn].EditedFormattedValue.ToString());//ProfitReturn, must be a number
+ newRow[6] = row.Cells[(int)SalesTableColumns.TotalProfitReturn].EditedFormattedValue.ToString() == "" ? 0 : double.Parse(row.Cells[(int)SalesTableColumns.TotalProfitReturn].EditedFormattedValue.ToString());//TotalProfitReturn, must be a number
+ newRow[7] = adItemId;
+ newRow[8] = rowAttribute;
+ if (_adSpecialIndex != -1 && row.Index > _adSpecialIndex)
+ {
+ newRow[9] = adSpecialId;
+ newRow[10] = row.Index; //"Subtract" one since we don't need to acknowledge the Ad Special Row's existence.
+ }
+ else
+ {
+ newRow[9] = 0;
+ newRow[10] = row.Index + 1;
+ }
+ newRow[11] = dateId;
+ trimmedTables[1].Rows.Add(newRow);
+ usedAdItems.Add(adItemId, 1);
+ }
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Row Dump for row number " + (row.Index + 1) + ".");
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "ID : " + rowIdNumber + " Sold: " + row.Cells[(int)SalesTableColumns.Sold].EditedFormattedValue);
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Sale Price : " + row.Cells[(int)SalesTableColumns.SalePrice].EditedFormattedValue + " Total Sales: " + row.Cells[(int)SalesTableColumns.TotalSales].EditedFormattedValue);
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Cost: " + row.Cells[(int)SalesTableColumns.Cost].EditedFormattedValue + " Profit Return: " + row.Cells[(int)SalesTableColumns.ProfitReturn].EditedFormattedValue);
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Total Profit Return: " + row.Cells[(int)SalesTableColumns.TotalProfitReturn].EditedFormattedValue + " Ad Item ID: " + adItemId);
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Row Attribute: " + rowAttribute + " Ad Special ID: " + adSpecialId);
+ //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Row Position: " + row.Index + (_adSpecialIndex != -1 && row.Index > _adSpecialIndex ? 1 : 0) + " Date ID: " + dateId);
+ }
+
+ return trimmedTables;
+ }
#endregion
-
}
}
diff --git a/AdvertsingProfitControl/RowParsing.cs b/AdvertsingProfitControl/RowParsing.cs
index 522d69d..2db59e7 100644
--- a/AdvertsingProfitControl/RowParsing.cs
+++ b/AdvertsingProfitControl/RowParsing.cs
@@ -8,20 +8,21 @@ namespace AdvertsingProfitControl
{
internal class RowParsing
{
- public static List _adSpecialGroups = new List();
+ public static List AdSpecialGroups = new List();
public string CheckForGroupKeyWord(string cellContents)
{
var keyWord = "NoGroupFound";
- var query = from adI in _adSpecialGroups
+ var query = from adI in AdSpecialGroups
where adI.Equals(cellContents, StringComparison.InvariantCultureIgnoreCase)
select adI;
- if (query.ToArray().Length > 0)
+ var enumerable = query as string[] ?? query.ToArray();
+ if (enumerable.ToArray().Length > 0)
{
//Grab the first object in the array and return it.
- keyWord = query.ToArray().First();
+ keyWord = enumerable.ToArray().First();
}
return keyWord;
@@ -50,6 +51,7 @@ namespace AdvertsingProfitControl
var i = 0;
foreach (DataGridViewCell cell in row.Cells)
{
+ if (cell.ColumnIndex >= (int) SalesTableColumns.IsHeaderRow) { i++; continue;}
//Strip all whitespace characters from the cell, this includes vertical tabs, newlines, and any number of spaces.
var cellContentsStripped = new string(cell.EditedFormattedValue.ToString().Where(c => !char.IsWhiteSpace(c)).ToArray());
//Now remove all zeros, including any decimal points as these values are meaningless.
@@ -60,7 +62,7 @@ namespace AdvertsingProfitControl
rowContents.Add(cell.EditedFormattedValue.ToString());
}
//If the first cell contains nothing, then return as IncompleteRow.
- else if (cellContentsStripped == "" && i == 0)
+ else if (cellContentsStripped == "" && i == (int) SalesTableColumns.AdItem)
{
return RowAttribute.IncompleteRow;
}
diff --git a/AdvertsingProfitControl/TextFormat.cs b/AdvertsingProfitControl/TextFormat.cs
index 403c9bf..fe7afa1 100644
--- a/AdvertsingProfitControl/TextFormat.cs
+++ b/AdvertsingProfitControl/TextFormat.cs
@@ -28,7 +28,6 @@ namespace AdvertsingProfitControl
var isPreviousCharWhiteSpace = false;
var cleanedInputString = "";
var lastnumberStartingIndex = -1;
- var removedCharacterOffset = 0;
//Create an array of brackets to test for, and either balance out or simply ignore the extras.
char[] openBrackets = { '(', '<', '{', '[' };
char[] closedBrackets = { ')', '>', '}', ']' };
@@ -47,7 +46,6 @@ namespace AdvertsingProfitControl
if (isPreviousCharWhiteSpace)
{
//If more then one space is found to be in a row, then ignore it and move onto the next character.
- removedCharacterOffset++;
continue;
}
//IF the current character is whitespace, then mark it and move onto the next loop.
@@ -62,7 +60,6 @@ namespace AdvertsingProfitControl
if (isInsideBrackets)
{
//If we are already inside of brackets then don't add anymore to the string just continue.
- removedCharacterOffset++;
continue;
}
isInsideBrackets = true;
@@ -76,7 +73,6 @@ namespace AdvertsingProfitControl
//IF we're not inside brackets then there is an imbalance so discard this parenthesis.
if (!isInsideBrackets)
{
- removedCharacterOffset++;
continue;
}
//Just gonna force parenthesis for now.
@@ -85,19 +81,19 @@ namespace AdvertsingProfitControl
//Clear the current working word.
isInsideBrackets = false;
continue;
- }
+ }
//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.
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.
- if (char.IsNumber(cleanedInputString[currentCharacter - (2 + removedCharacterOffset)]))
+ if (char.IsNumber(cleanedInputString[cleanedInputString.Length - 2]))
{
BuildAbbreviationsAndWordsLists(adItemText, currentCharacter, out abbreviations, out words);
//Remove the last space if there are any abbreviations or words found.
if (abbreviations.Count > 0 || words.Count > 0)
{
- cleanedInputString = cleanedInputString.Remove(currentCharacter - (1 + removedCharacterOffset), 1);
+ cleanedInputString = cleanedInputString.Remove(cleanedInputString.Length - 1, 1);
}
//Begin checking to see how to place these items back into the final string.
if (abbreviations.Count >= 1 && words.Count == 0)
@@ -143,7 +139,7 @@ namespace AdvertsingProfitControl
else if (!char.IsNumber(adItemText[currentCharacter]) && char.IsLetter(adItemText[currentCharacter]))
{
//IF the previous character is a number...
- if (char.IsNumber(cleanedInputString[currentCharacter - (1 + removedCharacterOffset)]))
+ if (char.IsNumber(cleanedInputString[cleanedInputString.Length - 1]))
{
//Check to see the length of the string and determine if the word with the number needs to be capitalized.
BuildAbbreviationsAndWordsLists(adItemText, currentCharacter, out abbreviations, out words);
@@ -183,7 +179,7 @@ namespace AdvertsingProfitControl
break;
}
}
- else if (char.IsLetter(adItemText[currentCharacter - 1]))
+ else if (char.IsLetter(adItemText[currentCharacter - 1]) || adItemText[currentCharacter - 1] == '\'')
{
cleanedInputString += char.ToLowerInvariant(adItemText[currentCharacter]);
}
@@ -191,10 +187,20 @@ namespace AdvertsingProfitControl
//IF a number is found, and we're not inside brackets, check to see if there is an opening parenthesis and if there aren't create one.
if (char.IsNumber(adItemText[currentCharacter]))
{
+ cleanedInputString += adItemText[currentCharacter];
if (lastnumberStartingIndex == -1)
{
- lastnumberStartingIndex = currentCharacter - removedCharacterOffset;
+ lastnumberStartingIndex = cleanedInputString.Length - 1; //Non-index based system, minus one for the index
}
+ }
+ //Check for any allowed punctuation.
+ if (adItemText[currentCharacter] == '\'')
+ {
+ cleanedInputString += adItemText[currentCharacter];
+ }
+ //Check if the previous character is an "'".
+ else if (cleanedInputString[cleanedInputString.Length - 1] == '\'')
+ {
cleanedInputString += adItemText[currentCharacter];
}
//Since whitespace booleans are handled above, set the boolean for white spaces false.
@@ -205,6 +211,7 @@ namespace AdvertsingProfitControl
{
cleanedInputString += ')';
}
+ //removedCharacterOffset++;
}
#if DEBUG
diff --git a/AdvertsingProfitControl/app.manifest b/AdvertsingProfitControl/app.manifest
index ea89d5e..a7cdc6a 100644
--- a/AdvertsingProfitControl/app.manifest
+++ b/AdvertsingProfitControl/app.manifest
@@ -40,7 +40,7 @@
-
+
diff --git a/StringInputParseTester/Form1.cs b/StringInputParseTester/Form1.cs
index 68f5242..ccbe16a 100644
--- a/StringInputParseTester/Form1.cs
+++ b/StringInputParseTester/Form1.cs
@@ -27,13 +27,13 @@ namespace StringInputParseTester
private void ExecuteParserCode(object sender, EventArgs e)
{
var adItemText = inputTextBox.Text.Trim();
+ //var splitInput = inputTextBox.Text.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
var isInsideBrackets = false;
var isPreviousCharWhiteSpace = false;
//preserveAcronyms
var preserveAcronyms = true;
var cleanedInputString = "";
var lastnumberStartingIndex = -1;
- var removedCharacterOffset = 0;
//Create an array of brackets to test for, and either balance out or simply ignore.
char[] openBrackets = {'(', '<', '{', '['};
char[] closedBrackets = {')', '>', '}', ']'};
@@ -52,7 +52,6 @@ namespace StringInputParseTester
if (isPreviousCharWhiteSpace)
{
//If more then one space is found to be in a row, then ignore it and move onto the next character.
- removedCharacterOffset++;
continue;
}
//IF the current character is whitespace, then mark it and move onto the next loop.
@@ -66,7 +65,6 @@ namespace StringInputParseTester
if (isInsideBrackets)
{
//If we are already inside of brackets then don't add anymore to the string just continue.
- removedCharacterOffset++;
continue;
}
isInsideBrackets = true;
@@ -80,7 +78,6 @@ namespace StringInputParseTester
//IF we're not inside brackets then there is an imbalance so discard this parenthesis.
if (!isInsideBrackets)
{
- removedCharacterOffset++;
continue;
}
//Just gonna force parenthesis for now.
@@ -95,7 +92,7 @@ namespace StringInputParseTester
if (!char.IsNumber(adItemText[currentCharacter]) && isPreviousCharWhiteSpace)
{
//Check to see if the character before the whitespace is a number.
- if (char.IsNumber(cleanedInputString[currentCharacter - (2 + removedCharacterOffset)]))
+ if (char.IsNumber(cleanedInputString[cleanedInputString.Length - 2]))
{
var abbreviations = new List();
var words = new List();
@@ -103,7 +100,7 @@ namespace StringInputParseTester
//Remove the last space if there are any abbreviations or words found.
if (abbreviations.Count > 0 || words.Count > 0)
{
- cleanedInputString = cleanedInputString.Remove(currentCharacter - (1 + removedCharacterOffset), 1);
+ cleanedInputString = cleanedInputString.Remove(cleanedInputString.Length - 1, 1);
}
//Begin checking to see how to place these items back into the final string.
if (abbreviations.Count >= 1 && words.Count == 0)
@@ -149,7 +146,7 @@ namespace StringInputParseTester
else if (!char.IsNumber(adItemText[currentCharacter]) && char.IsLetter(adItemText[currentCharacter]))
{
//IF the previous character is a number...
- if (char.IsNumber(cleanedInputString[currentCharacter - (1 + removedCharacterOffset)]))
+ if (char.IsNumber(cleanedInputString[cleanedInputString.Length - 1]))
{
//Check to see the length of the string and determine if the word with the number needs to be capitalized.
var abbreviations = new List();
@@ -199,10 +196,21 @@ namespace StringInputParseTester
//IF a number is found, and we're not inside brackets, check to see if there is an opening parenthesis and if there aren't create one.
if (char.IsNumber(adItemText[currentCharacter]))
{
+
+ cleanedInputString += adItemText[currentCharacter];
if (lastnumberStartingIndex == -1)
{
- lastnumberStartingIndex = currentCharacter - removedCharacterOffset;
+ lastnumberStartingIndex = cleanedInputString.Length - 1; //This is index based.
}
+ }
+ //Check for any allowed punctuation.
+ if (adItemText[currentCharacter] == '\'')
+ {
+ cleanedInputString += adItemText[currentCharacter];
+ }
+ //Check if the previous character is an "'".
+ else if (cleanedInputString[cleanedInputString.Length - 1] == '\'')
+ {
cleanedInputString += adItemText[currentCharacter];
}
//Since whitespace booleans are handled above, set the boolean for white spaces false.
@@ -224,23 +232,23 @@ namespace StringInputParseTester
/// three (3) characters long or being exactly three characters long but having
/// zero (0) vowels.
///
- /// The string to determine whether or not its a word.
+ /// The string to determine whether or not its a word.
///
- private bool IsWord(string stringToCheck)
+ private bool IsWord(string text)
{
- if (string.IsNullOrEmpty(stringToCheck)) return false;
+ if (string.IsNullOrEmpty(text)) return false;
var isWord = true;
//Most abbreviations do not have vowels in them so check to see if the "abbreviation"
//isn't just a short word like "Box", as opposed to "lbs".
char[] vowels = {'a', 'e', 'i', 'o', 'u', 'y'};
//Count the number of vowels the word has.
- var vowelCount = stringToCheck.Count(x => vowels.Contains(x));
+ var vowelCount = text.Count(x => vowels.Contains(x));
//IF the string is exactly three (3) characters long and has more then zero (0) vowels then it is considered a word.
- if (stringToCheck.Length == 3 && vowelCount == 0)
+ if (text.Length == 3 && vowelCount == 0)
{
isWord = false;
}
- else if (stringToCheck.Length < 3)
+ else if (text.Length < 3)
{
isWord = false;
}
@@ -307,5 +315,25 @@ namespace StringInputParseTester
words[i] = CapitalizeFirstLetter(words[i]);
}
}
+
+ public string FormatShit(string inputString)
+ {
+ var finalString = "";
+ var workingText = "";
+ //The (char[])null avoids creating a new object in memory.
+ var splitInput = inputString.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
+
+ foreach (var text in splitInput)
+ {
+ //Clear the working text to start building the next one to test.
+ workingText = "";
+ foreach (var character in text)
+ {
+
+ }
+ }
+
+ return finalString;
+ }
}
}
diff --git a/StringInputParseTester/bin/Debug/StringInputParseTester.exe b/StringInputParseTester/bin/Debug/StringInputParseTester.exe
index 990a17b..94e337d 100644
Binary files a/StringInputParseTester/bin/Debug/StringInputParseTester.exe and b/StringInputParseTester/bin/Debug/StringInputParseTester.exe differ
diff --git a/StringInputParseTester/bin/Debug/StringInputParseTester.pdb b/StringInputParseTester/bin/Debug/StringInputParseTester.pdb
index 26d950e..0815eb9 100644
Binary files a/StringInputParseTester/bin/Debug/StringInputParseTester.pdb and b/StringInputParseTester/bin/Debug/StringInputParseTester.pdb differ
diff --git a/StringInputParseTester/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/StringInputParseTester/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
index fb7932a..82200d1 100644
Binary files a/StringInputParseTester/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache and b/StringInputParseTester/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ
diff --git a/StringInputParseTester/obj/Debug/StringInputParseTester.exe b/StringInputParseTester/obj/Debug/StringInputParseTester.exe
index 990a17b..94e337d 100644
Binary files a/StringInputParseTester/obj/Debug/StringInputParseTester.exe and b/StringInputParseTester/obj/Debug/StringInputParseTester.exe differ
diff --git a/StringInputParseTester/obj/Debug/StringInputParseTester.pdb b/StringInputParseTester/obj/Debug/StringInputParseTester.pdb
index 26d950e..0815eb9 100644
Binary files a/StringInputParseTester/obj/Debug/StringInputParseTester.pdb and b/StringInputParseTester/obj/Debug/StringInputParseTester.pdb differ