excel - toutes - vba select case multiple




Comment éviter d'utiliser Select dans Excel VBA (8)

"... et je trouve que mon code serait plus réutilisable si je pouvais utiliser des variables au lieu des fonctions Select."

Bien que je ne puisse pas penser à une poignée de situations isolées où le choix serait préférable à celui de la référence cellulaire directe, j'élèverais la défense de la Selection et je soulignerais qu'il ne faudrait pas la rejeter pour les mêmes raisons .Select devrait être évité.

Il y a des moments où des sous-routines de macros courtes et rapides, attribuées à des combinaisons de raccourcis-clavier, sont disponibles en appuyant sur quelques touches, ce qui permet d'économiser beaucoup de temps. Etre capable de sélectionner un groupe de cellules pour appliquer le code opérationnel sur des merveilles de travail lorsqu'il s'agit de données empochées qui ne sont pas conformes à un format de données à l'échelle de la feuille de calcul. De la même manière que vous pouvez sélectionner un groupe de cellules et appliquer un changement de format, la sélection d'un groupe de cellules pour exécuter un code de macro spécial peut être un gain de temps important.

Exemples de sous-cadre basé sur la sélection:

Public Sub Run_on_Selected()
    Dim rng As Range, rSEL As Range
    Set rSEL = Selection    'store the current selection in case it changes
    For Each rng In rSEL
        Debug.Print rng.Address(0, 0)
        'cell-by-cell operational code here
    Next rng
    Set rSEL = Nothing
End Sub

Public Sub Run_on_Selected_Visible()
    'this is better for selected ranges on filtered data or containing hidden rows/columns
    Dim rng As Range, rSEL As Range
    Set rSEL = Selection    'store the current selection in case it changes
    For Each rng In rSEL.SpecialCells(xlCellTypeVisible)
        Debug.Print rng.Address(0, 0)
        'cell-by-cell operational code here
    Next rng
    Set rSEL = Nothing
End Sub

Public Sub Run_on_Discontiguous_Area()
    'this is better for selected ranges of discontiguous areas
    Dim ara As Range, rng As Range, rSEL As Range
    Set rSEL = Selection    'store the current selection in case it changes
    For Each ara In rSEL.Areas
        Debug.Print ara.Address(0, 0)
        'cell group operational code here
        For Each rng In ara.Areas
            Debug.Print rng.Address(0, 0)
            'cell-by-cell operational code here
        Next rng
    Next ara
    Set rSEL = Nothing
End Sub

Le code réel à traiter peut être quelque chose d'une seule ligne à plusieurs modules. J'ai utilisé cette méthode pour lancer des routines longues sur une sélection irrégulière de cellules contenant les noms de fichiers des classeurs externes.

En bref, ne pas ignorer la Selection raison de son association étroite avec .Select et ActiveCell . En tant que propriété de feuille de calcul, elle a de nombreux autres objectifs.

(Oui, je sais que cette question concernait .Select , pas Selection mais je voulais supprimer toutes les idées fausses que les codeurs VBA novices pourraient déduire.)

