Se connecter avec
S'enregistrer | Connectez-vous

Optimisation code enregistrer facture

Dernière réponse : dans Programmation

Arff je vais m'en remettre au judicieux conseil de zeb dans le domaine de l'optimisation de code.

Cette macro fonctionne en 3 partie:

1. Première partie vérifie si la facture est complète et inscrit quelques donne sur une page du classeur.

2. Deuxième partie crée un classeur dont la nomenclature est année-mois (09-05) et d'y copier le contenu de la facture sans formule, en respectant le format des cellule et le logo de cie

3. Troisième partie prise en charge de l'inventaire. Ajoute les produits désinstaller et défectueux en stock en indiquant leur état et leur provenance. Si la pièces est doa elle change le statut de cette pièces dans le listing de produits. Si la pièces est installer elle l'enlève de l'inventaire. Et finalement, incrémente de 1 le service utilisé dans l'optique de statistique future.

Bref partie 1 et 2 fonctionnent a merveille, quoique j'imagine y'a mieux. Mais c'est la meilleur optimisation que je puisse faire pour l'instant.

La partie 3 fonctionne, mais j'ai tellement l'impression que c'est plein d'erreur potentiel lors d'utilisation intensive. J'en ai baver toute la journée avec de multiple test. J'arrive pas faire mieux :( 
  1. Sub Enregistrer()
  2. Dim numerofacture As String, cel As Range, fname As String
  3. Dim Doa As Range
  4. Dim doa2 As Range
  5. Dim Bad As Range
  6. Dim deinstall As Range
  7. Dim qty As Range
  8. Dim install As Range
  9. Dim wb_f As Workbook
  10. Dim ws_f As Worksheet, ws_fs As Worksheet, ws_p As Worksheet, ws_se As Worksheet
  11.  
  12. Set ws_se = Worksheets("services")
  13. Set ws_p = Worksheets("produits")
  14. Set wb_f = Workbooks("Facturation")
  15. Set ws_f = Worksheets("facture")
  16. Set ws_fs = Worksheets("factures")
  17. numerofacture = ws_f.Range("B10")
  18. abrege = Right(Left(numerofacture, 6), 5)
  19. fname = "F:\ProActive\Factures\" & abrege
  20. last_row = ws_p.Cells(2, 2).End(xlDown).Row
  21.  
  22. If ws_f.Range("I43") <> 0 And ws_f.Range("C49") <> "" And ws_f.Range("E13") <> "" And ws_f.Range("F13") <> "" And ws_f.Range("H8") <> "" And ws_f.Range("H9") <> "" And ws_f.Range("H10") <> "" Then
  23. ws_fs.Range("A2").EntireRow.Insert
  24. ws_fs.Range("A2") = ws_f.Range("B10")
  25. ws_fs.Range("B2") = ws_f.Range("F1")
  26. ws_fs.Range("C2") = ws_f.Range("I43")
  27. ws_fs.Range("D2") = ws_f.Range("H10")
  28. ws_fs.Range("E2") = ws_f.Range("H8")
  29. ws_fs.Range("F2") = ws_f.Range("H9")
  30. ws_fs.Range("G2") = (Now)
  31. ws_fs.Range("H2") = ws_f.Range("C49")
  32. ws_fs.Range("I2") = "NON"
  33. Else
  34. MsgBox ("Facture incomplète")
  35. Exit Sub
  36. End If
  37.  
  38. If Dir(fname & ".xls") = "" Then
  39. Workbooks.Add.SaveAs Filename:=fname
  40. Workbooks(abrege).Worksheets("Feuil1").Name = numerofacture
  41. Application.DisplayAlerts = False
  42. Workbooks(abrege).Worksheets("Feuil2").Delete
  43. Workbooks(abrege).Worksheets("Feuil3").Delete
  44. Application.DisplayAlerts = True
  45. Else:
  46. Workbooks.Open Filename:=fname & ".xls"
  47. Workbooks(abrege).Worksheets.Add.Name = numerofacture
  48. End If
  49. wb_f.Activate
  50. ws_f.Range("A1:I52").Copy
  51. Workbooks(abrege).Worksheets(numerofacture).Activate
  52. Range("a1").Select
  53. Selection.PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
  54. wb_f.Activate
  55. ws_f.Shapes("Image 40").Copy
  56. Workbooks(abrege).Worksheets(numerofacture).Paste
  57. wb_f.Activate
  58. ws_f.Range("A1:I52").Copy
  59. Workbooks(abrege).Worksheets(numerofacture).Activate
  60. Range("a1").Select
  61. Selection.PasteSpecial Paste:=xlFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
  62. With Workbooks(abrege).Worksheets(numerofacture).PageSetup
  63. .PrintArea = Range("a1:i43")
  64. .LeftMargin = Application.InchesToPoints(0.2)
  65. .RightMargin = Application.InchesToPoints(0.2)
  66. End With
  67. Workbooks(abrege).Save
  68. Workbooks(abrege).Close
  69.  
  70. With ws_f.Range("a35:a40")
  71. Set doa2 = .Find(what:="doa", LookIn:=xlValues)
  72. Set Bad = .Find(what:="bad", LookIn:=xlValues)
  73. Set deinstall = .Find(what:="deinstall", LookIn:=xlValues)
  74. If Not doa2 Is Nothing Then
  75. With ws_p.Range("C2:c" & last_row)
  76. Set Doa = .Find(doa2.Offset(0, 2).Value, LookIn:=xlValues)
  77. If Not Doa Is Nothing Then Doa.Offset(0, -1) = "Doa"
  78. End With
  79. End If
  80. If Not Bad Is Nothing Then
  81. ws_p.Range("A2").EntireRow.Insert
  82. ws_p.Range("A2") = "01SSIISEP03"
  83. ws_p.Range("B2") = "Bad"
  84. ws_p.Range("C2") = Bad.Offset(0, 2)
  85. ws_p.Range("D2") = Bad.Offset(0, 1)
  86. ws_p.Range("E2") = ws_f.Range("B10")
  87. ws_p.Range("F2") = ws_f.Range("H10")
  88. ws_p.Range("G2") = ws_f.Range("H8")
  89. End If
  90. If Not deinstall Is Nothing Then
  91. ws_p.Range("A2").EntireRow.Insert
  92. ws_p.Range("A2") = "01SSIISEP03"
  93. ws_p.Range("B2") = "Deinstall"
  94. ws_p.Range("C2") = Bad.Offset(0, 2)
  95. ws_p.Range("D2") = Bad.Offset(0, 1)
  96. ws_p.Range("E2") = ws_f.Range("B10")
  97. ws_p.Range("F2") = ws_f.Range("H10")
  98. ws_p.Range("G2") = ws_f.Range("H8")
  99. End If
  100. End With
  101. For Each cel In ws_f.Range("h35:h40")
  102. If cel <> "" Then
  103. With ws_p.Range("C2:c" & last_row)
  104. Set install = .Find(cel.Value, LookIn:=xlValues)
  105. If Not install Is Nothing Then
  106. install.EntireRow.Delete
  107. End If
  108. End With
  109. End If
  110. Next cel
  111. For Each cel In ws_f.Range("E13:E28")
  112. If cel <> "" Then
  113. With ws_se.Range("A2:A65536")
  114. Set qty = .Find(cel.Value, LookIn:=xlValues)
  115. If Not qty Is Nothing Then
  116. qty.Offset(0, 5) = qty.Offset(0, 5) + cel.Offset(0, 1)
  117. End If
  118. End With
  119. End If
  120. Next cel
  121. End Sub
