Extraire des données selon date du jour par VBA

Bonjour au forum,

J'aimerai pouvoir extraire les données de l'onglet "Import" de chaque ligne (de A à R) ayant la date du jour dans la cellule de la colonne A, et de les coller dans l'onglet "BD_Jour" à partir de la ligne 2.

J'ai essayé ceci (je débute...), mais le temps de traitement est extrêmement long (je peux avoir à traiter plus de 800 000 lignes...), et j'ai régulièrement des plantages divers (ligne 1 de l'onglet destination qui s'efface, collage d'uniquement la dernière ligne de l'onglet source, etc.) :

Sub BDJour()

Dim c, MaPlage As Range
Dim dl1, dl2, dlbd, Ln As Long
Dim ws1, ws2 As Worksheet

Set ws1 = Sheets("Import")
Set ws2 = Sheets("BD_Jour")

dlbd = Sheets("BD_Jour").Range("A" & Rows.Count).End(xlUp).Row
Set MaPlage = ws2.Range("A2:R" & dlbd)

MaPlage.Clear

dl1 = Sheets("Import").Range("A" & Rows.Count).End(xlUp).Row

    For Ln = 11 To ws1.Range("A" & dl1)
        If ws1.Range("A" & Ln) = Date Then
            ws1.Range("A" & Ln & ":R" & Ln).Copy
            ws2.Range("A" & Application.Max(2, Range("A" & Rows.Count).End(xlUp)(2).Row)).PasteSpecial xlPasteValues
        End If
    Next Ln

dl2 = Sheets("BD_Jour").Range("A" & Rows.Count).End(xlUp).Row

    For Each c In Range("A2:A" & dl2)
        If c.Value <> 0 Then
            c.Value = CDate(c) ' Format(Now, "dd/mm/yyyy hh:mm") 'date du jour ou date du jour + heure
        End If
    Next c
    Range("A" & Rows.Count).End(xlUp).Select
    Application.CutCopyMode = False
End Sub  

Auriez-vous une proposition plus fiable et rapide ?

Si vous avez également le temps, l'envie et la patience de m'expliquer ce qui ne va pas dans mon code, ce serait super

Merci d'avance et bonne journée

18fof-v1.xlsm (43.31 Ko)

Bonjour Nico, bonjour le forum,

Peut-être comme ça :

Option Explicit
Option Private Module

Sub test()
Dim OI As Worksheet 'déclare la variable OI (Onglet Import)
Dim OB As Worksheet 'déclare la variable OB (Onglet BD_Jour)
Dim TV As Variant 'déclare la variable TV (Tableau des Valeurs)
Dim NL As Integer 'déclare la variable NL (Nombre de Lignes)
Dim NC As Byte 'déclare la variable NC (Nombre de Colonnes)
Dim I As Integer 'déclare la variable I (Incrément)
Dim J As Byte 'déclare la variable J (incrément)
Dim K As Byte 'déclare la variable K (incrément)
Dim TL() As Variant 'déclare la variable TL (Tableau des Lignes)

Set OI = Sheets("Import") 'définit l'onglet OI
Set OB = Sheets("BD_Jour") 'définit l'onglet OB
OB.Range("A2").CurrentRegion.ClearContents 'efface les éventuelles anciennes valeurs
TV = OI.Range("A10").CurrentRegion 'définit le tableau des valeurs TV
NL = UBound(TV, 1) 'définit le nombre de lignes NL du tableau des valeurs TV
NC = UBound(TV, 2) 'définit le nombre de colonnes NC du tableau des valeurs TV
For I = 2 To NL 'boucle sur toutes les lignes I du tableau des valurs TV (en partant de la seconde)
    'condition : si la date de la donnée ligne I colonne 1 de TV est égale a la date du jour
    If DateSerial(Year(TV(I, 1)), Month(TV(I, 1)), Day(TV(I, 1))) = DateSerial(Year(Date), Month(Date), Day(Date)) Then
        K = K + 1 'incrémente K
        ReDim Preserve TL(1 To NC, 1 To K) 'redimensionne de le tableau des lignes TL (autant de lignes que TV a de colonnes, K colonnes)
        For J = 1 To NC 'boucle 2 sur toutes les colonnes J du tableau des valeurs TV
            TL(J, K) = TV(I, J) 'récupère dans la ligne J de TL la donnée en colonne J de TV (=> Transposition)
        Next J 'prochaine colonne de la boucle2
    End If 'fin de la condition
Next I 'prochaine ligne de la boucle 1
'si K est supérieure à zéro, renvoie le tableau TL transposé dans la cellule A2 redimensionnée de l'onglet OB
If K > 0 Then OB.Range("A2").Resize(K, NC).Value = Application.Transpose(TL)
End Sub

Bonjour ThauThème,