J'ai beaucoup entendu parler de l'aversion compréhensible d'utiliser .Select dans Excel VBA, mais je ne sais pas comment éviter de l'utiliser. Je trouve que mon code serait plus réutilisable si j'étais capable d'utiliser des variables plutôt que des fonctions Select . Cependant, je ne suis pas sûr de savoir comment faire référence à des choses (comme l' ActiveCell etc.) si vous n'utilisez pas Select .

J'ai trouvé cet article sur les gammes et cet exemple sur les avantages de ne pas utiliser select mais ne trouve rien sur comment ?


Ceci est un exemple qui effacera le contenu de la cellule "A1" (ou plus si le type de sélection est xllastcell, etc). Tout est fait sans avoir à sélectionner les cellules.

Application.GoTo Reference:=Workbook(WorkbookName).Worksheets(WorksheetName).Range("A1")
Range(Selection,selection(selectiontype)).clearcontents 

J'espère que ça aidera quelqu'un.


Je vais donner la réponse courte puisque tout le monde a donné le long.

Vous obtiendrez .select et .activate chaque fois que vous enregistrez des macros et que vous les réutilisez. Lorsque vous sélectionnez une cellule ou une feuille, cela la rend active. À partir de ce moment, chaque fois que vous utilisez des références non qualifiées comme Range.Value elles utilisent simplement la cellule et la feuille actives. Cela peut également poser problème si vous ne regardez pas où votre code est placé ou si un utilisateur clique sur le classeur.

Ainsi, vous pouvez éliminer ces problèmes en référençant directement vos cellules. Qui va:

'create and set a range
Dim Rng As Excel.Range
Set Rng = Workbooks("Book1").Worksheets("Sheet1").Range("A1")
'OR
Set Rng = Workbooks(1).Worksheets(1).Cells(1, 1)

Ou vous pourriez

'Just deal with the cell directly rather than creating a range
'I want to put the string "Hello" in Range A1 of sheet 1
Workbooks("Book1").Worksheets("Sheet1").Range("A1").value = "Hello"
'OR
Workbooks(1).Worksheets(1).Cells(1, 1).value = "Hello"

Il existe diverses combinaisons de ces méthodes, mais ce serait l'idée générale exprimée aussi rapidement que possible pour les personnes impatientes comme moi.


L'utilisation IMHO de .select vient de gens qui, comme moi, ont commencé à apprendre VBA par nécessité en enregistrant des macros puis en modifiant le code sans se rendre compte que .select et la selection suivante ne sont que des intermédiaires inutiles.

.select peut être évité, comme beaucoup l'ont déjà fait, en travaillant directement avec les objets déjà existants, ce qui permet divers référencements indirects comme calculer i et j de façon complexe puis éditer la cellule (i, j), etc.

Sinon, rien ne se passe implicitement avec .select lui-même et vous pouvez trouver des utilisations pour cela facilement, par exemple j'ai une feuille de calcul que je remplis avec la date, active la macro qui fait de la magie et l'exporte dans un format acceptable , qui nécessite cependant des entrées manuelles finales (imprévisibles) dans une cellule adjacente. Alors voici le moment pour .select qui me sauve ce mouvement de souris supplémentaire et cliquez.


Réponse rapide:

Pour éviter d'utiliser la méthode .Select , vous pouvez définir une variable égale à la propriété que vous souhaitez.

► Par exemple, si vous voulez la valeur dans la Cell A1 vous pouvez définir une variable égale à la propriété value de cette cellule.

  • Exemple valOne = Range("A1").Value

► Par exemple, si vous voulez le nom de code de 'Sheet3`, vous pouvez définir une variable égale à la propriété codename de cette feuille de calcul.

  • Exemple valTwo = Sheets("Sheet3").Codename

J'espère que ça aide. Faites moi savoir si vous avez des questions.


S'il vous plaît noter que dans ce qui suit, je compare l'approche Select (celui que l'OP veut éviter), avec l'approche Range (et c'est la réponse à la question). Alors n'arrêtez pas de lire quand vous voyez le premier Select.

Cela dépend vraiment de ce que vous essayez de faire. De toute façon un exemple simple pourrait être utile. Supposons que vous voulez définir la valeur de la cellule active sur "foo". En utilisant ActiveCell, vous écrivez quelque chose comme ceci:

Sub Macro1()
    ActiveCell.Value = "foo"
End Sub

Si vous voulez l'utiliser pour une cellule qui n'est pas active, par exemple pour "B2", vous devez d'abord la sélectionner, comme ceci:

Sub Macro2()
    Range("B2").Select
    Macro1
End Sub

En utilisant Ranges vous pouvez écrire une macro plus générique qui peut être utilisée pour définir la valeur de n'importe quelle cellule que vous voulez:

Sub SetValue(cellAddress As String, aVal As Variant)
    Range(cellAddress).Value = aVal
End Sub

Ensuite, vous pouvez réécrire Macro2 comme:

Sub Macro2()
    SetCellValue "B2", "foo"
End Sub

Et Macro1 comme:

Sub Macro1()
    SetValue ActiveCell.Address, "foo"
End Sub

J'espère que cela aidera à éclaircir un peu les choses.


Un petit point d'accent que j'ajouterai à toutes les excellentes réponses données ci-dessus:

Probablement la plus grande chose que vous pouvez faire pour éviter d'utiliser Select est, dans la mesure du possible, d'utiliser des plages nommées (combinées avec des noms de variables significatifs) dans votre code VBA . Ce point a été mentionné ci-dessus, mais a glissé un peu; cependant, il mérite une attention particulière.

Voici quelques raisons supplémentaires pour faire un usage libéral des plages nommées bien que je suis sûr que je pourrais penser à plus.

Les plages nommées facilitent la lecture et la compréhension de votre code.

Exemple:

Dim Months As Range
Dim MonthlySales As Range

Set Months = Range("Months")
'e.g, "Months" might be a named range referring to A1:A12

Set MonthlySales = Range("MonthlySales")
'e.g, "Monthly Sales" might be a named range referring to B1:B12

Dim Month As Range
For Each Month in Months
    Debug.Print MonthlySales(Month.Row)
Next Month

Il est assez évident que les plages nommées Months et MonthlySales contiennent, et ce que la procédure est en train de faire.

Pourquoi est-ce important? En partie parce qu'il est plus facile pour les autres de le comprendre, mais même si vous êtes la seule personne qui verra ou utilisera votre code, vous devriez toujours utiliser des plages nommées et de bons noms de variables car VOUS OUBLIEZ ce que vous vouliez faire avec un an plus tard, et vous perdrez 30 minutes à déterminer ce que fait votre code.

Les plages nommées garantissent que vos macros ne se cassent pas lorsque (pas si!) La configuration de la feuille de calcul change.

Considérez, si l'exemple ci-dessus a été écrit comme ceci:

Dim rng1 As Range
Dim rng2 As Range

Set rng1 = Range("A1:A12")
Set rng2 = Range("B1:B12")

Dim rng3 As Range
For Each rng3 in rng1 
    Debug.Print rng2(rng3.Row)
Next rng3

Ce code fonctionnera très bien au début - jusqu'à ce que vous ou un futur utilisateur décide "gee wiz, je pense que je vais ajouter une nouvelle colonne avec l'année dans la colonne A !", Ou mettre une colonne de dépenses entre les mois et colonnes de ventes, ou ajoutez un en-tête à chaque colonne. Maintenant, votre code est cassé. Et parce que vous avez utilisé de terribles noms de variables, il vous faudra beaucoup plus de temps pour trouver une solution.

Si vous aviez déjà utilisé des plages nommées, les colonnes Months et Sales pourraient être déplacées comme vous le souhaitez, et votre code continuerait à fonctionner correctement.


Deux raisons principales pour lesquelles .Select / .Activate / Selection / Activecell / Activesheet / Activeworkbook etc ... doivent être évitées

  1. Il ralentit votre code.
  2. C'est généralement la cause principale des erreurs d'exécution.

Comment pouvons-nous l'éviter?

1) Travailler directement avec les objets pertinents

Considérez ce code

Sheets("Sheet1").Activate
Range("A1").Select
Selection.Value = "Blah"
Selection.NumberFormat = "@"

Ce code peut aussi être écrit comme

With Sheets("Sheet1").Range("A1")
    .Value = "Blah"
    .NumberFormat = "@"
End With

2) Si nécessaire, déclarez vos variables. Le même code ci-dessus peut être écrit comme

Dim ws as worksheet

Set ws = Sheets("Sheet1")

With ws.Range("A1")
    .Value = "Blah"
    .NumberFormat = "@"
End With




excel-vba