2015-06-10 15 views
14

Come controllare una cella contiene la formula o no in Excel tramite il lettore oledb?Come controllare una cella contiene la formula o no in Excel tramite la libreria oledb reader o excel, excel datareader o NPOI ecc (eccetto Interop)?

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

Ci può spiegare che cosa c'è che non va con il tuo codice attuale? – aspiring

+0

non c'è niente di sbagliato nel mio codice voglio solo un codice per controllare nel mio foglio excel c'è qualche formula in ogni cella. Attualmente sto usando il codice sopra per leggere Excel e convertire in tabella dati. – LuckyS

+0

come so che se aggiungi una formula a una cella restituirà sempre qualcosa (non null) nel tuo caso, penso che tu possa controllare se il valore è nullo o nullo, devi dire se è un pensiero. – SMHasnain

risposta

2

È possibile utilizzare OpenXML SDK per leggere i file Xlsx.

Per fare ciò è necessario aggiungere un riferimento alla libreria OpenXML che può essere eseguita tramite lo nuget package (sarà necessario anche un riferimento a WindowsBase). È quindi necessario caricare il foglio di calcolo, trovare il foglio che ti interessa e iterare le celle.

Ogni Cell ha una proprietà CellFormula che non sarà nulla se c'è una formula in quella cella.

Ad esempio, il codice seguente eseguirà l'iterazione di ciascuna cella e genererà una riga per ogni cella che ha una formula.restituirà true se una cella contiene una formula; altrimenti restituirà 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; 
} 

Questo può essere chiamato con il nome del file e il nome del foglio che ti interessa, anche se sarebbe banale per aggiornare il codice per iterare tutti fogli. Un esempio di richiamo:

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

Un'uscita esempio da quanto sopra:

cella C1 ha la formula A1 + B1
cellulare B3 ha formula C1 * esiste 20
Formula? Vero

Se siete interessati solo se ci sono eventuali celle nel foglio che hanno una formula è possibile semplificare il sopra utilizzando il metodo Any estensione:

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

Buone anser, ma tu don ' t trovare [ClosedXML] (https://www.nuget.org/packages/ClosedXML) come 100 volte migliore? –

+0

Grazie :). La maggior parte del lavoro di Excel che ho fatto è stato su file di grandi dimensioni, quindi utilizzo prevalentemente OpenXML a causa delle prestazioni (utilizzando un approccio SAX piuttosto che l'approccio DOM sopra). Data la semplicità di ciò che l'OP vuole ottenere, personalmente mi piacerebbe andare per un wrapper supportato da MS, ma da quello che ho visto su ClosedXML sembra troppo bello. – petelids

+0

grazie petelids :) – LuckyS

7

Si può esplorare questa: Range.HasFormula sotto com-interop.

Ho anche notato che c'è uno post che può essere improvvisato per soddisfare le vostre esigenze.

Ecco uno scheletro, non la sintassi esatta.

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

Non sei sicuro di come si può raggiungere tale con OLEDB, dal momento che la query sembra appena appena afferrare dati cellulari (testi, numeri, senza formule) nella query.

Se è necessario utilizzare OLEDB, this post può essere utile iniziare. Se hai ancora bisogno di assistenza, sentiti libero di commentare.

+2

sì, può essere fatto da questo, ma non sto usando il servizio Interop, voglio farlo solo tramite Oledb, o Exceldatareader ... – LuckyS

3

Ho una soluzione ma solo nei servizi di Interop !!

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

Se il file Excel è .xlsx, che, dal momento che .xlsx è davvero un archivio zip, si può leggere xl \ calcChain.xml al suo interno. Questo file contiene voci come questa:

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

In questo esempio ci sono le formule nelle celle G3 e A3. modo da poter fare qualcosa di simile:

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

E quindi utilizzare questo metodo come questo:

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

non capisco puoi elaborare. o dare qualche metodo per controllare il foglio contiene formula o no ... – LuckyS

+0

ho bisogno di utilizzare quale strumento di terze parti per utilizzare questo metodo o dll? – LuckyS

+0

Non sono necessari strumenti esterni, solo classi di framework .NET standard. – Eldarien

3

ho usato Apache Poi Biblioteca ... che ha seguito il metodo rilevante

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