Merci beaucoup pour ta réponse.

Malheureusement, lorsque je lance ta macro, rien ne se passe, sauf la suppression des lignes d'en-tête de l'onglet "BD_Jour" de A1 à R1.

J'en profite pour te remercier infiniment pour les commentaires que tu mets régulièrement sur les codes que tu m'envois (nous envoie...), c'est juste génial pour un débutant comme moi. C'est d'autant plus appréciable vu le temps et l'investissement que ça représente pour toi. Donc, MERCI !

Re,

Je viens de m'apercevoir que je ne t'avais pas signalé quelques anomalies.
• Tout d'abord dans ton exemple il n'y a pas de ligne d'en-tête dans l'onglet BD_Jour donc je n'en ai pas tenu compte dans la macro.
• La ligne Option Private Module fait que la macro n'apparaît pas dans la liste quand je lance la boîte de dialogue Macro ([Alt]+[F8]). Ce n'est pas vraiment une anomalie mais je ne connaissais pas...
• Ensuite après avoir remplacé ton code par le mien, quand j'ai voulu lancer la macro j'ai eu le mot Date avec fond bleu et le message avec :

mes

Cela arrive quand il y a un problèmes de références. Le menu Outil/Références m'affiche :

mes2

J'ai décoché : MANQUANT..., validé et j'ai pu alors lancer la macro directement de l'éditeur VBE (toujours à cause de Option Private Module).

Après tout cela, ça fonctionne. Les fichiers en pièce jointe avant et après la macro :

Re,

• Tout d'abord dans ton exemple il n'y a pas de ligne d'en-tête dans l'onglet BD_Jour donc je n'en ai pas tenu compte dans la macro.

Je m'excuse pour ça, je n'y avais pas pensé...

• La ligne Option Private Module fait que la macro n'apparaît pas dans la liste quand je lance la boîte de dialogue Macro ([Alt]+[F8]). Ce n'est pas vraiment une anomalie mais je ne connaissais pas...

Je l'utilise régulièrement pour éviter que mes collègues lancent une macro qui ne devrait pas être lancée...

J'ai décoché : MANQUANT..., validé et j'ai pu alors lancer la macro directement de l'éditeur VBE (toujours à cause de Option Private Module).

J'ai décoché également et ça fonctionne parfaitement (et ça fonctionne aussi après avoir recoché... ). Merci !

Avec cette extraction dans BD_Jour, j'en fais un TCD que j'aimerais pouvoir envoyer par email à partir d'Outlook (c'est un résumé du stock de la banque de sang que j'envoie à différents médecins pour évaluer les besoins des donneurs, pour info).

Accepterais-tu également de m'aider pour intégrer les informations dans cet email ?

Pour l'envoi de l'email je pense m'en sortir avec ça :

Option Explicit

Private Sub email()

Dim olApp As Outlook.Application
Dim olMail As Outlook.MailItem

   Set olApp = CreateObject("outlook.application")
   Set olMail = olApp.CreateItem(olMailItem)

    With olMail
        .Subject = "Suivi de Stock"
        .To = "blabla@bla.com"
        '.CC = Range("L" & Ligne) 'ou .BCC pour Cci
        .Body = "Bonjour," & vbCrLf & vbCrLf & "Veuillez trouver ci-joint l'état du stock au " & Now & vbCrLf & vbCrLf & "Bonne fin de journée !"
        .Send '.Display
    End With
End Sub

Mais je n'ai absolument aucune idée de comment intégrer joliment le résumé du TCD...

Re,

C'est pas que je refuse, c'est que je ne connais pas du tout, car je ne l'ai jamais utilisé, les code pour envoyer des emails...

Aucun problème, je te remercie déjà pour tout ce que tu as fais, c'est TOP !

Dans le fichier concerné, j'utilise 2 autres codes :

- le 1er pour convertir des données d'un fichier .txt que j'exporte d'un logiciel externe en fichier .xlsx

- le 2nd pour importer ces données (fichier .xlsx) dans mon fichier

Je pense que j'ai fabriqué une petite usine à gaz, malgré que ça fonctionne très bien. Mais c'est long...

Quand je vois la rapidité de ton code par rapport au mien, je pense que je pourrais beaucoup mieux faire...

Sans vouloir t'embêter, tu accepterais d'y jeter un œil ?

Dans le cas où tu serais d'accord, voici mon 1er code, qui permet de transformer mes données de .txt en .xlsx :

Sub transformer()

Dim i%, J%
Dim xl As Excel.Application, wb As Workbook
Dim Fichier
Dim N
Dim flagDate
Dim Contenu
Dim tbl

