Aller au contenu

Sélectionner un bloc dynamique


rrobert

Messages recommandés

Merci d'avoir pris le temps du lisp et de me montrer en VBA, c'est très appréciable. Je comprends bien mieux la structure des bloc et blocs dynamiques dans Autocad.

 

Donc si je comprends bien il me suffit d'ajouter autant de codes DXF que je souhaite à FilterType et autant de conditions à FilterData pour complexifier le filtrage si je le souhaite?

 

Lien vers le commentaire
Partager sur d’autres sites

Merci du lien.

J'ajoute aussi que si je veux autant développer en VBA et pas trop en lisp c'est que nous sommes 4 au bureau et que je suis le seul à avoir AutoCAD en full, les autres ayant LT c'est mieux si tout le monde peut en profiter 😉

Lien vers le commentaire
Partager sur d’autres sites

1 hour ago, rrobert said:

J'ajoute aussi que si je veux autant développer en VBA et pas trop en lisp c'est que nous sommes 4 au bureau et que je suis le seul à avoir AutoCAD en full, les autres ayant LT c'est mieux si tout le monde peut en profiter

Les versions LT ne supportent aucune programmation.

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Lien vers le commentaire
Partager sur d’autres sites

Je n'étais pas sûre donc j'ai préféré ne rien dire plutôt que de dire des bêtises mais c'est bien ce qu'il me semblait...Si tu veux écrire des programmes pour des versions LT, il faudrait se tourner plutôt sur des scripts ou le langage DIESEL (il me semble qu'il est compatible avec les versions LT). En revanche, je ne sais plus si les versions LT possèdent les mêmes commandes qu'une version full ou bien si leur nombre est limité (je confonds sûrement avec les Viewers)...

Peut-être essaye de voir avec la commande FILTRE (à vérifier s'il y a moyen de ne pas passer par la Boîte de Dialogue) ou SELECTSIMILAR dans ce cas. Mais en effet c'est bien de s'en rendre compte le plus tôt possible que ton programme doit être compatible avec les versions LT.

Bon courage !

Lien vers le commentaire
Partager sur d’autres sites

@rrobert, je ne sais pas si tu as bien compris donc je préfère insister juste au cas où :
Les versions LT ne supporte AUCUNE programmation, autrement dit, que se soit en VBA ou en LISP, les versions LT n'y auront pas le droit. La seule solution si tu ne veux pas être le seul à en profiter, c'est de creuser le sujet en passant par un script, ou du DIESEL...(ou bien en achetant des licences full pour tout le monde, mais chat fait cher le programme !)

Je préfère insister car ta phrase 

11 minutes ago, rrobert said:

Argh, je n'ai donc plus aucun argument pour développer en lisp 😉

prête à confusion et semble indiquer que tu comptes programmer en LISP, ce qui ne solutionnera pas le problème. Si tu veux développer un programme pour toi uniquement, libre à toi de choisir le VBA ou le LISP en fonction de tes habitudes (les fonctionnalités sont très similaire, c'est juste le langage qui est différent) mais si ton programme à pour vocation d'être utilisé par tes collègues (donc LT), alors autant faire directement tous tes programmation en script/DIESEL qui fonctionneront aussi bien sur une version LT que full ! Tu risques de perdre du temps à devoir écrire le même programme dans deux langages différents (voir 3 si tu veux revenir en version LISP alors que tu as commencé en VBA).

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

@Luna j'avais bien compris le problème, pour l'instant je vais faire 2/3 trucs urgents en VBA pour moi, je verrai après si je passe le cap du script et diesel pour les collègues car ça fait déjà pas mal de choses à décortiquer en ce moment 😉 

Lien vers le commentaire
Partager sur d’autres sites

28 minutes ago, rrobert said:

Argh, je n'ai donc plus aucun argument pour développer en lisp

@rrobert, tu fais comme tu veux, chacun ses préférences.

Par contre, l'activité des forums peut te donner une idée de la quantité d'aide et d'exemples que tu trouveras:
CADxp : VBA = 4600 messages LISP = 41600 messages
Autodesk : VBA = 91526 envois, LISP = 385009 envois
TheSwamp : VBA 9168 posts, LISP = 110610 posts

@Luna, @rrobert, pour les blocs dynamiques pas de salut hors programmation.
La commande FILTRE (_FILTER) offre les mêmes possibilités que les filtres de sélections, et le Diesel n'est pas vraiment un langage de programmation, il permet juste de mettre certaines conditions dans les macros de commandes.

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Lien vers le commentaire
Partager sur d’autres sites

Bonjour @rrobert

Pour le coup, c'est vraiment minimaliste ! Trop d'ailleurs, j'aurais aimé un fichier avec des entités, je vais les rajouter pour tester les filtres...
Je vais voir ce que je peux te proposer, mais pas dans les minutes ni dans la journée qui vient, je suis over full sur autre chose.

Amicalement

Lien vers le commentaire
Partager sur d’autres sites

EDIT : j'avais initialement dû mal recopier le code de @gile, en prenant  "*,>=,*" et non pas ">=" tout fonctionne. Merci.

Du coup qu'ajoutent le *, en plus du >= ?

 

 

Je complète le fichier DWG avec le code actuel inspiré de @gile :

 

Sub test420000()

Dim nom_bloc As String
nom_bloc = "toto"

Dim pointMin(0 To 2) As Double
Dim filterType(3) As Integer
Dim filterData(3) As Variant

pointMin(0) = 50
pointMin(1) = 50
pointMin(2) = 50

'Le code suivant renvoie une erreur de declaration de variable
'Dim filterType(0, 2, -4, 10, -4, 10) As Integer
'Dim filterData("INSERT", nom_bloc & ",`*U*", "*,>=,*", pointMin, "*,<,*", pointMax) As Variant


'Les filtres sont faits pour sélectionner tous les blocs situés au-dessus du pointMin de coordonnées (50,50,50)
filterType(0) = 0
filterType(1) = 2
filterType(2) = -4
filterType(3) = 10
filterData(0) = "INSERT"
filterData(1) = nom_bloc & ",`*U*"
filterData(2) = ">="
filterData(3) = pointMin


Dim sset As AcadSelectionSet
Set sset = ThisDrawing.SelectionSets.Add("test13")

sset.Select acSelectionSetAll, , , filterType, filterData
'sset.SelectOnScreen filterType, filterData


MsgBox ("Elements filtrés: " & str(sset.Count))
sset.Highlight True

sset.Delete

End Sub

 

 

Ca fonctionne très bien pour la coordonnée X.

 

Mais, suivant ce manuel, si je replace le code DXF "10" par le code DXF "20" afin de filtrer suivant la coordonnée Y, et bien il ne se passe rien, aucune entité n'est sélectionnée alors que ça devrait être le cas !

Lien vers le commentaire
Partager sur d’autres sites

Je ne peux pas t'aider en ce qui concerne la syntaxe VBA pour la déclaration des variables, mais je suis quasiment certain pour la syntaxe pour les valeurs du filtre (c'est le même principe qu'en LISP et qu'en .NET).

filterType(0) = 0
filterData(0) = "INSERT"
filterType(1) = 2
filterData(1) = nom_bloc & ",`*U*"
filterType(2) = -4
filterData(2) = "*,>=,*"
filterType(3) = 10
filterData(3) = pointMin
filterType(4) = -4
filterData(4) = "*,<,*"
filterType(5) = 10
filterData(5) = pointMax

 

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Lien vers le commentaire
Partager sur d’autres sites

Coucou,

il y a 53 minutes, rrobert a dit :

EDIT : j'avais initialement dû mal recopier le code de @gile, en prenant  "*,>=,*" et non pas ">=" tout fonctionne. Merci.

Du coup qu'ajoutent le *, en plus du >= ?

Alors pour commencer, les codes DXF 20 et 30 (respectivement Y et Z) n'existent pas vraiment dans la liste DXF d'un objet...Pour cela, je te conseil de consulter les objets directement via (entget (car (entsel))) ! En réalité, les codes 20 et 30 sont "contenus" dans le code DXF 10 de manière implicite.

Le code DXF 10 se compose ainsi : (10 X Y Z), autrement dit, tu as les 3 axes. Le code -4 avec pour valeur "*,>=,*" permet de définir les valeurs acceptable pour le code DXF 10 suivant. Ainsi cela permet de définir que l'on accepte n'importe quelle valeur pour les coordonnées en X et en Z (la virgule permet de séparer les axes) grâce à * (donc on peut mettre n'importe quelle valeur dans le code DXF 10 suivant pour ces axes, car elles ne comptent pas). Et on n'acceptent ici que les valeurs en Y qui sont supérieures ou égales à la valeur précisée dans le code DXF 10 suivant cette paire pointée.

Encore une fois, @(gile) est plus rapide ^^"

Pour le coup, l'aide en LISP concernant la fonction (ssget) te donneras toutes les réponses que tu souhaites car c'est le même fonctionnement qu'en LISP.
http://www.lee-mac.com/ssget.html

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

Le 09/06/2021 à 13:55, Curlygoth a dit :

Pour revenir à l'ajout à une sélection :



selection.AddItems objet_new

et

set objet_new = ton objet 😉

 

J'ai essayé par tous les moyens mais rien n'y fait, ça ne fonctionne pas...

Je suis capable de préfiltrer sans souci, mais en post-filtrage je ne peux supprimer ou ajouter des éléments à mon selectionSet.

J'ai crée un selectionset "selection" qui contient tous les éléments de ma présélection.

et j'ai créé un autre jeu de selection "selection_finale" à qui je veux ajouter mes objets post-filtrés. Sauf que ça ne marche pas, peu importe le type d'objet que je veux y ajouter...

(pour l'instant je ne joue qu'avec des selectionset, je regarderai pas la suite pour les collections)

 

Je me suis aidé de cette page de l'aide Autodesk avec l'exemple qu'ils ont mis.

La partie qui beugue est à la fin.

 

Sub selection_etage()
'Cette macro permet de sélectionner un bloc manuellement puis de sélectionner tous les blocs présents sur le même étage
' Elle évoluera dans le temps pour créer un utilitaire de sélection complet permettant de renseigner les calques, noms, visibilité, attributs, dimensions, etc.

'Variables permettant de déterminer les limites d'étages de sélection
Dim etage_ref As Integer
Dim espacement_etage As Double
Dim lim_inf As Double
Dim lim_sup As Double

'Variables pour la sélection d'objet
Dim selectionref As AcadEntity
Dim point_selection_ref As Variant
Dim blocref As AcadBlockReference
Dim nom_bloc_ref As String

Dim selection As AcadSelectionSet
Dim selection_finale As AcadSelectionSet
Dim objet As AcadObject
Dim bloc As AcadBlockReference
'Dim bloc_sel As AcadBlockReference


'Variables pour le filtrage
Dim pointMin(2) As Double
Dim pointMax(2) As Double
Dim filterType(5) As Integer
Dim filterData(5) As Variant


Dim nom_bloc As String




'on vient récupérer l'écartement entre étages définis par la variable USERI1
espacement_etage = ThisDrawing.GetVariable("useri1")


'##############SELECTION DU BLOC DE REFERENCE################
'L'utilisateur doit sélectionner UN bloc de référence
'Si la sélection comporte une erreur on recommence la phase de sélection
On Error Resume Next
RETRY:
'Code de sélection du bloc de référence
ThisDrawing.Utility.GetEntity selectionref, point_selection_ref, vbCr & "Sélectionnez le bloc de référence"
'verification des erreurs de selection
If Err <> 0 Then
    Err.Clear
    MsgBox "La sélection est vide ou non valide."
    GoTo RETRY
End If


'On vérifie que l'élément de référence sélectionné est un bloc
If TypeOf selectionref Is AcadBlockReference Then
    Set blocref = selectionref
    nom_bloc_ref = blocref.EffectiveName
    'On détermine le niveau du bloc ainsi que les limites sup et inf du niveau auquel il se trouve
    'ATTENTION, ceci ne fonctionne qu'avec les coordonnées du SCG
    If blocref.InsertionPoint(1) >= 0 Then
        etage_ref = Fix((blocref.InsertionPoint(1)) / espacement_etage)
    Else
        etage_ref = Fix((blocref.InsertionPoint(1)) / espacement_etage) - 1
    End If
    lim_sup = espacement_etage * (etage_ref + 1)
    lim_inf = espacement_etage * etage_ref
    'Les lignes en commentaires suivantes servent, au besoin, à faire un suivi pas à pas des étapes précédentes
    'MsgBox "Nom du bloc : " & nom_bloc_ref
    'MsgBox "Point d'insertion (1) : " & blocref.InsertionPoint(1)
    'MsgBox "Etage ref : " & etage_ref
    'MsgBox "Lim inf : " & lim_inf
    'MsgBox "Lim sup : " & lim_sup
Else
    MsgBox "L'élément sélectionné n'est pas un bloc."
    GoTo RETRY
End If
'##############FIN DE LA SELECTION DU BLOC DE REFERENCE################




'##############CARACTERISATION DU PREFILTRAGE################
'A l'avenir cette partie du code permettra la caractérisation du pré-filtrage via un userform VBA

'On détermine les coordonnées permettant de filtrer la sélection dans l'espace (X, Y, Z)
pointMin(0) = 0
pointMin(1) = lim_inf
pointMin(2) = 0
pointMax(0) = 0
pointMax(1) = lim_sup
pointMax(2) = 0


'Détermination du filtrage qui sera opéré
'Ici on filtre tous les blocs et blocs dynamiques étant sur le même étage que le bloc de référence précédemment sélectionné
filterType(0) = 0
filterType(1) = 2
filterType(2) = -4
filterType(3) = 10
filterType(4) = -4
filterType(5) = 10
filterData(0) = "INSERT"
filterData(1) = ",`*U*" '& nom_bloc_ref
filterData(2) = "*,>=,*"
filterData(3) = pointMin
filterData(4) = "*,<,*"
filterData(5) = pointMax
'##############FIN DE LA CARACTERISATION DU PREFILTRAGE################


'On sélectionne les éléments souhaités
Set selection = ThisDrawing.SelectionSets.Add("selectiondyntest1")
Set selection_finale = ThisDrawing.SelectionSets.Add("selectionfindyntest1")
selection.Select acSelectionSetAll, , , filterType, filterData


ReDim ajout(0 To selection.Count - 1) As AcadEntity
Dim i As Integer
i = 0

'/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\
'ici on sous-entend que la selection contient uniquement des blocs, à adapter si le préfiltrage doit prendre en compte d'autres objets que les blocs
'/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\
'Pour cette partie de code on vient post-filtrer afin de n'avoir que les blocs dont le nom effectif correspond au bloc de référence




For i = 0 To selection.Count - 1
    Set bloc = selection(i)
    Set objet = selection(i)
    If bloc.EffectiveName = nom_bloc_ref Then
        'LA LIGNE DE CODE SUIVANTE NE FONCTIONNE PAS
        Set ajout(i) = objet      
        'MsgBox (TypeName(bloc))
    End If
Next i
selection_finale.AddItems ajout
'MsgBox (TypeName(ajout))
'/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\


'sset.SelectOnScreen filterType, filterData
MsgBox ("Elements filtrés en première sélection : " & str(selection.Count))
MsgBox ("Elements filtrés en sélection finale: " & str(selection_finale.Count))
selection_finale.Highlight True
selection.Delete
selection_finale.Delete
End Sub



 

 

Pour le fichier de test, voir message plus haut.

Lien vers le commentaire
Partager sur d’autres sites

Bonjour @rrobert

Je n'ai pas lu ta prose, mais elle me semble quelque peu verbeuse
Je te propose ceci :

Il va falloir montrer le bloc à sélectionner, puis une sélection de ce bloc va se lancer sur l'emprise de l'étage.

C'est améliorable à l'infini, mais je reste simple pour que tu comprennes bien, pas à pas.

Amicalement

Sub Test_rrobert()
  Dim ssFiltre As AcadSelectionSet
  Dim SelRef  As AcadEntity
  Dim FilterType(1) As Integer
  Dim FilterData(1) As Variant
  Dim ptSel As Variant
  Dim Pt1(0 To 2) As Double
  Dim Pt2(0 To 2) As Double
  Dim nomBlocDyn As String
  
  ThisDrawing.Utility.GetEntity SelRef, ptSel, vbCr & "Sélectionnez le bloc de référence"
  nomBlocDyn = SelRef.EffectiveName & ",`*U*"
  Set ssFiltre = ThisDrawing.SelectionSets.Add("SS")
  FilterType(0) = 0
  FilterData(0) = "INSERT"
  FilterType(1) = 2
  FilterData(1) = nomBlocDyn
  Pt1(0) = 0#:   Pt1(1) = 50#:   Pt1(2) = 0#
  Pt2(0) = 99#:   Pt2(1) = 99#:  Pt2(2) = 0#
  ssFiltre.Select acSelectionSetWindow, Pt1, Pt2, FilterType, FilterData
  ssFiltre.Highlight (True)
  MsgBox ssFiltre.Count & " blocs sélectionnés."
  ssFiltre.Delete
End Sub

 

Lien vers le commentaire
Partager sur d’autres sites

Jusque là je vous suis @didier.

Cela me sélectionne sur un seul étage tous les blocs dont le nom correspond au bloc de référence, ainsi que tous les blocs dynamiques.

Si je veux désormais supprimer de ma sélection tous les blocs dont le EffectiveName ne correspond pas au EffectiveName du boc de référence, comment dois-je m'y prendre? 

Lien vers le commentaire
Partager sur d’autres sites

Bonjour @rrobert

Je ne comprends plus les questions, j'ai répondu à la demande : sélectionner les blocs dynamiques dont le nom correspond à celui montré en exemple.
Ce que j'ai écrit le fait, pourquoi vouloir en retirer de la sélection ? Elle est filtrée.
Sauf erreur (toujours possible le dessin fourni étant tellement simpliste) il me semble que le filtre est efficace.

Autre chose : Attention aux unités de dessin et aux blocs insérés en échelles 0.001, ça fait désordre

Amicalement

Lien vers le commentaire
Partager sur d’autres sites

il y a 11 minutes, didier a dit :

Autre chose : Attention aux unités de dessin et aux blocs insérés en échelles 0.001, ça fait désordre

Je viens justement de m'attaquer à la mise à jour des échelles des anciens plans de mon entreprise parce que là ce n'est plus possible...

 

Le filtre n'est pas complètement fonctionnel  car il sélectionne tous les blocs dont le nom correspond au premier bloc, mais aussi tous les blocs dynamiques, peu importe le nom du bloc sélectionné en amont 😕

C'est pour cela que je souhaite, après premier filtrage, supprimer les blocs dynamiques dont EffectiveName ne correspond pas au  bloc de référence.

 

Un exemple en image : j'ai sélectionné un des blocs en bas à gauche comme ref.

Le bloc dynamique en haut à droite a un nom différent, mais comme il a un nom en *U, il a également été sélectionné par le code SelRef.EffectiveName & ",`*U*"

image.png.72810a074fd28eb36d45f2503179c740.png

 

Lien vers le commentaire
Partager sur d’autres sites

Coucou,

Je ne pourrais pas vraiment t'aider en VBA, mais pourquoi créer un second jeu de sélection pour le remplir si l'élément est bon ?
Je pense qu'un simple truc comme chat ferait l'affaire (WARNING : je suis nulle en VBA donc je me contente simplement de copier ce que je comprends, c'est donc potentiellement faux à 90%)

If bloc.EffectiveName /= nom_bloc_ref Then
	selection.RemoveItems bloc
End If

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

Bonjour @rrobert

Effectivement je n'ai pas vérifié avec d'autres blocs dynamiques... (en fait ce sont les blocs dynamiques dont on a modifié un paramètre car ils deviennent anonymes à ce moment-là)
Je ne vois pas tout de suite comment faire étant sur autre chose,
Tu peux te documenter et trouver toi-même la solution d'itérer le jeu de sélection et utiliser (je pense) RemoveItem.
Je te réponds dès que je peux m'y mettre

À bientôt

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant



×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité