c# Smart tags

using System;
using System.Collections.Generic;
using System.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using System.Collections;
using System.Xml;
using System.Diagnostics;
using System.Windows.Forms;

namespace TwoinOne
{
    public partial class ThisAddIn
    {
        XmlDocument xmlDoc = new XmlDocument();
        FunctionLogic obj;
        private string fromUnit;
        private string fromUnitCategory;
        private int methodsNodesCount;
        private bool columnAlign = true;
        private string rootNode = "root";
        private string callNamesNode = "callnames";
        private string identifyNode = "identify";
        private string unitsNode = "units";
        private string methodsNode = "methods";
        private Excel.XlDirection excelDirection;
        private Excel.XlDirection headerDirection;
        private Excel.Range calculationInputColumn;

        private void ThisAddIn_Startup(object sender, System.EventArgs evArgs)
        {
            resetOptions();
            string xmlPath = AppDomain.CurrentDomain.BaseDirectory + @"..\..\xml_object.xml";
            try
            {
                string xmlServerPath = "http://de08u8979:5771/2in1/xml_object.xml";
                xmlDoc.Load(xmlServerPath);
                xmlDoc.Save(xmlPath);
            }
            catch (Exception e)
            {
                xmlDoc.Load(xmlPath);
            }
            obj = new FunctionLogic(xmlPath);
            this.Application.SheetBeforeRightClick += new Excel.AppEvents_SheetBeforeRightClickEventHandler(executeMethod);
        }

        private void executeMethod(object sheet, Excel.Range selectedCells, ref bool Cancel)
        {
            Office.CommandBar contextMenu = GetCellContextMenu();
            Office.CommandBarButton methodMenu;

            if (selectedCells.Cells.Count == 1)
            {
                resetOptions();
                object selectedUnitValue = selectedCells.Value;
                fromUnit = (string)selectedCells.Value;
                fromUnit = fromUnit.ToLower().Trim();
                int callNamesCount = xmlDoc.SelectSingleNode(rootNode + "/" + callNamesNode).ChildNodes.Count;
                for (int i = 1; i < callNamesCount; i++)
                {
                    string[] callNamesArray = xmlDoc.SelectSingleNode(rootNode + "/" + callNamesNode).ChildNodes[i].InnerText.Split(',');
                    bool fromUnitCheck = callNamesArray.Contains(fromUnit);
                    if (fromUnitCheck)
                    {
                        fromUnit = xmlDoc.SelectSingleNode(rootNode + "/" + callNamesNode).ChildNodes[i].Name;
                        break;
                    }
                }
                XmlNode identifyXml = xmlDoc.SelectSingleNode(rootNode + "/" + identifyNode + "/" + fromUnit);
                fromUnitCategory = identifyXml.InnerText;

                Office.MsoControlType conversionPopupType = Office.MsoControlType.msoControlPopup;
                Office.CommandBarPopup conversionPopup = (Office.CommandBarPopup)GetCellContextMenu().Controls.Add(conversionPopupType, missing, missing, 1, true);
                conversionPopup.Caption = "Convert to";

                string unitCategory = xmlDoc.SelectSingleNode(rootNode + "/" + unitsNode + "/" + fromUnitCategory).InnerText;
                List<string> units = unitCategory.Split(',').ToList<string>();

                int unitCount = 0;
                while (unitCount < units.Count())
                {
                    if (fromUnit != units.ElementAt(unitCount))
                    {
                        methodMenu = (Office.CommandBarButton)conversionPopup.Controls.Add();
                        methodMenu.Visible = true;
                        methodMenu.Caption = units.ElementAt(unitCount);
                        methodMenu.Click += new Office._CommandBarButtonEvents_ClickEventHandler(executeConversion);
                    }
                    unitCount++;
                }
            }
            else if (selectedCells.Cells.Count > 1)
            {
                resetOptions();
                Office.MsoControlType calculationPopupType = Office.MsoControlType.msoControlPopup;
                Office.CommandBarPopup calculationPopup = (Office.CommandBarPopup)GetCellContextMenu().Controls.Add(calculationPopupType, missing, missing, 1, true);
                calculationPopup.Caption = "Calculate";
                int headersCount = selectedCells.Count;

                string[] selectedCategoriesVal = new string[headersCount];
                string address = selectedCells.Address;
                if (address.Contains(','))
                {
                    string[] addressArray = address.Split(',');
                    int addressArrayCount = addressArray.Count();
                    for (int i = 0; i < addressArrayCount; i++)
                    {
                        Excel.Worksheet activeSheet = (Excel.Worksheet)this.Application.ActiveSheet;
                        Excel.Range a = activeSheet.Range[addressArray[i].ToString()];
                        selectedCategoriesVal.SetValue(a.Value2.ToString().ToLower(), i);
                    }
                }
                else
                {
                    object selectedCategories = selectedCells.Value;
                    selectedCategoriesVal = ((IEnumerable)selectedCategories).Cast<object>()
                                     .Select(x => x.ToString().ToLower())
                                     .ToArray();
                }
                int selectedCategoriesCount = 0;
                methodsNodesCount = xmlDoc.SelectSingleNode(rootNode + "/" + methodsNode).ChildNodes.Count;
                for (int i = 0; i < methodsNodesCount; i++)
                {
                    string methodsNodes = xmlDoc.SelectSingleNode(rootNode + "/" + methodsNode).ChildNodes[i].InnerText;
                    string[] methods = methodsNodes.Split(',');
                    while (selectedCategoriesCount < selectedCategoriesVal.Length)
                    {
                        selectedCategoriesVal[selectedCategoriesCount] = selectedCategoriesVal[selectedCategoriesCount].Trim().ToLower();
                        bool methodsCheck = (methods.OrderBy(t => t)).Contains(selectedCategoriesVal[selectedCategoriesCount]);
                        if (methodsCheck)
                        {
                            string calculationMethod = xmlDoc.SelectSingleNode(rootNode + "/" + methodsNode).ChildNodes[i].Name;
                            methodMenu = (Office.CommandBarButton)calculationPopup.Controls.Add();
                            methodMenu.Visible = true;
                            methodMenu.Caption = calculationMethod;
                            methodMenu.Click += new Office._CommandBarButtonEvents_ClickEventHandler(executeCalculation);
                            break;
                        }
                        selectedCategoriesCount++;
                    }
                    selectedCategoriesCount = 0;
                }
            }
        }

