Méthode efficace pour énumérer les cellules dans un classeur Excel à l'aide de c#

Quel est le moyen le plus efficace pour énumérer toutes les cellules dans chaque feuille dans un classeur ?

La méthode ci-dessous semble fonctionner raisonnablement pour un classeur avec ~ 130 000 cellules. Sur ma machine, il a fallu environ 26 secondes pour ouvrir le fichier et ~ 5 secondes pour énumérer les cellules. Cependant, je ne suis aucun Excel expert et voulait 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:

Une valeur indiquant que je veux utiliser le PIA et interop afin d'accéder aux propriétés d'excel classeurs qui ne sont pas exposées par les API s ce travail directement avec le fichier Excel.

répondre #1

Interop assembly PIA Excel est très lent lorsque vous faites des choses par une cellule.

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

Cela donnera un object[,] , c'est-à-dire, deux dimension array, qui peut être facilement énuméré et est rapide à lire.

EDIT: J'ai juste lire votre code réel et s'est rendu compte que c'est effectivement ce que je propose. Honte sur moi pour ne pas lire la question avant de répondre correctement. Dans ce cas, vous ne peut pas faire beaucoup plus rapidement. Interop assembly PIA Excel est lente. Si vous avez besoin d'une solution plus rapide, vous devrez soit migrer jExcelApi de Java en c# (pas une chose de terriblement difficile à faire) ou utiliser une composante commerciale. Je suggère d'éviter à tout prix de l'interface OLEDB, afin de garder votre santé mentale.

Non, mais une astuce utile : vous devez utiliser la?? opérateur. C'est vraiment pratique. Au lieu de

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

vous pouvez simplement écrire

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

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

répondre #2

Il existe une implémentation open source d'un lecteur Excel et écrivain appelé Koogra. Il vous permet de lire dans le fichier excel et le modifier à l'aide de code managé pur. Ce serait probablement beaucoup plus rapide que le code que vous utilisez actuellement.

répondre #3

Je pense que c'est le moyen le plus efficace, comment le faire avec PIA. Sera peut-être littlebit plus rapide à l'aide de « foreach » plutôt que « pour », mais il change pas dramatique.

Si l'efficacité est votre objectif, vous devez travailler avec excel directement des fichiers - excel sans application.

répondre #4

Pour plus d'informations sur pour les recenseurs de chaque boucle (Foreach ADO.NET Schema Rowset énumérateur à l'aide de feuilles Excel) et le service d'intégration programmation (SSIS) à l'aide de c# .net et VB .net, veuillez visiter le dessous le lien : http://www.sqllion.com/2009/06/programming-foreach-loop-container-%e2%80%93-enumerating-excel-sheets/


Tags lesen

  
 
logo_banner