Compter des plages de cellule variable

Bonsoir à tous,

Merci de jeter un œil dans le fichier joint... RESULTAT.xlsx

Il s'agit de résultat effectué sur Excel+VBA pour optimiser des panneaux ((Ligne 2 à 6) dans un panneau de 2500 mm de long on peut mettre 3 modules de 674 + 1 module de 374 + 1 module de 104).

Chaque ligne est faite par une mise en forme conditionnelle.

Bien sûr le nombre de module dans un panneau peut varier en fonction des demandes de coupes ! (Comme dans le 4ème panneau).

Actuellement j'utilise une formule matricielle =SI(D6="";"";NB.SI.ENS(D:D;D6;C:C;C6)) qui fonctionne en partie les critères ne sont pas adaptés, car par exemple le 2ème et 3ème panneaux sont comptés comme égaux (cause les critères) alors qu'ils ne le sont pas.

Tous ça pour obtenir une feuille de synthèse pour découpe pour un atelier( Exemple: 10 panneaux comme le N°1, 3 panneau comme le N°2, etc...) . sachant qu'il peut y avoir 8000 lignes.

Merci de m'aider à trouver une solution Excel ou +VBA

25resultat.xlsx (173.72 Ko)

Hummm

Excel + CBA avec un fichier joint au format xlsX ?

plus de VBA alors

Bonsoir,

veuillez joindre un fichier avec du VBA soit une extension de la forme xlsM, merci

@ bientôt

LouReeD

Bonsoir quel rapidité !

Il s'agit d'un code que j'ai adapter pour moi avec des difficultés sans jamais avoir pratiquer le VBA !

Ce qui permet d'avoir ce résultat est...

' Optim 2015
Dim K1 As Integer, K2 As Integer, K3 As Integer, K4 As Integer, n As Integer, k As Integer
Dim TVAL(8000) As Long, TQ(8000) As Long, TLib(8000) As String     ' dim 8000
Dim TSol(8000) As Long    ' Solution pour la barre étudiée      ' Dim 8000
Dim TNoeud(8000) As Integer ' N° de ligne du Noeud étudié
Dim TTOT(8000) As Long    ' Longueur Totale jusqu'à ce Noeud
Dim TAux(100) As Long     ' tableau de valeurs auxiliaires      ' dim 100
Dim NomFeuille As String, AERR As String
Dim ChuteAcceptable As Long, LongueurBarres As Long, Morceau As Long, TOTAL As Long, CHUTE As Long
Dim A1 As Variant, LigneBas As Integer

Sub Découpe35V()
' 1°) Préparation des données
' 2°) Trouver une bonne solution
'  Les différentes solutions sont considérées comme
'       les Noeuds d'une arborescence
'       dont on examine toutes les branches.

    Mess0 = "Découpe Linéaire": MessF = "Travail Terminé"
    On Error GoTo NIVERR
' =============================================================
' 1°) Préparation des données et Constantes
    K1 = 1  ' colonne des dimensions
    K2 = 2  ' colonne des quantités par dimension
    K3 = 3  ' colonne des libellés
    K4 = 5  ' colonne des paramètres

' 1-1) Contrôle des données
    NomFeuille = ActiveSheet.Name
    If Cells(1, K1) < "A" Then GoTo NIVERR1
    LigneDébut = 2: A1 = Cells(LigneDébut, K1)
    If IsNumeric(A1) = False Then GoTo NIVERR1
    LongueurBarres = Cells(2, K4)
    If LongueurBarres = 0 Then GoTo NIVERR1
    ChuteAcceptable = Cells(3, K4)
    If ChuteAcceptable > LongueurBarres / 2 Then GoTo NIVERR1

'1-2) Report dans la feuille Travail_35V
    KK = 9   ' colonne cumuls. ATTENTION modifier aussi dans Report( )

' Lecture des données
    n = 1
NIV1:
    n = n + 1: Morceau = Cells(n, K1): If Morceau = 0 Then GoTo NIV12
    If Morceau > LongueurBarres Then GoTo NIVERR4
    If n > 101 Then GoTo NIVERR2
    Q = Cells(n, K2): If Q < 1 Then Q = 1
    TVAL(n) = Morceau: TQ(n) = Q: TLib(n) = Cells(n, K3)
    GoTo NIV1
NIV12:
    LigneBas = n - 1
    For n = LigneBas + 1 To 8000                         ' sécurité
        TVAL(n) = Empty: TQ(n) = Empty: TLib(n) = Empty
        Next n

' report dans la feuille Travail_35V
    Sheets("Travail_35V").Select
    Cells(4, KK + 1) = "Recherche en cours"
    Cells(6, KK) = NomFeuille

    Columns("A:B").Select: Selection.ClearContents
    Range("A1").Value = Sheets(NomFeuille).Range("A1").Value
    Range("B1").Value = Sheets(NomFeuille).Range("C1").Value

    LigneFin = 1
    For n = 2 To LigneBas: Morceau = TVAL(n)
        If LigneFin > 8000 Then GoTo NIVERR3
        For k = 1 To TQ(n): LigneFin = LigneFin + 1
            Cells(LigneFin, 1) = Morceau
            If k = 1 Then Cells(LigneFin, 2) = TLib(n)
            Next k
        Next n
    Cells(2, KK) = LigneFin - LigneDébut + 1