        private void executeCalculation(Office.CommandBarButton calculationControl, ref bool CancelDefault)
        {
            Excel.Application excelApp = Globals.ThisAddIn.Application as Excel.Application;
            Excel.Range excelRange = excelApp.Selection as Excel.Range;
            System.Array calculationInput;
            string[] calculationHeaders = null;
            try
            {
                calculationInput = ((Excel.Range)excelRange).Cells.Value;
                calculationHeaders = calculationInput.OfType<object>().Select(o => o.ToString()).ToArray();
            }
            catch
            {
                List<string> myList = new List<string>();
                foreach (Excel.Range header in excelRange)
                {
                    string headerValue = header.Value2.ToString();
                    myList.Add(header.Value2.ToString());
                }
                calculationHeaders = myList.ToArray();
            }

            Excel.Range lastCell = excelRange.Offset[0, 1];
            Excel.Range calculationInputValRange = excelRange;
            Excel.Range inputDirection = null;
            int matrixRowCount = 0;
            int matrixColumnCount = calculationHeaders.Length;
            int row = 1;
            int column = 1;

            if (excelRange.Rows.Count == 1)
            {
                lastCell = (Excel.Range)excelRange.End[Excel.XlDirection.xlToRight];
                calculationInputValRange = (Excel.Range)this.Application.Range[excelRange, excelRange.End[Excel.XlDirection.xlDown]];
                row = lastCell.Row;
                if (excelRange.Columns.Count == 1)
                    column = 1;
                for (int i = 1; i <= calculationInputValRange.Rows.Count; i++)
                {
                    Excel.Range testCell = calculationInputValRange[i, 1].End[Excel.XlDirection.xlToRight];
                    if (testCell.Column >= column)
                        column = testCell.Column;
                }
                lastCell = (Excel.Range)this.Application.Cells[row, column + 1];
                matrixRowCount = calculationInputValRange.Rows.Count;
                inputDirection = calculationInputValRange.Columns;
                headerDirection = Excel.XlDirection.xlDown;
            }
            else if (excelRange.Columns.Count == 1)
            {
                lastCell = (Excel.Range)excelRange.End[Excel.XlDirection.xlDown];
                calculationInputValRange = (Excel.Range)this.Application.Range[excelRange, excelRange.End[Excel.XlDirection.xlToRight]];
                column = lastCell.Column;
                for (int i = 1; i <= calculationInputValRange.Columns.Count; i++)
                {
                    Excel.Range testCell = calculationInputValRange[1, i].End[Excel.XlDirection.xlDown];
                    if (testCell.Row >= row)
                        row = testCell.Row;
                }
                lastCell = (Excel.Range)this.Application.Cells[row + 1, column];
                matrixRowCount = calculationInputValRange.Columns.Count;
                inputDirection = calculationInputValRange.Rows;
                headerDirection = Excel.XlDirection.xlToRight;
            }


            string lastCellValue = lastCell.Value2;
            if ((lastCellValue != null) || (!String.IsNullOrEmpty(lastCellValue)))
            {
                return;
            }

            string[,] matrix = new string[matrixRowCount, matrixColumnCount];
            int colIndex = 0;
            foreach (Excel.Range cell in excelRange)
            {
                calculationInputColumn = (Excel.Range)this.Application.Range[cell, cell.End[headerDirection]];
                calculationInput = ((Excel.Range)calculationInputColumn).Cells.Value;
                string[] calculationInputValues = calculationInput.OfType<object>().Select(o => o.ToString()).ToArray();
                for (int j = 0; j < calculationInputValues.Length; j++)
                {
                    matrix[j, colIndex] = calculationInputValues[j];
                }
                colIndex++;
            }

            string[] calculatedArray = obj.calculation(matrix, calculationControl.Caption);
            if (excelRange.Rows.Count == 1)
            {
                for (int i = 0; i < calculatedArray.Length; i++)
                {
                    lastCell.Offset[i, 0].Value2 = calculatedArray[i].ToString();
                }
            }
            else if (excelRange.Columns.Count == 1)
            {
                for (int i = 0; i < calculatedArray.Length; i++)
                {
                    lastCell.Offset[0, i].Value2 = calculatedArray[i].ToString();
                }
            }

        }

