public List <ColumnValueCounter> GetUsedColumns(TextReplacementOptions processedCommand, List <ColumnValueCounter> allColumns) { List <ColumnValueCounter> usedColumns = new List <ColumnValueCounter>(); for (int i = 0; i < allColumns.Count; i++) { if (processedCommand.columnNames.Contains(allColumns[i].columnName.ToLower()) || processedCommand.columnNames.Contains(allColumns[i].columnName) || processedCommand.columnNames.Contains(allColumns[i].abbreviatedRepresentation)) { usedColumns.Add(allColumns[i]); } } return(usedColumns); }
/// <summary> /// Takes a command provided by the user in the word document, parses it into a TextReplacementOptions object, and executes that command based on the user-provided parameters. /// </summary> /// <param name="rawCommand">The exact text provided by the user in the document command</param> /// <param name="columnValueCounters">List of objects that contain information about each column</param> private void ProcessDocumentCommand(string rawCommand, Word.Application wordApp, List <ColumnValueCounter> columnValueCounters) { //Remove any extraneous braces string command = rawCommand.Trim('{', '}'); TextReplacementOptions processedCommand = new TextReplacementOptions(); //Parse the raw command to get a textReplacementOptions object that stores more usable command options. try { processedCommand = GetTextReplacementOptions(command); } catch (Exception e) { MessageBox.Show(new Form { TopMost = true }, "Error: " + e.Message); wordApp.Quit(); Environment.Exit(1); } //if the command was a declaration of the color pallette used in the document, just remove the text and do not execute anything. if (processedCommand.isColors) { ReplaceTextWithText(rawCommand, "", wordApp); return; } else if (processedCommand.isOrder) { _graphColumnOrder = processedCommand.order; ReplaceTextWithText(rawCommand, "", wordApp); return; } //A list of the columns that we actually use for this command. DocumentCommandExecuter commandExecuter = new DocumentCommandExecuter(ColorPalette, _graphColumnOrder); //Populate a list of columnValueCounters that pertain to the columns that we are actually using for this command. List <ColumnValueCounter> usedColumns = GetUsedColumns(processedCommand, columnValueCounters); //Ensure that all columns in the list of used columns have the same number of unique row values NormalizeColumns(usedColumns); if (processedCommand.hasFailed) { MessageBox.Show(new Form { TopMost = true }, "Command Failed: Check template command syntax"); wordApp.Quit(); Environment.Exit(1); } if (usedColumns.Count == 0) { MessageBox.Show(new Form { TopMost = true }, "No columns found in CSV file for command:\n" + processedCommand.rawInput); wordApp.Quit(); Environment.Exit(1); } //Process the command as a graph if (processedCommand.isGraph) { string replaceWith = commandExecuter.GenerateGraph(usedColumns, Application.StartupPath + "\\tempGraph.PNG", processedCommand, wordApp); ReplaceTextWithImage(rawCommand, replaceWith, wordApp); } //Process the command as text replacement else if (processedCommand.isText) { string replaceWith = commandExecuter.GenerateText(usedColumns, processedCommand); ReplaceTextWithText(rawCommand, replaceWith, wordApp); } else { return; } }
/// <summary> /// Parses the command given by the user in the word document template, /// and compiles it into a single TextReplacementOptions struct that can be more easily analyzed later /// The TextReplacementOptions struct defines exactly how the data from the CSV file will be interpretted and processed. /// </summary> public TextReplacementOptions GetTextReplacementOptions(string rawText) { TextReplacementOptions textReplacementOptions = new TextReplacementOptions { rawInput = rawText }; string[] options; string outputType; string outputOption1; List <string> columnNames = new List <string>(); //split the raw command into all of its various components (NOTE: the user command needs to be semicolon seperated) try { options = rawText.Split(';'); outputType = options[0].ToLower(); outputOption1 = options[1].ToLower(); } catch (Exception) { throw new Exception("Error in word document input at:\n" + rawText); } //If the command is a declaration of the color pallette then parse the command as such and generate a color pallette as an array of rgb colors. if (outputType.Contains("colors") || outputType.Contains("colorpalette")) { //Parse the color pallette out of the collor pallette command and set the classwide color pallette to the new one. ParseAndSetColorPallette(options); //Set a flag to tell the rest of the program that this command was just a color pallette declaration textReplacementOptions.isColors = true; return(textReplacementOptions); } //Proccess the command as an 'order' command which specifies the order in which the columns and legend entries will shop up in on the graph. //The position of the columns and legend entries are identical to the position of the items in this 'order' list. if (outputType.Contains("order")) { List <string> order = new List <string>(); //Iterate through the list of items in the command and add them to order List. for (int i = 1; i < options.Length; i++) { order.Add(options[i].Trim(' ', '}')); } textReplacementOptions.order = order; //Set a flag that tells the rest of the program that this was just an order command. //Keeps the rest of the program from attempting to process the command as a text or image replacement. textReplacementOptions.isOrder = true; return(textReplacementOptions); } //Check to see whether this command asks for a bar graph, pie chart, or a simple text replacement if (outputType.Contains("bar")) { textReplacementOptions.isGraph = true; textReplacementOptions.graphType = "bar"; } else if (outputType.Contains("pie")) { textReplacementOptions.isGraph = true; textReplacementOptions.graphType = "pie"; } else { textReplacementOptions.isText = true; } //Check to see if this command wants the output to be a data range, mean, percentage, count, or just whatever value is unanimous in the specified columns. if (outputOption1.Contains("range")) { textReplacementOptions.isRange = true; } else if (outputOption1.Contains("mean")) { textReplacementOptions.isMean = true; } else if (outputOption1.Contains("percentage") || outputOption1.Contains("%")) { textReplacementOptions.isPercentage = true; } else if (outputOption1.Contains("count")) { textReplacementOptions.isCount = true; } else { textReplacementOptions.isColumnValue = true; } //If it was decided that the command asked for graph generation, then interpret the rest of the command as such. if (textReplacementOptions.isGraph) { int fontSize = 0; int optionsIndex = 2; //Check to see if the next parameter given in the command is a font size (if it is an int then it is a font size) and //if it is then store it as the font size for the command. if (int.TryParse(options[2].Trim(' ', '}'), out fontSize)) { optionsIndex++; } textReplacementOptions.fontSize = fontSize; //All of the following parameters given are column names, so iterate through them, process them, and store them in a columnNames list. for (int i = optionsIndex; i < options.Length - 1; i++) { columnNames.Add(options[i].Trim(' ', '}')); } //The final parameter in the user-given command is always the graph title. textReplacementOptions.graphTitle = options[options.Length - 1].Trim(' ', '}'); } //If they only provided a column name then put the column name in the name array else if (textReplacementOptions.isColumnValue) { columnNames.Add(outputOption1.Trim(' ', '}')); } //If it is a simple text replacement command, then proceed to add all of the column names to the columnNames list. else { for (int i = 2; i < options.Length; i++) { columnNames.Add(options[i].Trim(' ', '}')); } } textReplacementOptions.columnNames = columnNames; return(textReplacementOptions); }