How to check a Cell contains formula or not in Excel through oledb reader or excel library, excel datareader or NPOI etc (Except Interop)?
Asked Answered
A

5

14

How to check a Cell contains formula or not in Excel through oledb reader ?

enter image description here

System.Data.OleDb.OleDbConnection conn2 = new System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0; Data Source = " + strFileName + "; Extended Properties = \"Excel 8.0;HDR=NO;IMEX=1\";");
conn2.Open();
string strQuery2 = "SELECT * FROM [" + Table + "]";

System.Data.OleDb.OleDbDataAdapter adapter2 = new System.Data.OleDb.OleDbDataAdapter(strQuery2, conn2);

System.Data.DataTable DT2 = new System.Data.DataTable();

adapter2.Fill(DT2);
Almazan answered 10/6, 2015 at 4:48 Comment(7)
Can you explain what's wrong with your current code?Escort
there is nothing wrong in my code i just want a code to check in my excel sheet is there is any formula in any cell. Currently i am using above code to read excel and convert into data table.Almazan
as i know if you add formula to a cell it will always return something (not null) in your case I think you can check for value is null or not null, do tell if its gives you a thought.Graf
aspiring ,,same columns inside the table which i shown with same values, i just want to check before reading the excel sheet , Is there is any formula contain in cell or not , check my image...Almazan
AFAIK this is not possible using OLEDBEke
Things like these make me want to write my own Excel library!Sitnik
you can Ravi , then u'll get 50 bounty :)Almazan
I
2

You can use the OpenXML SDK to read Xlsx files.

To do this you need to add a reference to the OpenXML library which can be done via the nuget package (you'll also need a reference to WindowsBase). You then need to load the spreadsheet, find the sheet you're interested in and iterate the cells.

Each Cell has a CellFormula property which will be non-null if there is a formula in that cell.

As an example, the following code will iterate each cell and output a line for any cell that has a formula. it will return true if any cell has a formula in it; otherwise it will return false:

public static bool OutputFormulae(string filename, string sheetName)
{
    bool hasFormula = false;

    //open the document
    using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filename, false))
    {
        //get the workbookpart
        WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
        //get the correct sheet
        Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName).First();
        if (sheet != null)
        {
            //get the corresponding worksheetpart
            WorksheetPart worksheetPart = workbookPart.GetPartById(sheet.Id) as WorksheetPart;

            //iterate the child Cells
            foreach (Cell cell in worksheetPart.Worksheet.Descendants<Cell>())
            {
                //check for a formula
                if (cell.CellFormula != null && !string.IsNullOrEmpty(cell.CellFormula.Text))
                {
                    hasFormula = true;
                    Console.WriteLine("Cell {0} has the formula {1}", cell.CellReference, cell.CellFormula.Text);
                }
            }
        }
    }

    return hasFormula;
}

This can be called with the name of the file and the name of the sheet you're interested in although it would be trivial to update the code to iterate all sheets. An example call:

bool formulaExistsInSheet = OutputFormulae(@"d:\test.xlsx", "Sheet1");
Console.WriteLine("Formula exists? {0}", formulaExistsInSheet);

An example output from the above:

Cell C1 has the formula A1+B1
Cell B3 has the formula C1*20
Formula exists? True

If you're only interested if there are any cells in the sheet that have a formula you can simplify the above by using the Any extension method:

public static bool HasFormula(string filename, string sheetName)
{
    bool hasFormula = false;
    //open the document
    using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filename, false))
    {
        //get the workbookpart
        WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
        //get the correct sheet
        Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName).First();
        if (sheet != null)
        {
            //get the corresponding worksheetpart
            WorksheetPart worksheetPart = workbookPart.GetPartById(sheet.Id) as WorksheetPart;

            hasFormula = worksheetPart.Worksheet.Descendants<Cell>().Any(c =>
                c.CellFormula != null && !string.IsNullOrEmpty(c.CellFormula.Text));
        }
    }

    return hasFormula;
}
Immemorial answered 18/6, 2015 at 11:5 Comment(4)
Good anwser, but you don't find ClosedXML like 100 times better?Replevin
Thanks :). Most of the Excel work I've done has been on large files so I predominantly use OpenXML due to performance (using a SAX approach rather than the above DOM approach). Given the simplicty of what the OP wants to achieve I would personally go for an MS supported wrapper but from what I've seen of ClosedXML that looks good too.Immemorial
MS office required for this or not ?Almazan
No Office is not required, just OpenXML (which makes this perfectly safe to use on a server for example)Immemorial
E
8