'1-3) Tri
    Columns("A:B").Select
    Selection.Sort Key1:=Range("A2"), Order1:=xlDescending, Header:=xlGuess, _
        OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
' Contrôle sur la plus petite dimension demandée
    If ChuteAcceptable > Cells(LigneFin, 1) Then GoTo NIVERR1
'1-4) on double la colonne A dans la colonne K
    Columns("A").Copy
    Columns("K").Select
    ActiveSheet.Paste
    Application.CutCopyMode = False
    Cells(1, 11) = ""

'1-5) Vidage de l'ancienne solution, colonnes C-D-E-F
    Range("C1:H1").Select
    Selection.Cut Destination:=Range("AC1:AH1")
    Columns("C:H").Select
    Selection.ClearContents
    Range("AC1:AH1").Select
    Selection.Cut Destination:=Range("C1:H1")
    NombreBarres = 0: Cells(3, KK) = NombreBarres

'1-6) tableaux de travail_35V
     TAux(1) = 0  'Nombre de solutions testées par barre
     TAux(2) = 0  'Nbre de solutions améliorées
     TAux(3) = LigneFin * LigneFin  ' Limitateur de bouclage
    If LigneFin > 50 Then TAux(3) = 4 * LigneFin
    LigneReport = 1         ' ligne de report des résultats
    Cells(5, KK) = TAux(1)        ' Nombre de solutions

' ============================================================
' 2°) C'est parti !

' essai du sous-programme Report()
'    TSol(1) = 2: TSol(2) = 4
'    Call Report(TSol, 2, LigneReport, NombreBarres, LongueurBarres, LigneFin, TAux)

' début du suivi de l'arborescence
NIV2:
    AERR = "NIV2:"
    If LigneFin < LigneDébut Then Range("A1").Select:  GoTo FINI

' 2-1) On prend le 1er morceau
    TSol(1) = 2: TAux(1) = TAux(1) + 1

    If LigneFin = LigneDébut Then
        Call Report(TSol, 1, LigneReport, NombreBarres, LongueurBarres, LigneFin, TAux)
        GoTo FINI
        End If

    Morceau = Cells(2, 11): DernierMorceau = Cells(LigneFin, 11)
    If Morceau + DernierMorceau > LongueurBarres Then
        Call Report(TSol, 1, LigneReport, NombreBarres, LongueurBarres, LigneFin, TAux)
        GoTo NIV2
        End If

' 2-2) On cherche la combinaison qui donnera le moins de chute avec ce morceau
    AERR = "NIV2-2)"
    Ligne = LigneDébut: TOTAL = Morceau: AncienneChute = LongueurBarres + 1
    Noeud = 1: TNoeud(1) = Ligne: TTOT(1) = TOTAL

'    ML = 15   ' pour mise au point
NIV22:
    If Ligne >= LigneFin Then GoTo NIV225     ' on est au bout
    TAux(1) = TAux(1) + 1
    Ligne = Ligne + 1: Morceau = Cells(Ligne, 11)
    CHUTE = LongueurBarres - TOTAL - Morceau
    If CHUTE < 0 Then GoTo NIV22
' donc le morceau tient dans la chute
    Noeud = Noeud + 1: TNoeud(Noeud) = Ligne
    TOTAL = TOTAL + Morceau: TTOT(Noeud) = TOTAL

' pour mise au point
'  ML = ML + 1: For J = 1 To Noeud: Cells(ML, J + 2) = TNoeud(J): Next J
'  Cells(ML, 1) = Taux(1)

    If CHUTE >= DernierMorceau Then GoTo NIV22

NIV225:
    AERR = "NIV225:"
' sécurité = limitateur de bouclage
    If TAux(1) > TAux(3) Then
        Mess2 = "Il y a déjà " & TAux(1) & " solutions testées" + Chr$(10) + "Voulez vous continuer"
        Réponse = MsgBox(Mess2, vbYesNo, Mess0)
        If Réponse <> 6 Then
            Cells(5, KK) = Cells(5, KK) + TAux(1)
            MessF = "Travail Interrompu": GoTo FINI
            End If
        TAux(3) = 2 * TAux(3)
        End If
' fin de la sécurité

    TAux(1) = TAux(1) - Noeud + 1
    If CHUTE < 0 Then CHUTE = LongueurBarres - TTOT(Noeud): Indic = 1
    If CHUTE < AncienneChute Then
        For n = 1 To Noeud: TSol(n) = TNoeud(n): Next n
        NoeudSol = Noeud: TAux(2) = TAux(2) + 1
        AncienneChute = CHUTE
        End If
    If CHUTE <= ChuteAcceptable Then
        Call Report(TSol, NoeudSol, LigneReport, NombreBarres, LongueurBarres, LigneFin, TAux)
        GoTo NIV2
        End If

