redwraith
Goto Top

VB.NET Lässt sich Excel Interop beschleunigen ?

Hallo Freunde !

Ich habe ein kleines Tool geschrieben, welches Berichte aus einer Datenbank erstellt und diese dem Nutzer anzeigt.

Nun möchte ich, dass der User die Möglichkeit hat, den Bericht in eine Excel Datei zu exportieren.
Meine Implementation über Microsoft.Office.Interop.Excel funktioniert auch, allerdings kommt diese mir langsam vor.
Ich brauche um eine 250 Zeilen lange, nachher etwa 50KB große Excel Tabelle zu exportieren etwa 15-20 Sekunden.
Wenn ich bedenke, dass ich auf einem Core2 Duo mit 4Gig Ram arbeite, kommt mir das zu langsam vor,
vorallem wenn ich daran denke, dass das Programm auch noch auf schwächeren Rechnern ausgeführt werden soll.


Meine Implementation sieht im Moment so aus:

Private Sub SpeicherDateiXLS(ByVal pfad As String, Optional ByVal confirm As Boolean = False)
        Dim app As Excel.Application
        Dim wb As Excel.Workbook
        Dim ws As Excel.Worksheet

        Dim i, j, cursor As Integer

        Try
           app = New Excel.Application
            wb = app.Workbooks.Add()
            ws = wb.Sheets(1)

            ws.Activate()

            cursor = 1

            With ws

                For i = 0 To Me.dgvDeckblatt.Columns.Count - 1
                    .Cells(cursor, i + 1).value = Me.dgvDeckblatt.Columns(i).HeaderText
                Next

                cursor += 1

                For i = 0 To Me.dgvDeckblatt.Rows.Count - 1
                    For j = 0 To Me.dgvDeckblatt.Columns.Count - 1
                        .Cells(cursor, j + 1).value = ds(Me.dgvDeckblatt.Rows(i).Cells(j).Value)
                    Next
                    cursor += 1
                Next

                cursor += 3

                For i = 0 To Me.dgvPackliste.Columns.Count - 1
                    .Cells(cursor, i + 1).value = Me.dgvPackliste.Columns(i).HeaderText
                Next

                cursor += 1

                For i = 0 To Me.dgvPackliste.Rows.Count - 1
                    For j = 0 To Me.dgvPackliste.Columns.Count - 1
                        .Cells(cursor, j + 1).value = ds(Me.dgvPackliste.Rows(i).Cells(j).Value)
                    Next
                    cursor += 1
                Next

                cursor += 3

                For i = 0 To Me.dgvFehlmengen.Columns.Count - 1
                    .Cells(cursor, i + 1).value = Me.dgvFehlmengen.Columns(i).HeaderText
                Next

                cursor += 1

                For i = 0 To Me.dgvFehlmengen.Rows.Count - 1
                    For j = 0 To Me.dgvFehlmengen.Columns.Count - 1
                        .Cells(cursor, j + 1).value = ds(Me.dgvFehlmengen.Rows(i).Cells(j).Value)
                    Next
                    cursor += 1
                Next

                .PageSetup.Zoom = False
                .PageSetup.FitToPagesWide = 1
                .PageSetup.FitToPagesTall = 99

            End With

            wb.SaveAs(pfad)
            wb.Close()
            app.Quit()

            If confirm Then
                MsgBox("Bericht wurde gespeichert unter:" & vbCrLf & pfad)  
            End If

        Catch ex As Exception
            MessageBox.Show("Error: " + ex.ToString())  
        End Try
    End Sub

Gibt es eine Möglichkeit, das in Bezug auf Ausführgeschwindigkeit zu verbessern ?

Ich wäre für jeden Vorschlag dankbar.

Content-ID: 137869

Url: https://administrator.de/contentid/137869

Ausgedruckt am: 26.11.2024 um 07:11 Uhr

problemsolver
problemsolver 10.03.2010 um 12:01:47 Uhr
Goto Top
Hallo,

mein Vorschlag:
1.) Exportiere die Werte in eine CSV-Datei. Dadurch benutzt Du nur die normalen Dateisystemfunktionen...
2.) Öffne die CSV mit Excel. Formatiere bzw Passe die Spalten dann an.

Das wird sicherlich viel viel schneller sein... schon mal über diesen Weg nachgedacht... Ok ich gebe zu, dass es etwas ungewöhnlich ist, aber "give it a try" face-wink

gruß

Markus
RedWraith
RedWraith 10.03.2010 um 12:19:38 Uhr
Goto Top
Ah ich werds versuchen !

Interessanterweise hatte ich ursprünglich einen CSV Export implementiert, aber ich brauchte zusätzliche Formatierungen.
Ich melde mich zurück, wenns geklappt hat.
76109
76109 10.03.2010 um 12:55:56 Uhr
Goto Top
Hallo RedWraith!

Da gibts doch sicher auch eine Range-Funktion und eventuell eine Copy-Funktion mit Destination oder Copy- und Paste-Funktion. In Excel würde man das sinngemäß in etwa so machen:
Range(Deckblatt.Cells(Zeile, Spalte 1), Deckblatt.Cells(Zeile, Deckblatt.Columns.Count)).Copy destination:=Excel.Cells(Zeile,Spalte)

Gruß Dieter
RedWraith
RedWraith 10.03.2010 um 13:52:45 Uhr
Goto Top
Hallo Dieter,

Programmintern werden die Bericht als DataTable bzw. DataGridView behandelt, die haben keine .Cells Funktion, weil sie nicht Bestandteil des Objektbaumes von Excel sind.

Ich habe Markus Idee implementiert und der Umweg, die Dateien erst als CSV direkt zu schreiben und dann mit Excel zu konvertieren ist zwar etwas unelegant, ist aber deutlich schneller.


Lösung:
Man speichert das Ganze als CSV, öffnet es im Excel und speichert es dann als XLS. Source ist in etwa folgendes:
csv="test.csv"  
xls="test.xls"  
app = New Excel.Application
wb = app.Workbooks.Open(csv)
ws = wb.Sheets(1)

wb.SaveAs(xls, Excel.XlFileFormat.xlWorkbookNormal)
wb.Close(False)
app.Quit()
io.file.delete(csv)

Danke für die Hilfe !

Tim