Lassé par la pub ? Créez un compte
Expert Programmation

C'est pas mal du tout. J'ai même peine à croire que ce bout de code soit d'un si prétendu débutant.
En plus de l'optimisation, il reste quelques petites erreurs.

Audit de code

  • Lignes 12, 13, 15, 16. Lorque plusieurs classeurs sont utilisés, il est prudent de préciser le classeur.
    1. Set ws_se = ThisWorkbook.Worksheets("services" )
    2. Set ws_se = Workbooks("classeur").Worksheets("services" )


  • Lignes 30, 34. Pourquoi ces parenthèses ? Ne pas confondre Function et Sub.

  • Ligne 34. Le programme va s'arrêter. Par convention, il faut prévenir l'utilisateur par l'utilisation d'une icône dans la boîte de dialogue. (i) pour information, /!\ pour avertissement, [X] pour arrêt. Donc :
    1. MsgBox "Facture incomplète", vbCritical


  • Ligne 22 à 26. Personnellement, j'use et j'abuse des "Exit" (exit en shell, return en C/C++, etc.) J'organisue donc mon code non pas comme cela :
    1. Si Ok Alors
    2. Partie 1...
    3. Sinon
    4. Exit!
    5. Fin Si
    6. Partie 2...
    Mis comme cela :
    1. Si Pas Ok Alors
    2. Exit!
    3. Fin Si
    4. Parties 1 & 2.
    C'est plus lisible, on voit et on traite bien les cas particuliers d'abord, puis on traite d'un coup le reste du traitement, sans plus se poser de question.

  • Lignes 41 à 44. C'est pas bien, c'est nul, c'est mal ! Encore faut-il savoir comment faire autrement ;) 
    1. SheetsInNewWorkbook = 1
    2. Workbooks.Add
    :sol:  Autre version, encore plus simple :
    1. Workbooks.Add xlWBATWorksheet
    re- :sol: 

  • Ligne 39. C'est pas mal, c'est même astucieux. Je te propose ce code pour étude :
    1. Dim wb_a As Workbook
    2. Dim ws_a As Worksheet
    3.  
    4. If Dir(fname & ".xls" ) = "" Then
    5. SheetsInNewWorkbook = 1
    6. Set wb_a = Workbooks.Add
    7. Set ws_a = wb_a.Worksheets(1)
    8. ws_a.Name = numerofacture
    9. wb_a.SaveAs Filename:=fname
    10. wb_a.Add.Close False
    Je n'aime pas me fier au nom du classeur. C'est trop alléatoire. Surtout que Excel donne des noms différents selon les cas, par exemple avant et après enregistrement. De la même façon, je n'utilise pas le nom des feuilles. Le jour où ta macro est exécutée sur un XL en anglais, la feuille 1 ne s'appelle plus Feuil1 mais Sheet1. Trop de fois j'ai vu des programmes planter comme ça :o 

  • Lignes 49, 51, 54, 57, 59. NON, NON, NON, NON et NON. [:marcus67]
    ____________________________________________________________

    Pas de ActiveTruc/Selection.Machin. Pourquoi activer ces objets ?
    Les laisser là où ils sont et utiliser leurs propriétés et méthodes !

    Ligne 49, activate inutile, puisque ligne 50, on précise sur quelle feuille on travaille.

    Ligne 51, activate utile puisque ligne 52, on a oublié de préciser sur quelle feuille on travaile. Evidemment, corriger les lignes 51 ET 52.

    Remplacer chaque Truc.Activate/ActiveTruc.Machin ou Truc.Select/Selection.Machin par Truc.Machin[:b].
    1. ' // MAL
    2. Range("a1").Select
    3. Selection.PasteSpecial Paste:=xlValues
    4. ' // Bien
    5. Range("A1").PasteSpecial Paste:=xlValues

    ____________________________________________________________

  • Lignes 67, 68. Bien, très bien. Parce que je suis paranoïaque, j'ajoute toujours False à Close. On ne sait jamais, Excel peut vouloir changer quelque chose avant qu'on ne ferme. Or si j'ai enregistré avant, c'est que je ne veux pas que l'utilisateur mette son grain de sel !

  • Lignes 62 à 66. Bonne utilisation de With.
  • Lignes 75 à 78, 103 à 108, 113 à 118. Mauvaise utilisation de With : imbrication + tout ça pour une seule ligne :pfff: 

  • Ligne 106. [:alzheimer parkinson] Mais puisque je t'ai déjà expliqué qu'il faut aller à rebours pour supprimer des lignes, bon sang !

    1 ere et 2 ieme partie en très bonne voie

    1. Set wb_f = ThisWorkbook
    2. Set ws_se = ThisWorkbook.Worksheets("services")
    3. Set ws_p = ThisWorkbook.Worksheets("produits")
    4. Set ws_f = ThisWorkbook.Worksheets("facture")
    5. Set ws_fs = ThisWorkbook.Worksheets("factures")
    6. numerofacture = ws_f.Range("B10")
    7. abrege = Right(Left(numerofacture, 6), 5)
    8. fname = "F:\ProActive\Factures\" & abrege
    9. last_row = ws_p.Cells(2, 2).End(xlDown).Row
    10.  
    11. If ws_f.Range("I43") = 0 Or ws_f.Range("C49") = "" Or ws_f.Range("E13") = "" Or ws_f.Range("F13") = "" Or ws_f.Range("H8") = "" Or ws_f.Range("H9") = "" Or ws_f.Range("H10") = "" Then
    12. MsgBox "Facture incomplète", vbCritical
    13. Exit Sub
    14. End If
    15.  
    16. ws_fs.Range("A2").EntireRow.Insert
    17. ws_fs.Range("A2") = ws_f.Range("B10")
    18. ws_fs.Range("B2") = ws_f.Range("F1")
    19. ws_fs.Range("C2") = ws_f.Range("I43")
    20. ws_fs.Range("D2") = ws_f.Range("H10")
    21. ws_fs.Range("E2") = ws_f.Range("H8")
    22. ws_fs.Range("F2") = ws_f.Range("H9")
    23. ws_fs.Range("G2") = Now
    24. ws_fs.Range("H2") = ws_f.Range("C49")
    25. ws_fs.Range("I2") = "NON"
    26.  
    27. If Dir(fname & ".xls") = "" Then
    28. Application.SheetsInNewWorkbook = 1
    29. Set wb_a = Workbooks.Add
    30. Set ws_a = wb_a.Worksheets(1)
    31. ws_a.Name = numerofacture
    32. wb_a.SaveAs Filename:=fname
    33. Else:
    34. Set wb_a = Workbooks.Open(fname & ".xls")
    35. Set ws_a = wb_a.Worksheets.Add
    36. ws_a.Name = numerofacture
    37. End If
    38.  
    39. ws_f.Range("A1:I52").Copy
    40. ws_a.Range("a1").PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
    41. ws_f.Shapes("Image 40").Copy
    42. ws_a.Paste
    43. ws_f.Range("A1:I52").Copy
    44. ws_a.Range("a1").PasteSpecial Paste:=xlFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
    45. With wb_a.Worksheets(1).PageSetup
    46. .PrintArea = Range("a1:i43")
    47. .LeftMargin = Application.InchesToPoints(0.2)
    48. .RightMargin = Application.InchesToPoints(0.2)
    49. End With
    50. wb_a.Save
    51. wb_a.Close False


    2 petit problème d'optimisation

    ligne 41 et 42: d'imbriquer en une seul ligne
    1. ws_f.Shapes("Image 40").Copy
    2. ws_a.Paste


    ligne 45 à 49: Je comprends pas pourquoi quand je mets With ws_a.PageSetup ca me donne une erreur
    1. With wb_a.Worksheets(1).PageSetup
    2. .PrintArea = Range("a1:i43")
    3. .LeftMargin = Application.InchesToPoints(0.2)
    4. .RightMargin = Application.InchesToPoints(0.2)
    5. End With


    Pour la 3 ieme partie je suis encore dessus... ne me souffler pas la réponse toute faite pour la 3 ieme parti. Je soumettrai la 3 ieme partie optimiser aussitôt terminer

    Et voila ... Est ce que ca plus d'allure comme ca ?
    1. Sub Enregistrer()
    2. Dim numerofacture As String, fname As String
    3. Dim Doa As Range, qty As Range, cel As Range
    4. Dim r As Long
    5. Dim wb_f As Workbook, wb_a As Workbook
    6. Dim ws_f As Worksheet, ws_fs As Worksheet, ws_p As Worksheet, ws_se As Worksheet, ws_a As Worksheet
    7. Set wb_f = ThisWorkbook
    8. Set ws_se = ThisWorkbook.Worksheets("services")
    9. Set ws_p = ThisWorkbook.Worksheets("produits")
    10. Set ws_f = ThisWorkbook.Worksheets("facture")
    11. Set ws_fs = ThisWorkbook.Worksheets("factures")
    12. numerofacture = ws_f.Range("B10")
    13. abrege = Right(Left(numerofacture, 6), 5)
    14. fname = "F:\ProActive\Factures\" & abrege
    15. last_row = ws_p.Cells(2, 2).End(xlDown).Row
    16. If ws_f.Range("I43") = 0 Or ws_f.Range("C49") = "" Or ws_f.Range("E13") = "" Or ws_f.Range("F13") = "" Or ws_f.Range("H8") = "" Or ws_f.Range("H9") = "" Or ws_f.Range("H10") = "" Then
    17. MsgBox "Facture incomplète", vbCritical
    18. Exit Sub
    19. End If
    20. ws_fs.Range("A2").EntireRow.Insert
    21. ws_fs.Range("A2") = ws_f.Range("B10")
    22. ws_fs.Range("B2") = ws_f.Range("F1")
    23. ws_fs.Range("C2") = ws_f.Range("I43")
    24. ws_fs.Range("D2") = ws_f.Range("H10")
    25. ws_fs.Range("E2") = ws_f.Range("H8")
    26. ws_fs.Range("F2") = ws_f.Range("H9")
    27. ws_fs.Range("G2") = Now
    28. ws_fs.Range("H2") = ws_f.Range("C49")
    29. ws_fs.Range("I2") = "NON"
    30. If Dir(fname & ".xls") = "" Then
    31. Application.SheetsInNewWorkbook = 1
    32. Set wb_a = Workbooks.Add
    33. Set ws_a = wb_a.Worksheets(1)
    34. ws_a.Name = numerofacture
    35. wb_a.SaveAs Filename:=fname
    36. Else:
    37. Set wb_a = Workbooks.Open(fname & ".xls")
    38. Set ws_a = wb_a.Worksheets.Add
    39. ws_a.Name = numerofacture
    40. End If
    41. ws_f.Range("A1:I52").Copy
    42. ws_a.Range("a1").PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
    43. ws_f.Shapes("Image 40").Copy
    44. ws_a.Paste
    45. ws_f.Range("A1:I52").Copy
    46. ws_a.Range("a1").PasteSpecial Paste:=xlFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
    47. With wb_a.Worksheets(1).PageSetup
    48. .PrintArea = Range("a1:i43")
    49. .LeftMargin = Application.InchesToPoints(0.2)
    50. .RightMargin = Application.InchesToPoints(0.2)
    51. End With
    52. wb_a.Save
    53. wb_a.Close False
    54. For Each cel In ws_f.Range("A35:A40")
    55. If LCase(cel.Value) = "bad" Or UCase(cel.Value) = "DEINSTALL" Then
    56. ws_p.Range("A2").EntireRow.Insert
    57. ws_p.Range("A2") = "01SSIISEP03"
    58. ws_p.Range("B2") = cel
    59. ws_p.Range("C2") = cel.Offset(0, 2)
    60. ws_p.Range("D2") = cel.Offset(0, 1)
    61. ws_p.Range("E2") = ws_f.Range("B10")
    62. ws_p.Range("F2") = ws_f.Range("H10")
    63. ws_p.Range("G2") = ws_f.Range("H8")
    64. End If
    65. If LCase(cel.Value) = "doa" Then
    66. Set Doa = ws_p.Columns(3).Cells.Find(what:=cel.Offset(0, 2))
    67. Doa.Offset(0, -1) = cel
    68. Doa.Offset(0, 2) = ws_f.Range("B10")
    69. Doa.Offset(0, 3) = ws_f.Range("H10")
    70. Doa.Offset(0, 4) = ws_f.Range("H8")
    71. End If
    72. Next
    73. For Each cel In ws_f.Range("H35:H40")
    74. If cel <> "" Then
    75. For r = last_row To 2 Step -1
    76. If ws_p.Cells(r, 3).Value = cel.Value Then
    77. ws_p.Cells(r, 1).EntireRow.Delete
    78. End If
    79. Next
    80. End If
    81. Next
    82. For Each cel In ws_f.Range("E13:E28")
    83. If cel <> "" Then
    84. Set qty = ws_se.Columns(1).Cells.Find(what:=cel)
    85. qty.Offset(0, 5) = qty.Offset(0, 5) + cel.Offset(0, 1)
    86. End If
    87. Next
    88. End Sub
    Lassé par la pub ? Créez un compte