Как проверить ячейку содержит формулу или нет в Excel через oledb reader или excel library, excel datareader или NPOI и т.д. (Кроме Interop)?

Как проверить ячейку содержит формулу или нет в Excel через читатель олда?

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);

Ответы

Ответ 1

Вы можете использовать OpenXML SDK для чтения файлов Xlsx.

Для этого вам нужно добавить ссылку на библиотеку OpenXML, которую можно выполнить с помощью пакета nuget (вам также понадобится ссылка на WindowsBase). Затем вам нужно загрузить электронную таблицу, найти интересующий вас лист и перебрать ячейки.

Каждый Cell имеет CellFormula свойство, которое будет не нулевым, если в этой ячейке есть формула.

В качестве примера следующий код будет перебирать каждую ячейку и выводить строку для любой ячейки, которая имеет формулу. он вернет true, если какая-либо ячейка имеет в ней формулу; иначе он вернет 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;
}

Это можно вызвать с именем файла и именем интересующего вас листа, хотя было бы тривиально обновлять код для повторения всех листов. Пример вызова:

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

Пример вывода из вышеперечисленного:

Ячейка C1 имеет формулу A1 + B1
Ячейка B3 имеет формулу C1 * 20
Формула существует? True

Если вас интересует только наличие на листе каких-либо ячеек, которые имеют формулу, вы можете упростить ее, используя Any метод расширения:

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;
}

Ответ 2

Вы можете изучить это: Range.HasFormula в разделе com-interop.

Я также заметил там пост, который можно импровизировать, чтобы удовлетворить ваши потребности.

Здесь скелет - не точный синтаксис.

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));
    }        
}

Не уверен, как вы можете достичь этого с помощью OLEDB, так как ваш запрос просто просто захватывает данные ячейки (тексты, цифры, без формул) в запрос.

Если вы должны использовать OLEDB, этот пост может быть полезен для запуска. Если вам по-прежнему нужна помощь, не стесняйтесь комментировать.

Ответ 3

Я получил решение, но только в 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;
  }

Ответ 4

Я использовал Apache Poi Library... который имеет ниже соответствующий метод

if(cell.getCellType()==CellType.CELL_TYPE_FORMULA)
{
// this cell contains formula......
}

Ответ 5

Если ваш файл excel равен .xlsx, то, поскольку .xlsx - это действительно zip-архив, вы можете прочитать xl\calcChain.xml внутри него. Этот файл содержит следующие записи:

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

В этом примере есть формулы в ячейках G3 и A3. Итак, вы можете сделать что-то вроде этого:

    // 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();
        }
    }

И затем используйте этот метод следующим образом:

var cellsWithFormula = GetCellsWithFormulaInSheet(@"c:\Book.xlsx", 1);
bool hasFormulaInSheet = cellsWithFormula.Any();