You may explore this : Range.HasFormula under com-interop.

I also noticed there's a post that can be improvised to cater your needs.

Here's a skeleton - not the exact syntax.

Excel.Application excelApp = new Excel.Application();
Excel.Workbook workBook = excelApp.Workbooks.Open(filePath);
Excel.WorkSheet WS = workBooks.WorkSheets("Sheet1");

Range rangeData = WS.Range["A1:C3"];    

foreach (Excel.Range c in rangeData.Cells)
{
    if (c.HasFormula)
    {
       MessageBox.Show(Convert.ToString(c.Value));
    }        
}

Not sure how you can achieve such with OLEDB, since your query just seems to just grab cell data (texts, numbers, without formulas) into the query.

If you must use OLEDB, this post can be helpful to start. If you still need assistance, feel free to comment.

Escort answered 10/6, 2015 at 7:45 Comment(1)
yes it can be done by this but i am not using Interop service, I want to do this only through Oledb, or Exceldatareader ...Almazan
A
4

I got solution but only in Interop Services!!

public bool IsFormulaExistInExcel(string excelpath)
     {
        bool IsFormulaExist = false;
        try
        {
            Microsoft.Office.Interop.Excel.Application excelApp = null;
            Microsoft.Office.Interop.Excel.Workbooks workBooks = null;
            Microsoft.Office.Interop.Excel.Workbook workBook = null;
            Microsoft.Office.Interop.Excel.Worksheet workSheet;
            excelApp = new Microsoft.Office.Interop.Excel.Application();
            workBooks = excelApp.Workbooks;
            workBook = workBooks.Open(excelpath, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
            workSheet = workBook.Worksheets.get_Item(1);
            Microsoft.Office.Interop.Excel.Range rng = workSheet.UsedRange;


            dynamic FormulaExist = rng.HasFormula;
            Type unknown = FormulaExist.GetType();

            if (unknown.Name == "DBNull")
                IsFormulaExist = true;
            else if (unknown.Name == "Boolean")
            {
                if (FormulaExist == false)
                    IsFormulaExist = false;
                else if (FormulaExist == true)
                    IsFormulaExist = true;
            }
        }
        catch (Exception E)
        {
        }
    return IsFormulaExist;
  }
Almazan answered 16/6, 2015 at 4:42 Comment(0)
W
3

i used Apache Poi Library... which has below relevant method

if(cell.getCellType()==CellType.CELL_TYPE_FORMULA)
{
// this cell contains formula......
}
Watersoak answered 18/6, 2015 at 10:2 Comment(0)
P
2

If your excel file is .xlsx, than, since .xlsx is really a zip archive, you can read xl\calcChain.xml inside it. This file contains entries like this:

<c r="G3" i="1" l="1"/><c r="A3" i="1" l="1"/>

In this example there are formulas in cells G3 and A3. So you can do something like this:

    // Add references for
    // System.IO.Compression
    // System.IO.Compression.FileSystem

    private static List<string> GetCellsWithFormulaInSheet(string xlsxFileName, int sheetNumber)
    {
        using (var zip = System.IO.Compression.ZipFile.OpenRead(xlsxFileName))
        {
            var list = new List<string>();

            var entry = zip.Entries.FirstOrDefault(e => e.FullName == "xl/calcChain.xml");
            if (entry == null)
                return list;

            var xdoc = XDocument.Load(entry.Open());
            XNamespace ns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";

            return xdoc.Root.Elements(ns + "c")
                .Select(x => new { Cell = x.Attribute("r").Value, Sheet = int.Parse(x.Attribute("i").Value) })
                .Where(x => x.Sheet == sheetNumber)
                .Select(x => x.Cell)
                .ToList();
        }
    }

And then use this method like this:

var cellsWithFormula = GetCellsWithFormulaInSheet(@"c:\Book.xlsx", 1);
bool hasFormulaInSheet = cellsWithFormula.Any();
Pallor answered 17/6, 2015 at 15:20 Comment(6)
i dont understand can you elaborate. or give some method to check sheet contains formula or not ...Almazan
i need to use which third party tool to use this method or dll ?Almazan
No external tools needed, only standard .NET framework classes.Pallor
always getting error while writing this System.IO.Compression.FileSystemAlmazan
Why are you writing it? You need to add it to project references in Solution Explorer. You need to check both System.IO.Compression and System.IO.Compression.FileSystem in Add References dialog.Pallor
You need to change the target framework of the current project from .Net 4 to .Net 4.5. Make sure that you did that and re-check your project references. Also see this thread: #14219102Pallor
I
2

You can use the OpenXML SDK to read Xlsx files.

To do this you need to add a reference to the OpenXML library which can be done via the nuget package (you'll also need a reference to WindowsBase). You then need to load the spreadsheet, find the sheet you're interested in and iterate the cells.

Each Cell has a CellFormula property which will be non-null if there is a formula in that cell.

As an example, the following code will iterate each cell and output a line for any cell that has a formula. it will return true if any cell has a formula in it; otherwise it will return false:

public static bool OutputFormulae(string filename, string sheetName)
{
    bool hasFormula = false;

    //open the document
    using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filename, false))
    {
        //get the workbookpart
        WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
        //get the correct sheet
        Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName).First();
        if (sheet != null)
        {
            //get the corresponding worksheetpart
            WorksheetPart worksheetPart = workbookPart.GetPartById(sheet.Id) as WorksheetPart;

            //iterate the child Cells
            foreach (Cell cell in worksheetPart.Worksheet.Descendants<Cell>())
            {
                //check for a formula
                if (cell.CellFormula != null && !string.IsNullOrEmpty(cell.CellFormula.Text))
                {
                    hasFormula = true;
                    Console.WriteLine("Cell {0} has the formula {1}", cell.CellReference, cell.CellFormula.Text);
                }
            }
        }
    }

    return hasFormula;
}