' est-on est au bout de cette branche ?
' plus exactement, peut on remplacer le dernier morceau par 2 plus petits
    If Ligne < LigneFin - 1 And Morceau > DernierMorceau Then
        Indic = 0: GoTo NIV22
        End If
    If Indic = 1 Then Noeud = Noeud + 1: Indic = 0
    TNoeud(Noeud) = LigneFin

NIV23:
    AERR = "NIV23:"
    If Noeud <= 2 Then GoTo NIV25
    LigneNM1 = TNoeud(Noeud - 1): Ligne = TNoeud(Noeud)
    If Ligne - LigneNM1 = 1 Then
        Noeud = Noeud - 1: GoTo NIV23
        End If
' Donc, il y a un intervalle, entre les 2 noeuds ...
    Morceau = Cells(LigneNM1, 11)
    If Morceau = Cells(Ligne - 1, 11) Then
' ... Mais c'est partout la même valeur
        Noeud = Noeud - 1: GoTo NIV23
        End If
' ... y'a une dimension différente entre les 2 noeuds
' Donc, on la cherche et on continue
    Noeud = Noeud - 2: Ligne = LigneNM1
NIV24:
    If Cells(Ligne + 1, 11) = Morceau Then Ligne = Ligne + 1: GoTo NIV24
    TAux(1) = TAux(1) + Noeud
    TOTAL = TTOT(Noeud): GoTo NIV22

' On a fini par détecter la meilleure solution, pour ce 1er morceau
NIV25:
    AERR = "NIV25:"
    Call Report(TSol, NoeudSol, LigneReport, NombreBarres, LongueurBarres, LigneFin, TAux)

    GoTo NIV2

NIVERR:
    Mess1 = "Anomalie non prévue détectée dans la macro" + Chr$(10) + "Contacter l'auteur"
    MsgBox Mess1, vbOKOnly, Mess0
    GoTo FINAL
NIVERR1:
    MsgBox "Données anormales", vbOKOnly, Mess0
    GoTo FINAL
NIVERR2:
' on vient ici depuis § NIV1:
' si  N > 101            ' on peut augmenter la taille des DIM
    MsgBox "Limite de 100 formats dépassée", vbOKOnly, Mess0
    GoTo FINAL
NIVERR3:
' si LigneFin > 8000    ' on peut augmenter la limite de 8000, mais
                        ' attention au nombre de noeuds
    MsgBox "Limite de 8000 morceaux dépassée", vbOKOnly, Mess0
    GoTo FINAL
NIVERR4:
    Cells(n, 1).Select
    MsgBox "Morceau > Longueur des Barres", vbOKOnly, Mess0
    GoTo FINAL
FINAL:
    MessF = "Travail non fait"
FINI:
'    ActiveSheet.PageSetup.PrintArea = "$A$1:$F" & LigneReport
    Cells(4, KK + 1) = MessF

End Sub

Pardon, j'ai oublié la fin du code...

Sub Report(TSol, NoeudFin, LigneReport, NombreBarres, LongueurBarres, LigneFin, TAux)
' reporte la solution d'une barre dans les colonnes Résultat C-D-E

    KC = 3: KD = KC + 1: KE = KC + 2: KF = KC + 3 ' colonnes report
    KK = 9    ' colonne cumuls. Le même que dans Découpe( )
    Cumul = 0

    For LL = 1 To NoeudFin
        LigneM = TSol(LL): LongM = Cells(LigneM, 11)
        LigneReport = LigneReport + 1
        Cells(LigneReport, KC) = LongM: Cumul = Cumul + LongM
        Next LL

    Cells(LigneReport, KD) = Cumul                  ' longueur utilisée
    Cells(LigneReport, KE) = LongueurBarres - Cumul ' chute
    Cells(LigneReport, KF) = LongueurBarres
    Cells(LigneReport, KF + 1) = TAux(1)
    If TAux(2) > 1 Then Cells(LigneReport, KF + 2) = TAux(2) - 1
    Cells(5, KK) = Cells(5, KK) + TAux(1): TAux(1) = 0: TAux(2) = 0
' suppression des morceaux utilisés de la colonne K
    For LL = NoeudFin To 1 Step -1: LigneM = TSol(LL)
        Range("K" & LigneM).Select: Selection.Delete Shift:=xlUp
        LigneFin = LigneFin - 1: TSol(LL) = 0
        Next LL

    NombreBarres = NombreBarres + 1: Cells(3, KK) = NombreBarres

End Sub

Bonsoir,

le code dans un fichier serait le bien venu...

Ceci dit, je vous avoue m'être perdu dans le code...

Désolé.

@ bientôt

LouReeD

Rechercher des sujets similaires à "compter plages variable"