ChDrive "P"
ChDir "P:\Extraction\" 'chemin par défaut

    Fichier = Application.GetOpenFilename '("Fichiers faux XLS, *.XLS")
    If Fichier = False Then Exit Sub

    N = FreeFile
    Open Fichier For Input As #N 'ouvre de façon classique le fichier en texte

    i = 1 ' ligne début
    flagDate = False 'est mis à false au début pour éviter d'appliquer la transformation de la date à la ligne d'en-tête, dès l'en-tête stocké, il est mis à true pour toutes les autres lignes
    Set xl = CreateObject("Excel.Application")
    xl.SheetsInNewWorkbook = 1
    Set wb = xl.Workbooks.Add
    With wb.Sheets(1)
        Do While Not EOF(1) 'Tant que je ne suis pas à la fin (EndOfFile)
            Line Input #N, Contenu ', je lis le Contenu ligne par ligne ce qui est tout à fait classique aussi sur les fichiers texte
            tbl = Split(Contenu, Chr(9)) 'permet de stocker les données d'une ligne du fichier texte dans un tableau
            .Cells(i, 1).Resize(1, UBound(tbl) + 1) = tbl 'et le reporter en l'état sur une ligne excel
            'If flagDate Then ' sup à la première ligne
                '.Cells(i, 6).Value = DateSerial(Mid(.Cells(i, 6).Value, 7, 4), Mid(.Cells(i, 6).Value, 4, 2), Mid(.Cells(i, 6).Value, 1, 2)) sauf que la première valeur ne donne pas la bonne date, on va alors reprendre cette valeur (ligne i, colonne 1) et lui appliquer ceci
                '.Cells(i, 17).Value = DateSerial(Mid(.Cells(i, 17).Value, 7, 4), Mid(.Cells(i, 17).Value, 4, 2), Mid(.Cells(i, 17).Value, 1, 2)) 'c'est-à-dire qu'on extrait l'année (4 caractères à partir de la position 7), le mois (2 caractères à partir de la position 4) et enfin le jour (2 caractères à partir de la position 1)
                '.Cells(i, 25).Value = DateSerial(Mid(.Cells(i, 25).Value, 7, 4), Mid(.Cells(i, 25).Value, 4, 2), Mid(.Cells(i, 25).Value, 1, 2))
                '.Cells(i, 26).Value = DateSerial(Mid(.Cells(i, 26).Value, 7, 4), Mid(.Cells(i, 26).Value, 4, 2), Mid(.Cells(i, 26).Value, 1, 2))
            'End If
            i = i + 1
            flagDate = True
        Loop
    End With

    Close #N

    wb.SaveAs Filename:="P:\Extraction\" & "Extraction_Stock_" & Format(Date, "yyyy.mm.dd") & ".xlsx"
    Set wb = Nothing
    xl.Quit
    Set xl = Nothing

    MsgBox "Conversion de fichier terminée !" & Chr(10) & "Sélectionner maintenant le fichier au format .xlsx à importer." _
    & Chr(10) & "Ce fichier se trouve dans le dossier : P:\Extraction\", vbInformation, "Conversion terminée !"

End Sub

Et le second, qui permet d'importer les données du fichier .xlsx convertit :

Sub Copy()

    Dim dl1 As Long, dl2 As Long, dl3 As Long 'déclaration des dernières lignes
    Dim pl1 As Long 'déclaration de la première ligne
    Dim wb1 As Workbook, wb2 As Workbook 'déclaration des classeurs
    Dim ws1 As Worksheet, ws2 As Worksheet 'déclaration des feuilles
    Dim Suppr As String
    Dim C As Range

    Call NettoyerPressPapiers
    Call NettoyerCacheTablePivot

