Etirer des sélection dans une macro et sélectionner une ligne

Bonjour,

Tout d'abord désolé pour le titre un peu flou mais tout va s'éclairer dans mon explication (enfin je l'espère)

J'ai à ma disposition des dates qui ont un pas de temps de 15min en colonne A et des données en colonne B.

Mon but est de faire des moyennes journalières et par pas de temps de 6H dans ces données. Et j'y arrive !

Étant donné que j'ai beaucoup de fichier à traiter je me suis que j'allais faire une macro. Et la macro marche !

Mais j'ai quand même un problème : la macro ne marche que quand j'ai des données sur 19506 lignes exactement.

Alors mon but serait de modifier mes deux macros ("moyenne_6h" et "Moyenne_jour") pour que ces macros tournent pour 10 ou 50.000 lignes. Et donc que la macro s'adapte aux données en input.

Mais voilà, je n'y arrive pas.

Vous trouver ci-dessous le fichier excel avec les deux macros. Bon le fichier est un peu moche maintenant j'ai dû supprimer des données pour vous l'envoyer, il était trop volumineux.

J'ai annoté les macros pour que tout le monde puisse comprendre à quoi serve chaque partie des macros. Et j'ai indiqué aussi les endroits où je pense qu'il y a un problème.

PS : les boutons pour lancer les macros sont aux colonnes O et P, mon but est de créer une nouvelle feuille de calcul et mettre les boutons dedans. Le problème est que quand je fais ça mes macros ne marchent plus car je change d' active sheet. Serait-il possible de me dire en plus se que je dois rajouter dans la macro pour retourner sur la bonne feuille.

Merci d'avance pour votre aide.

11fichier-exp.xlsm (696.37 Ko)

Bonjour Sankreet, bonjour le forum,

La regle d'or en VBA c'est d'éviter autant que possible les Activate/Select inutiles qui sont source de bugs et ralentissent considérablement l'exécution du code. La fin de ton code, à partir de la petite magouille, je n'ai pas compris où tu voulais en venir. Pour cette partie :

Sub Moyenne_jour()
'
' Moyenne_jour Macro
'

'
    ActiveCell.FormulaR1C1 = ""
    Range("A2").Select
    Selection.End(xlDown).Select 'ici je voudrais sélectionner la dernière valeur de la colonne
    Range("D19506").Select 'ici se déplacer dans la colonne au même niveau que la dernière ligne de la colonne A
    ActiveCell.FormulaR1C1 = "a" 'marqueur de fin de colonne
    Selection.End(xlUp).Select
    Range("D2").Select
    ActiveCell.FormulaR1C1 = "=INT(RC[-3])"
    Range("D2").Select
    Selection.Copy
    Range(Selection, Selection.End(xlDown)).Select
    ActiveSheet.Paste

    'le but de cette première partie est d'appliquer
    'la fonction ENT à toutes les données de
    ' la colonne A dans la colonne D
    '

    Range("E2").Select
    Application.CutCopyMode = False
    ActiveCell.FormulaR1C1 = "=DATEDIF(RC[-4],R[19504]C[-4],""d"")"

Voila ce que je te propose :

Sub Moyenne_jour() ' Moyenne_jour Macro
Dim C As Worksheet
Dim DL As Long

Set C = Worksheets("Calcul")
DL = C.Cells(Application.Rows.Count, "A").End(xlUp).Row 'définit la dernière ligne édité DL de la colonne A de l'onglet C
C.Cells(DL + 1, "D") = "a" 'marqueur de fin de colonne
C.Range("E2").FormulaR1C1 = "=DATEDIF(RC[-4],R[" & DL - 2 & "]C[-4],""d"")"
C.Range("F2").FormulaR1C1 = "=RC[-1]+2"

Bonjour,

On ne t'a jamais dit que sans bouger on se fatiguait moins ! C'est pareil avec VBA, au lieu de lui courir après à coup de Select, ce qui le ralentit, tu le laisses faire, et tu ne cherches pas non plus à l'espionner, si tu lui as donné de bonnes instructions, il va faire, vite et bien !

On fait donc disparaître tous les Select, et autres éléments qui relèvent de l'espionnite (Windows et autres mouvements...), on ne copie pas non plus (trop long !), et voilà ta première macro :

Sub copie_feuille()
    Dim wsC, n&, i%
    wsC = Array("Pas de temps de base", "Pas de temps journalier", "Pas de temps de 6h")
    With Worksheets("Calcul").Range("A1").CurrentRegion
        n = .Rows.Count
        For i = 0 To 2
            Worksheets(wsC(i)).Range("A1").Resize(n, 2).Value = _
             .Offset(, i * 6).Resize(, 2).Value
            Worksheets(wsC(i)).Range("A1").Resize(n).NumberFormat = "d/m/yy h:mm"
        Next i
    End With
End Sub

Et là, tu te mets où tu veux pour la lancer, tu peux même masquer la feuille, elle va faire...

Reste à voir maintenant si c'était utile pour ce que tu veux faire, ce que je n'ai pas encore regardé.

Re, Salut ThauThème !

Bon ! J'ai perdu un peu de temps avec tes facéties de données aléatoires qui m'ont fait me demander pourquoi mes chiffres variaient, rendant toute vérification impossible...

Ne voyant pas l'utilité de la colonne D, ni de E2, ni de F2, je crois que l'on peut se borner à mettre en G les valeurs dates nécessaires, et en H les résultats, en éliminant les formules.

C'est bien les résultats qu'on veut, non ?

Sub Moyenne_jour()
    Dim PlgS As Range, d1 As Date, d2 As Date, j%, fm$
    With Worksheets("Calcul")
        With .Range("A1").CurrentRegion.Resize(, 1)
            d1 = Int(.Cells(2, 1))
            d2 = Int(.Cells(.Rows.Count, 1))
            Set PlgS = Range(.Cells(2, 1), .Cells(.Rows.Count, 1))
        End With
        fm = "=AVERAGE(IF(INT(" & PlgS.Address(, , xlR1C1) & ")=RC[-1]," _
         & PlgS.Offset(, 1).Address(, , xlR1C1) & "))"
        With .Range("G2")
            Do While d1 + j <= d2
                .Offset(j) = d1 + j
                .Offset(j, 1).FormulaArray = fm
                .Offset(j, 1) = .Offset(j, 1).Value
                j = j + 1
            Loop
        End With
    End With
End Sub

Comment qu'on fait ?

D'abord on se réfère à la feuille Calcul, avec With VBA place sa référence en mémoire et pourra y accéder sans perte de temps...

On se réfère ensuite dans cette feuille à la colonne A utile, soit comportant des données (voir dans le code). On y prélève la date de début des données, et la date de fin des données. Avec ces 2 dates, on sait de quelle date à quelle date on devra opérer, sans autre calcul inutile en D, E, F !

Et pour faciliter la suite, on affecte la plage sur laquelle s'opère le calcul à une variable Range. Plus exactement la plage de dates PlgS, la plage de valeurs s'atteindra aisément par PlgS.Offset(, 1).

Ceci fait on va pouvoir poser nos dates utiles en G, mais auparavant on prépare la formule de calcul qu'on utilisera pour obtenir le résultat voulu.

Formule du type :

=MOYENNE(SI(ENT(PlageSourceDates)=CelluleDateEnG;PlageSourceDatesDécaléede1Col))

Formule matricielle qu'on compose dans les règles, en style L1C1...

Je t'accorde que c'est un peu moins facile à faire qu'enregistrer une formule... mais là on sait exactement ce qu'on fait !

On ajuste notre référence à G2, première cellule à servir. On y met la première date, et on va l'incrémenter sur les cellules suivantes (en G) à l'aide d'une variable j, initialement à 0.

On utilise pour cela une boucle Do... Loop, qui s'interrompra lorsqu'on aura atteint la date de fin.

A chaque tour de boucle :

on prend la cellule décalée en ligne de j (au premier tour, j = 0, il s'agit donc de G2)

on y place la date : d1+j (au premier tour, elle sera = à d1)

dans la cellule voisine, décalée en ligne de j et de 1 colonne, on place la formule (qu'on a préparée) en utilisant FormulaArray car il s'agit d'une formule matricielle

la formule ayant renvoyée son résultat, on l'écrase au profit de ce résultat

on incrémente j pour passer à la ligne suivante.

Et au final, on aura juste les résultats souhaités en G et H.

Cordialement.

Pour des pas de 6h, on n'a plus qu'à faire de même, en utilisant PLANCHER et des pas de 0.25...

Sub moyenne_6h()
    Dim PlgS As Range, d1 As Date, d2 As Date, j%, fm$
    With Worksheets("Calcul")
        With .Range("A1").CurrentRegion.Resize(, 1)
            d1 = WorksheetFunction.Floor(.Cells(2, 1), 0.25)
            d2 = WorksheetFunction.Floor(.Cells(.Rows.Count, 1), 0.25)
            Set PlgS = Range(.Cells(2, 1), .Cells(.Rows.Count, 1))
        End With
        fm = "=AVERAGE(IF(FLOOR(" & PlgS.Address(, , xlR1C1) & ",0.25)=RC[-1]," _
         & PlgS.Offset(, 1).Address(, , xlR1C1) & "))"
        With .Range("M2")
            Do While d1 + j * 0.25 <= d2
                .Offset(j) = d1 + j * 0.25
                .Offset(j, 1).FormulaArray = fm
                .Offset(j, 1) = .Offset(j, 1).Value
                j = j + 1
            Loop
        End With
    End With
End Sub

Cordialement.

Salut Thauthème et Salut MFerrand !

Tout d'abord merci pour vos réponses !

J'ai essayé tes codes ça marche niquel merci beaucoup !

J'avais fais des programme lourd et pas optimisé pour deux raisons :

  • La première : je suis débutant en VBA et je galère encore avec le langage ^^
  • La deuxième : je dois être capable de comprendre ce programme et de pouvoir l'expliquer à d'autres personnes qui s'en servirons sans avoir aucune base en VBA

Si ça vous convient je ne vais pas clore le sujet tout de suite car dans l’après-midi je vais travailler sur les programme pour comprendre l'utilité de chaque ligne de code. Et je reviendrai vers vous si je ne comprends pas en utilisant vos explications et internet. (mon but est quand même de progresser et de finir par me débrouiller par moi même).

Encore merci à vous deux.

Bonjour,

(mon but est quand même de progresser et de finir par me débrouiller par moi même).

Mon soutien est pleinement acquis sur cet objectif !

Pour utiliser, on n'a pas besoin de démonter tout le mécanisme.

Par contre, pour l'adapter, le modifier, et le cas échéant le construire, il faut comprendre ce que l'on fait...

VBA utilise 2 sortes de composants (principaux) :

  • les éléments du langage Visual Basic,
  • les composants Excel (lorsque l'application est Excel) [on dit : le modèle d'objets Excel].
L'enregistreur est limité, en ce sens qu'il ne fait que reproduire des opérations effectuées manuellement, dont beaucoup n'ont pas besoin d'être programmées parce que superflues, sinon parasites, telles celles qui relèvent de sélections (incontournables en manuel mais inutiles en programmation), et d'autres qui peuvent être réalisées autrement que de la façon manuelle (qui ne peuvent donc être enregistrées).

Il puise dans la bibliothèque Excel, mais quasiment pas dans la bibliothèque VBA, laquelle relève de choix du programmeur et nécessite quelques rudiments en matière de programmation VBA.

Cordialement.

Rechercher des sujets similaires à "etirer selection macro selectionner ligne"