This can be called with the name of the file and the name of the sheet you're interested in although it would be trivial to update the code to iterate all sheets. An example call:

bool formulaExistsInSheet = OutputFormulae(@"d:\test.xlsx", "Sheet1");
Console.WriteLine("Formula exists? {0}", formulaExistsInSheet);

An example output from the above:

Cell C1 has the formula A1+B1
Cell B3 has the formula C1*20
Formula exists? True

If you're only interested if there are any cells in the sheet that have a formula you can simplify the above by using the Any extension method:

public static bool HasFormula(string filename, string sheetName)
{
    bool hasFormula = false;
    //open the document
    using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filename, false))
    {
        //get the workbookpart
        WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
        //get the correct sheet
        Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName).First();
        if (sheet != null)
        {
            //get the corresponding worksheetpart
            WorksheetPart worksheetPart = workbookPart.GetPartById(sheet.Id) as WorksheetPart;

            hasFormula = worksheetPart.Worksheet.Descendants<Cell>().Any(c =>
                c.CellFormula != null && !string.IsNullOrEmpty(c.CellFormula.Text));
        }
    }

    return hasFormula;
}
Immemorial answered 18/6, 2015 at 11:5 Comment(4)
Good anwser, but you don't find ClosedXML like 100 times better?Replevin
Thanks :). Most of the Excel work I've done has been on large files so I predominantly use OpenXML due to performance (using a SAX approach rather than the above DOM approach). Given the simplicty of what the OP wants to achieve I would personally go for an MS supported wrapper but from what I've seen of ClosedXML that looks good too.Immemorial
MS office required for this or not ?Almazan
No Office is not required, just OpenXML (which makes this perfectly safe to use on a server for example)Immemorial

© 2022 - 2024 — McMap. All rights reserved.