If MsgBox("Veuillez sélectionner le fichier d'extraction Inlog au format .txt des données brutes à convertir." _
& Chr(10) & "Ce fichier se trouve dans le dossier : P:\Extraction\", vbInformation + vbOKCancel, "Convertion du .txt en .xlsx") = vbCancel Then
Exit Sub

Else:

    Call transformer

On Error GoTo Erreur 'si erreur, va directement à Erreur en fin de code

    ChDrive "P"
    ChDir "P:\Extraction\" 'chemin par défaut

    Set wb1 = ThisWorkbook 'définition du classeur 1 (ce classeur)
    Set ws1 = wb1.Sheets("Import") 'définition de la feuille 1 (Import de ce classeur)
    Set wb2 = Workbooks.Open(Application.GetOpenFilename) 'définition du classeur 2 (classeur à importer)
    Set ws2 = wb2.Worksheets(1) 'définition de la feuille 2 (1er feuille du classeur à importer)

    dl1 = ws1.Range("B" & Rows.Count).End(xlUp).Row + 1
    dl2 = ws2.Range("A" & Rows.Count).End(xlUp).Row

If MsgBox("Voulez-vous réellement importer les données de stock ?", vbQuestion + vbYesNo, "Importation") = vbNo Then
    wb2.Close False
Exit Sub

Else:

Application.ScreenUpdating = False

    ws1.Unprotect ""
    ws2.Range("A2:P" & dl2).Copy
    ws1.Range("B" & dl1).PasteSpecial Paste:=xlPasteValues
    wb2.Close False

    With ws1

    dl3 = ws1.Range("B" & Rows.Count).End(xlUp).Row

        For Each C In Range("A11:A" & dl3)
            If C.Value = 0 Then
                C = Date ' Format(Now, "dd/mm/yyyy hh:mm") 'date du jour ou date du jour + heure
            End If
        Next C

        'For Each c In Range("A11:A" & dl3)
        '    If c.Value <> 0 Then
        '        c = CDate(Mid(c, 1, 10)) ' extrait 10 caractères à partir de la position 1 de la valeur de c et transforme en Date
        '    End If
        'Next c

        For Each C In Range("R11:R" & dl3)
            If Mid(C.Offset(0, -8), 1, 2) = "D+" Then
                C.Value = "RhD+"
            ElseIf Mid(C.Offset(0, -8), 1, 2) = "D-" Then
                C.Value = "RhD-"
            Else
                C.Value = "RhD inconnu"
            End If
        Next C

        '.Range("A11:A" & dl3).NumberFormat = "dd/mm/yyyy"
        .Range("B11:B" & dl3).NumberFormat = "@"
        .Range("C11:C" & dl3).NumberFormat = "@"
        .Range("D11:D" & dl3).NumberFormat = "@"
        .Range("E11:E" & dl3).NumberFormat = "@"
        .Range("F11:F" & dl3).NumberFormat = "dd/mm/yyyy"
        .Range("G11:G" & dl3).NumberFormat = "@"
        .Range("H11:H" & dl3).NumberFormat = "@"
        .Range("I11:I" & dl3).NumberFormat = "@"
        .Range("J11:J" & dl3).NumberFormat = "@"
        .Range("K11:K" & dl3).NumberFormat = "@"
        .Range("L11:L" & dl3).NumberFormat = "@"
        .Range("M11:M" & dl3).NumberFormat = "0"
        .Range("N11:N" & dl3).NumberFormat = "0"
        .Range("O11:O" & dl3).NumberFormat = "@"
        .Range("P11:P" & dl3).NumberFormat = "0"
        .Range("Q11:Q" & dl3).NumberFormat = "dd/mm/yyyy"
        '.Range("R11:R" & dl3).NumberFormat = "@"
        .Range("A11:R" & dl3).WrapText = True
        .Range("A11:R" & dl3).HorizontalAlignment = xlCenter
        .Range("A11:R" & dl3).VerticalAlignment = xlCenter
        .Range("A11:R" & dl3).EntireRow.AutoFit
        .Range("A11:R" & dl3).Borders.Value = 1
        .Range("A11:R" & dl3).Borders(xlEdgeLeft).Weight = xlThick
        .Range("A11:R" & dl3).Borders(xlEdgeRight).Weight = xlThick
        .Range("A11:R" & dl3).Borders(xlEdgeTop).Weight = xlMedium
        .Range("A11:R" & dl3).Borders(xlEdgeBottom).Weight = xlThick
        .Range("A11:R" & dl3).Sort key1:=Range("A11"), Order1:=xlAscending
        .Range("A11:R" & dl3).Locked = True
        .Protect "x1pdzx2a", True, True, False, AllowFormattingCells:=False, _
            AllowSorting:=True, AllowFiltering:=True, AllowUsingPivotTables:=True
    End With
End If
End If

Call NettoyerPressPapiers
Call NettoyerCacheTablePivot

Suppr = Dir("P:\Extraction\*.*")
    Do While Suppr <> ""
        Kill "P:\Extraction\" & Suppr
        Suppr = Dir
    Loop

Application.ScreenUpdating = True

MsgBox "L'import a été effectué avec succès !", vbInformation, "Importation réussie !"

Exit Sub 'Permet de sortir de la procédure et évite la gestion d'erreur (Erreur), si la macro
's'est déroulée sans encombre.
Erreur:

Suppr = Dir("P:\Extraction\*.*")
    Do While Suppr <> ""
        Kill "P:\Extraction\" & Suppr
        Suppr = Dir
    Loop

MsgBox "Aucun fichier sélectionné !", vbExclamation, "Annulation !"
ws1.Protect "", True, True, False, AllowFormattingCells:=False, _
            AllowSorting:=True, AllowFiltering:=True, AllowUsingPivotTables:=True
End Sub

Bon c'est énorme en relisant tout ça, donc je comprendrais parfaitement que tu n'ai pas envie de te lancer là dedans !

Rechercher des sujets similaires à "extraire donnees date jour vba"