        private void executeConversion(Office.CommandBarButton conversionControl, ref bool CancelDefault)
        {
            int rowOffset = 0, colOffset = 0;
            double number;
            bool isNumeric = false;
            if (this.Application.ActiveCell.Offset[1].Value2 != null)
            {
                isNumeric = double.TryParse(this.Application.ActiveCell.Offset[1].Value2.ToString(), out number);
            }

            if (isNumeric)
            {
                columnAlign = true;
            }

            if (columnAlign == true)
            {
                excelDirection = Excel.XlDirection.xlDown;
                rowOffset = 1;
                colOffset = 0;
            }
            else
            {
                excelDirection = Excel.XlDirection.xlToRight;
                rowOffset = 0;
                colOffset = 1;
            }
            Excel.Range startRange = (Excel.Range)this.Application.ActiveCell.Offset[rowOffset, colOffset];
            Excel.Range conversionInputRange;
            System.Array conversionArray;
            string[] conversionArrayValues = new string[] { };

            if (startRange.Offset[rowOffset, colOffset].Value != null)
            {
                conversionInputRange = (Excel.Range)this.Application.Range[startRange, startRange.End[excelDirection]];
            }
            else
            {
                conversionInputRange = startRange;
            }
            try {
                conversionArray = ((Excel.Range)conversionInputRange).Cells.Value2;
                conversionArrayValues = conversionArray.OfType<object>().Select(o => o.ToString()).ToArray();
            }
            catch(Exception exc)
            {
                string inputString = conversionInputRange.Cells.Value2.ToString();
                conversionArrayValues = new[] { inputString };
            }
            string[] convertedArray = obj.conversion(conversionArrayValues, fromUnit, conversionControl.Caption);
            int index = 0;

            foreach (object cell in conversionInputRange.Cells)
            {
                ((Excel.Range)cell).Value = convertedArray[index].ToString();
                index++;
            }
            this.Application.ActiveCell.Value2 = conversionControl.Caption;

        }
       
        #region populateOptions
        private void resetOptions()
        {
            GetCellContextMenu().Reset();
        }
        #endregion

        #region GetCellContextMenu
        private Office.CommandBar GetCellContextMenu()
        {
            return this.Application.CommandBars["Cell"];
        }
        #endregion

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }
       
        #endregion
    }
}

Comments