2009-10-09 7 views
0

Je dois générer environ 800 fichiers Excel à partir d'une base de données d'accès.lente exportation de l'accès à Excel

Pour les 10-15 premiers, ça marche bien, quelques secondes/fichier Excel mais ça prend toujours plus de temps, au 150ème fichier Excel, ça prend 10 minutes.

Voici mon code:

Il fait cela pour chaque nrliste dans la table d'accès (environ 800 d'entre eux)

Dim lista = From ls In Liste _ 
         Where ls!Concatenare = nrliste(i) _ 
        Select ls 
      Dim table = lista.CopyToDataTable 
      Dim DataArr(table.Rows.Count, 30) 

      For x = 0 To table.Rows.Count - 1 
       For y = 0 To 30 
        DataArr(x, y) = table.Rows(x).Item(y) 
       Next 
      Next 


      Dim filetocopy As String 
      Dim newcopy As String 
      Dim tempname As String = nrliste(i).ToString 
      Dim filename As String = "LISTA INV OBI(MF) LA 30.09.2009_" & tempname.Replace("#", "_") 
      filetocopy = Environment.CurrentDirectory & "\MACHETA.xls" 
      newcopy = FolderBD.SelectedPath & "\" & filename & ".xls" 
      If System.IO.File.Exists(newcopy) = True Then 
       System.IO.File.Delete(newcopy) 
       System.IO.File.Copy(filetocopy, newcopy) 
      Else 
       System.IO.File.Copy(filetocopy, newcopy) 
      End If 

      'excel file 
      Dim xlWBook As Excel.Workbook = xlApp.Workbooks.Open(newcopy) 
      Dim xlSheet As Excel.Worksheet = CType(xlWBook.Worksheets("Lista inventar OBI de natura MF"), Excel.Worksheet) 

      'insereaza liniile necesare 
      For n = 11 To ((lista.Count - 1) + 11) 
       With xlSheet 
        .Rows(n).Insert(Excel.XlDirection.xlDown, 1) 
       End With 
      Next 

      'copiaza datele 

      With xlSheet 

       .Range(.Cells(11, 1), .Cells(table.Rows.Count + 11, 31)).Value = DataArr 

      End With 
+0

Voir la réponse modifiée de moi ci-dessous. Merci!! – shahkalpesh

Répondre

1

au lieu des lignes Insérer je vais essayer de faire CopyFromRecordset un ensemble d'enregistrements. Vous devrez essentiellement retravailler votre logique bien sûr.

Mais surtout, où fermez-vous l'objet feuille de calcul Excel une fois que vous avez terminé?

+0

ok, avec copie du jeu d'enregistrements j'ai exporté environ 400 fichiers en 4 minutes, c'est une méthode très très rapide, merci – Iulian

0

Je ne sais pas, mais je regardais combien de fichiers finissent par avoir ouvert dans Excel tous en même temps. Fermez-vous les fichiers une fois que vous avez fini de les écrire? Peut-être que cela les maintient ouverts, alors au moment où la feuille de travail 150'th est ouverte, il pourrait être difficile pour l'utilisation de la mémoire. Aussi, je dirais, essayez de passer par le code dans un débogueur, et voir quel bit est lent (ou ralentir au fil du temps) - cela aidera à affiner la cause du problème.

+0

merci pour la suggestion, j'ai intensifié avec le débogueur et cela prend beaucoup de temps dans cette déclaration LINQ: Dim lista = De ls Dans Liste _ Où ls Concatenare = nrliste (i) _ Sélectionnez ls This! est où est l'obtention des lignes de la table d'accès pour l'exportation. Je n'ai aucune ideea comment je peux faire ceci plus rapidement. – Iulian

1

Fermez-vous le classeur une fois que vous avez terminé (dans la boucle)?

xlWBook.Close 
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWBook) 

Regardez fil this, qui explique la nécessité de libérer toutes les interfaces COM.

EDIT: J'ai vu vos commentaires, en réponse à @ 1800 Information.

Dim lista = From ls In Liste _ 
         Where ls!Concatenare = nrliste(i) _ 
        Select ls 

Que fait cette requête linq?

EDIT2: Essayez d'exécuter le SQL dans MS-Access pour voir comment il fonctionne? En outre, je vais suggérer de rejeter LINQ pour l'instant & utiliser l'ancien objet de commande ADO.net simple avec une requête paramétrée. Sinon, un simple moyen & serait de tirer tous les enregistrements (où ID entre votre valeur min et max) dans un DataTable et de le filtrer en mémoire et de faire un transfert direct (sans utiliser tableau et éviter d'écrire des valeurs rangée par rangée, cellule par cellule).

Je vais essayer de trouver, si c'est possible. (c'est-à-dire utiliser un ensemble de données filtré et l'écrire dans un fichier Excel).

Espérons que cela vous donne, un indice sur la façon de procéder.

+0

il est de sélectionner les données de la table d'accès où concatenare (une colonne dans la table d'accès) = liste (i) (critères de sélection - je vais de 0 à 768) – Iulian

+0

merci pour les suggestions, je vais les essayer dès comme je peux – Iulian

1

Vous pouvez essayer d'utiliser un tableur de transfert Docmd comme cela devrait être plus rapide

DoCmd.Transferspreadsheet .... 

Ensuite, vous pouvez toujours ouvrir le fichier en utilisant l'automatisation Excel après

+0

j'ai une autre application où j'utilise la feuille de calcul de transfert docmd mais il me semble plus lent, je vais essayer. – Iulian

+0

Il devrait être plus rapide de loin, car ce n'est pas un séquentiel, mais une opération par lots. Et vous n'avez pas le temps d'automatiser une deuxième application Office lourde - il écrit le fichier directement en utilisant Jet/ACE. –

-1

Un rapide coup d'oeil à votre code me fait remettre en question l'appel à .Rows (n) .Insert (Excel.XlDirection.xlDown, 1) pour chaque ligne. Vous devriez pouvoir appeler Insérer une fois pour toutes les lignes. Insérer des lignes dans une feuille de calcul est coûteux même si vous insérez simplement 1 ligne - surtout si vous insérez dans une grande feuille de calcul ou dans un classeur avec beaucoup de formules.

accélère généralement des applications telles que la vôtre (vous pouvez voir quelques citations confirmant ce here - sur le côté droit de la page). SpreadsheetGear a également une méthode IRange.CopyFromDataTable de sorte que vous n'aurez pas à copier les données dans un tableau temporaire.L'API SpreadsheetGear est similaire à l'API d'Excel. La conversion de votre code est donc simple. Vous pouvez télécharger un essai gratuit here si vous voulez l'essayer.

Disclaimer: Je possède SpreadsheetGear LLC

+0

Quel est l'avantage de votre produit par rapport à TransferSpreadsheet pour un cas comme celui-ci où l'automatisation n'est pas utilisée pour effectuer un formatage spécial des données de sortie? –

+0

Il me semble de la publication originale que chaque ensemble d'enregistrements est inséré en haut d'un classeur (je pourrais avoir mal compris) de VB.NET. Ma réponse est à ce message original. Je ne suis pas familier avec DoCmd.TransferSpreadsheet donc je ne peux pas commenter sur la façon dont SpreadsheetGear se compare à elle. –

+0

Je n'ai pas vu la réponse ici quand elle a été postée à l'origine. Je suis downvoting parce qu'il montre que la réponse originale était un drive-by, puisque l'affiche professe l'ignorance complète de la solution alternative. –

Questions connexes