Question

I have formula cell in excel file that has the formula =SUM(C2:C3).

From the web application hosted on remote webserver in the cloud, that does not have Excel installed, I would pass in values for C2 and C3.

I can also determine the exact formula in excel. How do I parse this formula programmatically in c# so that I could get the result of 6 if the input values of C2 and C3 were 2 and 4 respectively?

What if the formula is very complex, what is the best way to parse the formula and calculate it in C# on the server side in asp.net mvc application?

Code sample would really benefit me in this case.

Was it helpful?

Solution

If you provide a tool to open excel file and translate it's content to html you must deal with calculation.

If the file is "well created", for example manually with Excel you can be sure you don't need to manage computation of the formulas cause excel does the trick and stores both the formula in CellFormula's child element and result in CellValue's child element (See the method GetValue_D11()). So basically you just need to show the result.. which always will be a String.

Unfortunately you have to deal with styles and dataTypes, if you want to mantain behaviour.

Actually you have to build a complex web based spreadsheet viewer/editor.

Here is a sample "fixed" (totally not dynamic for all) for retrieving String values and formula values. if you wanna run the test be sure to download that file (http://www.devnmore.com/share/Test.xlsx) otherwise it can't works.

ShowValuesSample svs = new ShowValuesSample("yourPath\\Test.xlsx");
String[] test = svs.GetDescriptions_A2A10();
Double grandTotal = svs.GetValue_D11();

ShowValuesSample class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DocumentFormat.OpenXml.Packaging;
using Ap = DocumentFormat.OpenXml.ExtendedProperties;
using Vt = DocumentFormat.OpenXml.VariantTypes;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Spreadsheet;
using A = DocumentFormat.OpenXml.Drawing;
using System.Globalization;

namespace TesterApp
{
    public class ShowValuesSample
    {

        public String FileName { get; private set; }

        private SpreadsheetDocument _ExcelDocument = null;
        public SpreadsheetDocument ExcelDocument
        {
            get
            {
                if (_ExcelDocument == null)
                {
                    _ExcelDocument = SpreadsheetDocument.Open(FileName, true);
                }
                return _ExcelDocument;
            }

        }
        private SheetData _SheetDataOfTheFirstSheet = null;
        public SheetData SheetDataOfTheFirstSheet
        {
            get
            {
                if (_SheetDataOfTheFirstSheet == null)
                {
                    WorksheetPart shPart = ExcelDocument.WorkbookPart.WorksheetParts.ElementAt(0);
                    Worksheet wsh = shPart.Worksheet;
                    _SheetDataOfTheFirstSheet = wsh.Elements<SheetData>().ElementAt(0);
                }

                return _SheetDataOfTheFirstSheet;
            }
        }
        private SharedStringTable _SharedStrings = null;
        public SharedStringTable SharedStrings
        {
            get
            {
                if (_SharedStrings == null)
                {
                    SharedStringTablePart shsPart = ExcelDocument.WorkbookPart.SharedStringTablePart;
                    _SharedStrings = shsPart.SharedStringTable;
                }
                return _SharedStrings;
            }
        }

        public ShowValuesSample(String fileName)
        {
            FileName = fileName;
        }

        //In the file descriptions are stored as sharedString 
        //so cellValue it's the zeroBased index of the sharedStringTable
        //in my example i saved 9 different values
        //sharedstring it's a trick to reduce size of a file obiouvsly writing 
        //repetitive string just once
        public String[] GetDescriptions_A2A10()
        {
            String[] retVal = new String[9];

            for (int i = 0; i < retVal.Length; i++)
            {
                Row r = SheetDataOfTheFirstSheet.Elements<Row>().ElementAt(i + 1);
                Cell c = r.Elements<Cell>().ElementAt(0);
                Int32 shsIndex = Convert.ToInt32(c.CellValue.Text);
                SharedStringItem shsItem = SharedStrings.Elements<SharedStringItem>().ElementAt(shsIndex);
                retVal[i] = shsItem.Text.Text;
            }

            return retVal;
        }

        //The value it's stored beacause excel does
        //To be sure it's correct you should perform all calculations
        //In this case i'm sure Excel didn't stored the wrong value so..
        public Double GetValue_D11()
        {
            Double retVal = 0.0d;

            Int32 cellIndex = 0;
            //cellIndex it's 0 and not 3, cause A11, B11, C11 are empty cells
            //Another issue to deal with ;-)
            Cell c = SheetDataOfTheFirstSheet.Elements<Row>().ElementAt(10).Elements<Cell>().ElementAt(cellIndex);

            //as example take a look at the value of storedFormula
            String storedFormula = c.CellFormula.Text;
            String storedValue = c.CellValue.Text;

            NumberFormatInfo provider = new NumberFormatInfo();
            provider.NumberDecimalSeparator = ".";
            provider.NumberGroupSeparator = ",";
            provider.NumberGroupSizes = new Int32[] { 3 };

            retVal = Convert.ToDouble(storedValue, provider);

            return retVal;
        }
    }
}

OTHER TIPS

spreadSheet.WorkbookPart.Workbook.CalculationProperties.ForceFullCalculation = true;
spreadSheet.WorkbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true;

worked for me.

I'm afraid its not possible. In Open XML you can read or change the formula. But you process the formula and get results through open xml.

Change the values for C2 and C3 for the formula and then save it in open xml, now open the document through Excel App. The values will be calculated and displayed.

Refer this SO Post, related to this issue open xml sdk excel formula recalculate cache issue

Refer this post too http://openxmldeveloper.org/discussions/formats/f/14/p/1806/158153.aspx

Hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top