0
votes

Comment puis-je améliorer l'efficacité de ma boucle pour une application importante

J'ai créé un grand programme VBA pour automatiser la création d'une table de données nécessaire pour exécuter des traceurs dans un fichier Excel. Alors que la boucle fonctionne bien pour créer ce dont j'ai besoin. La boucle principale prend une heure pour créer la liste des noms de sociétés dont j'ai besoin. Je me demandais s'il y a un moyen d'améliorer le temps qu'il faut pour la boucle à compléter. J'ai 191 rangées qui doivent être copiées et ensuite collées 68 fois chacune dans la nouvelle feuille. J'ai essayé quelques approches différentes pour améliorer le temps et avoir seulement réduit le temps nécessaire à environ 50 minutes environ. Toute aide serait très appréciée. Je sais que l'utilisation de Select est horrible pour l'efficacité du temps, mais toutes les autres options que j'ai essayées n'ont pas bien fonctionné. xxx

vba

4 commentaires

Vous auriez bonne chance sur Codereview pour les questions d'optimisation. Cependant, si vous vous débarrassez de la copie et de la pâte et que vous venez de vider les valeurs directement, cela réduira considérablement le temps d'exécution.


Pour commencer, do application.screenupdating = false avant la boucle et application.screenupdature = true après la fin de la boucle.


J'ai oublié d'ajouter cela dans le code, c'est là. Qui a sauvé environ 5 min.


Aussi lire ce Stackoverflow .Com / Questions / 10714251 / ... et vous pouvez faire le colle en une fois sans boucle ni mieux suivre la suggestion de la Warcupine.


3 Réponses :


0
votes

Veuillez supprimer les dernières feuilles ("Données d'entrée"). Sélectionnez - Cela n'est pas nécessaire, car la boucle commence avec cela.
Deuxièmement, la boucle interne de la boucle peut être remplacée par cette opération qui remplit une plage de lot: xxx

Je pense que cela devrait être plus rapide, mais d'autres ajustements peuvent être nécessaires.


0 commentaires

0
votes

Au lieu de copier et coller des cellules, lisez-les une fois dans la mémoire dans une matrice à 2 dimensions et écrivez le tableau dans la destination. Cela accélère considérablement le processus.

inconvénient (ou avantage, en fonction de vos besoins): seules les valeurs sont copiées. P>

call CopyRangeSheets(rng, ThisWorkbook.Sheets("TrialSheet").Range("A1"), 68)


0 commentaires

0
votes

Étant donné qu'aucune information n'était disponible sur la taille de la gamme source en cours de copie

après la suite des zones grises de la question est supposée comme suit p>

  1. depuis 191 lignes x 68 copie x 3 colonnes prennent environ 10 minutes seulement (avec votre code), la plage est d'environ 191 lignes x 15 colonnes de taille p> li>

  2. Comme il a été prétendu que le code fonctionne correctement. Les cellules de la plage (indépendamment de leurs positions de ligne ou de colonne) sont copiées dans la colonne A uniquement (ci-dessous l'une et l'autre). Bien qu'il contredit la déclaration "automatiser la création d'une table de données" p> li>

  3. car les cellules des gammes sont copées et collées. Dans les formules de cas d'essai, les formules sont copiées uniquement. P>

    Le code ci-dessous répliquera donc simplement ce que votre code fait avec une efficacité accrue. Personnellement, je ne préfère pas conserver les calculs, le traitement des événements et la mise à jour de l'écran (dans des cas normaux), je n'ai pas ajouté que les lignes standard. Cependant, vous pouvez utiliser ces techniques standard, en fonction de la condition de fichier de travail. Effectuez les modifications nécessaires concernant la plage, etc. P> li> ol>

    code ne prend que 2-3 secondes à remplir avec 191 lignes X 15 Colonnes x 68 Copies: P>

    Sub test()
    Dim SrcWs As Worksheet, DstWs As Worksheet, SrcArr As Variant
    Dim Rng As Range, cell As Range, DstArr() As Variant
    Dim X As Long, Y As Long, Z As Long, i As Long, LastRow As Long
    Dim Chunk60K As Long
    Dim tm As Double
    tm = Timer
    Set SrcWs = ThisWorkbook.Sheets("Input Data")
    Set DstWs = ThisWorkbook.Sheets("TrialSheet")
    
    Set Rng = SrcWs.Range("A1:O191")
    SrcArr = Rng.Formula
        
    LastRow = DstWs.Cells(Rows.Count, "A").End(xlUp).Row + 1
    Chunk60K = 0
    Z = 1
        For X = 1 To UBound(SrcArr, 1)
        For Y = 1 To UBound(SrcArr, 2)
        For i = 1 To 68
            ReDim Preserve DstArr(1 To Z)
            DstArr(Z) = SrcArr(X, Y)
        
            If Z = 60000 Then  ' To Overcome 65K limit of Application.Transpose
            DstWs.Range("A" & Chunk60K * 60000 + LastRow).Resize(UBound(DstArr, 1), 1).Formula = Application.Transpose(DstArr)
            Chunk60K = Chunk60K + 1
            Z = 1
            ReDim DstArr(1 To 1)
            Debug.Print "Chunk: " & Chunk60K & " Seconds Taken: " & Timer - tm
            Else
            Z = Z + 1
            End If
        
        Next i
        Next Y
        Next X
    
    If Z > 1 Then DstWs.Range("A" & Chunk60K * 60000 + LastRow).Resize(UBound(DstArr, 1), 1).Formula = Application.Transpose(DstArr)
    
    Debug.Print "Seconds Taken: " & Timer - tm
    End Sub
    


0 commentaires