C# Exceldokument schneller bearbeiten

Raknar

Ensign
Registriert
Apr. 2006
Beiträge
204
Guten Tag,

ich habe vor einiger Zeit ein Programm geschrieben, dass Excel-Sheets nach bestimmten Vorgaben umgestaltet. Z.B. werden Begriffe durch andere ersetzt oder Berechnungen durchgeführt. Je nachdem, welche Zelle es eben betrifft - sprich: das Programm geht die Sheets mit Schleifen durch und greift (besonders bei den Ersetzungen) oft auf jede Zelle einzeln zu. So dass bei einer Tabelle mit 40 Spalten und 40 Zeilen die Bearbeitung schon 2 Minuten dauert. Es gibt auch Tabellen mit 4000 Zeilen... :freaky:

Frage: Kann man den kompletten Inhalt schneller bearbeiten? Es sind diese vielen Zugriffe auf das Exceldokument, die Zeit kosten. Ich stelle mir da die Möglichkeit vor alles in einen String zu laden und fix mit Regexoperationen etc. zu bearbeiten und dann das Ergebnis ins Exceldokument zu schreiben. Das wären dann gerade mal zwei Zugriffe - lesen und schreiben.

Vielen Dank schon mal im Voraus.
 
Nicht so einfach zu beantworten.

Ich nutze Excel eigentlich nur als Datenquelle, heißt ich lesen mit den Inhalt von Excel in eine DataTable und manipuliere nur noch die Daten dort und schreibe, bei Bedarf, am Ende einfach ein neues Dokument.

Mein Ziel ist es aber hier nicht Excel qua Automatisierung Dinge berechnen zu lassen, sondern wie gesagt Excel als Datenquelle zu nutzen. Per ADO ist der Zugriff auf die Daten in Excel daher recht schnell. Keine Ahnung welche Methode du nutzt, um auf Excel zu zugreifen.
 
Es wäre gut, wenn Du ein paar Daten zur Verfügung stellt:
- Visual Studio ?
- C# Version? (entspricht .Net Version)
- Eingebetteten Code in Excel (gehe mal davon aus).

Also wenn man anschaut, dass Du 40 * 40 = 1600 Werten hast, ist 2 Minuten doch etwas zu lang.
Aber wenn man Dir helfen möchtet, braucht man schon Code, um zu sehen, ob da ein Vorgang gibt, die möglicherweise zu den 2 Minuten führen.

@ADO: Danke für den Hinweis. *Wieder was gelernt*
 
Es gibt auch externe Kompononenten, die Excel Dateien bearbeiten können, evlt. sind die schneller.

Ansonsten schonmal eine andere Herangehensweise probiert? Sowie ich das anhört, liest Du eine Zelle, berechnest was und schreibst wieder was in die Zelle zurück. Schonmal probiert, alles am Stück zu lesen in ein Array oder sonstige Struktur, dort die Berechnungen und Ersetzungen zu machen und dann wieder alles am Stück zurückzuschreiben?

Evtl. ist das perfomanter...
 
[Ger]Phoenix schrieb:
Es wäre gut, wenn Du ein paar Daten zur Verfügung stellt:
- Visual Studio ?
- C# Version? (entspricht .Net Version)
- Eingebetteten Code in Excel (gehe mal davon aus).

...*

- VS2010
- .Net 4.0
- Der Code liegt in C# vor. Ich weiß nicht, was du meinst. In VBA wurde nichts gemacht.

@Drexel
Das klingt viel versprechend. Du hast Recht, in der Methode für das Ersetzen lese, bearbeite und schreibe ich zurück für jede Zeile. Du hast nicht zufällig ein Beispiel für das Anlegen eines Arrays, das den Inhalts einer Excel-Tabelle einliest und dessen Inhalt wieder zurück geschrieben wird?

Es sieht wohl so aus als wenn ich das komplette Programm umschreiben muss. Die Hälfte des Codes sieht so aus:

Code:
if (xlSht.Cells[row, spalte].Text == ("'Parameter"))
                        {
                            xlSht.Cells[row, spalte] = "'Bezeichnung"; continue;
                        }


Der Code ist auch historisch gewachsen und war am Anfang nicht für diesen neuen Umfang gedacht.

EDIT:
Ich habe einfach mal die offiziellen Beschreibungen von MS zu Office.Interop durchgelesen und bin fündig geworden:
Code:
            string testpfad = @"N:\DotNet Programme\...";     

            String sheetName = "Tabelle1";
            Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
            xlApp.Visible = true;
            Microsoft.Office.Interop.Excel.Workbook xlWbk = xlApp.Workbooks.Open(testpfad);
            Microsoft.Office.Interop.Excel.Worksheet xl_Sheet = xlWbk.Sheets[sheetName.ToString()];

            Microsoft.Office.Interop.Excel.Range xl_Range;
            xl_Range = xl_Sheet.UsedRange;

            int row = xl_Range.Rows.Count-1;
            int spalte = xl_Range.Columns.Count;


            for (int i = 1; i <= row; i++)
            {
                for (int j = 1; j <= spalte; j++)
                {
                    if (xl_Range.Cells[row, spalte].Text == ("geheim"))
                    {
                        xl_Range.Cells[row, spalte] = "'noch geheimer";
                              
                                    . . .
Zeile 10 ist der Hit :) Hier wird das komplette benutzte Areal des Excel-Sheets (in meinem Fall also die Tabelle samt Inhalt) gezogen und virtuell abgebildet. Ich kann den bösen unperformanten Code des Kollegen darauf anwenden.
Eine Tabelle mit 4000 Zeilen einlesen und bearbeiten dauert nicht mal 5 Sekunden! Jetzt beschäftige ich mich noch damit das Ganze zurück zu schreiben. Wird aber einfach :)
Dank an Drexel. Du hast mich in die richtige Richtung gelenkt
 
Zuletzt bearbeitet:
Statt einzeln auf die Zellen zugreifen zu wollen, würde ich die gesamte Range erstmal in ein 2 dimensionales Object Array laden. Dann auf dem Array arbeiten und das Array wieder zurück in das Excelsheet werfen. Das geht über die Range.Value Eigenschaft:

Code:
 Microsoft.Office.Interop.Excel.Range xl_Range = xl_Sheet.UsedRange;
 object[,] values = xl_Range.Value;
 for(int row = 0; row <= values.GetUpperBound(0); row++)
   for(int col = 0; col <= values.GetUpperBound(1); col++)
   {
      // mach was immer du willst:
      values[row, col] = "xyz";
   }
 xl_Range.Value = values;

Gruß
Rossibaer
 
Zurück
Oben