2008-11-04 8 views
2

Quel est le moyen le plus efficace d'énumérer chaque cellule de chaque feuille d'un classeur?Méthode efficace pour énumérer des cellules dans un classeur Excel à l'aide de C#

La méthode ci-dessous semble fonctionner raisonnablement pour un classeur avec ~ 130 000 cellules. Sur ma machine, il a fallu ~ 26 secondes pour ouvrir le fichier et ~ 5 secondes pour énumérer les cellules. Cependant, je ne suis pas un expert Excel et je voulais valider cet extrait de code avec la communauté plus large.

DateTime timer = DateTime.Now; 
Microsoft.Office.Interop.Excel.Application excelApplication = new Microsoft.Office.Interop.Excel.Application(); 
try 
{ 
    exampleFile = new FileInfo(Path.Combine(System.Environment.CurrentDirectory, "Large.xlsx")); 
    excelApplication.Workbooks.Open(exampleFile.FullName, false, false, missing, missing, missing, true, missing, missing, true, missing, missing, missing, missing, missing); 
    Console.WriteLine(string.Format("Took {0} seconds to open file", (DateTime.Now - timer).Seconds.ToString())); 

    timer = DateTime.Now; 
    foreach(Workbook workbook in excelApplication.Workbooks) 
    { 
      foreach(Worksheet sheet in workbook.Sheets) 
      { 
      int i = 0, iRowMax, iColMax; 
      string data = String.Empty; 

      Object[,] rangeData = (System.Object[,]) sheet.UsedRange.Cells.get_Value(missing); 

      if (rangeData != null) 
      { 
       iRowMax = rangeData.GetUpperBound(0);      
       iColMax = rangeData.GetUpperBound(1);              

       for (int iRow = 1; iRow < iRowMax; iRow++) 
       { 
         for(int iCol = 1; iCol < iColMax; iCol++) 
        { 
         data = rangeData[iRow, iCol] != null ? rangeData[iRow, iCol].ToString() : string.Empty; 
         if (i % 100 == 0) 
         { 
          Console.WriteLine(String.Format("Processed {0} cells.", i)); 
         } 

         i++; 
        }                         
       } 
      } 
     } 

     workbook.Close(false, missing, missing); 
    } 

    Console.WriteLine(string.Format("Took {0} seconds to parse file", (DateTime.Now - timer).Seconds.ToString()));    
    } 
    finally 
    { 
     excelApplication.Workbooks.Close();    
     excelApplication.Quit();     
    }     

Modifier:

Worth indiquant que je veux utiliser PIA et Interop afin d'accéder aux propriétés des classeurs Excel qui ne sont pas exposés par des API qui travaillent directement avec le fichier Excel.

Répondre

2

Excel PIA Interop est très lent lorsque vous effectuez des opérations cellule par cellule.

Vous devez sélectionner la plage que vous voulez extraire, comme vous l'avez fait avec la propriété Worksheet.UsedRange puis lire la valeur de l'ensemble en une seule étape, en invoquant get_Value() (ou tout simplement en lisant la propriété Value ou Value2, je Je ne me souviens plus lequel).

Ceci donnera un object[,], c'est-à-dire un tableau bidimensionnel, qui peut être facilement énuméré et rapidement lu.

EDIT: Je viens de lire votre code actuel et j'ai réalisé qu'il fait ce que j'ai proposé. Honte à moi de ne pas avoir lu la question correctement avant de répondre. Dans ce cas, vous ne pouvez pas le faire beaucoup plus vite. Excel PIA Interop est lent. Si vous avez besoin d'une solution plus rapide, vous devrez migrer jExcelApi de Java vers C# (ce n'est pas une chose terriblement difficile à faire) ou utiliser un composant commercial. Je suggère d'éviter l'interface OLEDB à tout prix, afin de garder votre santé mentale.

Sans rapport, mais conseil utile: Vous devriez utiliser le ?? opérateur. C'est vraiment pratique. Au lieu de

data = rangeData[iRow, iCol] != null ? rangeData[iRow, iCol].ToString() : string.Empty; 

vous pourriez simplement écrire

data = Convert.ToString(rangeData[iRow, iCol]) ?? string.Empty; 

Dans ce cas, même String.Empty est pas nécessaire puisque Convert.ToString(object) convertit null à une chaîne vide de toute façon.

1

Je pense que c'est le moyen le plus efficace, comment le faire avec PIA. Peut-être deviendra-t-il plus rapide en utilisant "foreach" pour "for", mais cela ne changera pas dramatiquement.

Si votre objectif principal est l'efficacité, vous devriez travailler directement avec les fichiers Excel - sans application Excel.

2

Il existe une implémentation open source d'un lecteur et un éditeur Excel appelé Koogra. Il vous permet de lire dans le fichier Excel et de le modifier en utilisant du code managé pur. Ce serait probablement beaucoup plus rapide que le code que vous utilisez maintenant.

+0

+1 Merci pour le pointeur sur Koogra. Cela va être utile dans mon projet. – dcharles

0

Pour plus d'informations sur Pour chaque recenseurs boucle (Foreach ADO.NET schéma d'ensemble de lignes à l'aide de feuilles Excel recenseur) Service d'intégration et programmation (SSIS) en utilisant C# .Net et VB.Net, s'il vous plaît visitez le lien ci-dessous: http://www.sqllion.com/2009/06/programming-foreach-loop-container-%e2%80%93-enumerating-excel-sheets/

+0

Le lien redirige vers un article aléatoire sur www [dot] yourcareeverywhere [dot] com. – altso

Questions connexes