PhilBat Posté(e) le 25 avril 2012 Posté(e) le 25 avril 2012 Bonjour à tousà partir d'une sélection d'objets (selectall)je voudrai créer une autre sélection répondant à quelques critères (calque)qui au final me permet de créer un bloc sur le disque dur. :unsure: Voici un exemple de code : Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = acDoc.Editor Dim Db As Database = acDoc.Database Dim idArray() As ObjectId 'Dim blkRef As BlockReference Dim TemSsetObj As SelectionSet Dim acObjId As ObjectId Using Tr As Transaction = Db.TransactionManager.StartTransaction Dim res As PromptSelectionResult = ed.SelectAll() Dim acObjIdColl As ObjectIdCollection = New ObjectIdCollection() If (res.Status <> PromptStatus.OK) Then ed.WriteMessage(vbLf & "Failed to select all entity [Lg..-prmfolio]") GoTo Fin End If Dim acSSet As SelectionSet = res.Value For I = 0 To UBound(Calque) If Not TemForcSuf Then txtSuffixe.Text = Calque(I) For Each acObjId In acSSet.GetObjectIds() Dim acEnt As Entity = Tr.GetObject(acObjId, OpenMode.ForRead) If Not IsDBNull(acEnt) Then If Microsoft.VisualBasic.Right("00" & acEnt.Layer, 3) = Calque(I) Or (acEnt.Layer = "FDP" And Calque(I) <> "PDG") Then acObjIdColl.Add(acObjId) End If End If Next ThisDrawing.Wblock(PathAff & "\" & Trim(txtPrefixe.Text) & Trim(txtRacine.Text) & "_" & Trim(txtSuffixe.Text) & ".dwg", ????????) acObjIdColl.Clear() If TemForcSuf Then txtSuffixe.Text = IncNum(txtSuffixe.Text, 1) Next Tr.Commit() Fin: End Using Me.Close() End Sub nota: la variable 'Calque' est la liste des calques triés numériquement (calque '1' puis '2' ...etc)Suivant le lienhttp://docs.autodesk.com/ACD/2010/ENU/AutoCAD%20.NET%20Developer%27s%20Guide/index.htmlil faut utilisé une collection pour travailler avec plusieurs sélections.Mais au final j'ai besoin d'une sélection pour créer mon bloc et pas d'une collection.Comment faire ? :( MerciPhil.
Maxence DELANNOY Posté(e) le 25 avril 2012 Posté(e) le 25 avril 2012 Tu dois passer un filtre de sélection à SelectAll : var tv = new[] { new TypedValue((int) DxfCode.Operator, "<OR"), new TypedValue((int) DxfCode.LayerName, "Calque1"), new TypedValue((int) DxfCode.LayerName, "Calque2"), [..] new TypedValue((int) DxfCode.Operator, "OR>") ; var sf = new SelectionFilter(tv); ed.SelectAll(sf); C'est en C# désolé, j'ai la flemme de traduire ça en VB. Maxence DELANNOYDéveloppement de compléments aux logiciels Autodesk : AutoCAD, Revit, Inventor, Vault, Navisworks... et autres logiciels de CAOWIIP - http://wiip.fr
(gile) Posté(e) le 25 avril 2012 Posté(e) le 25 avril 2012 Salut, Comme dis Maxence, en utilisant des filtres de sélection tu auras directement des sélections. Tu peux aussi créer un jeu de sélection à partir d'un tableau d'ObjectId en utilisant la méthode statique/Shared SelectionSet.FromObjectIds(). Mais, encore une fois essaye d'arrêter de mélanger .NET et VBA...Il n'est pas difficile de de faire un Wblock à partir d'un ObjectIdCollection en .NET private void WBlock(ObjectIdCollection ids, string filename) { Database db = HostApplicationServices.WorkingDatabase; using (Database target = new Database()) { db.Wblock(target, ids, Point3d.Origin, DuplicateRecordCloning.Replace); target.SaveAs(filename, DwgVersion.Current); } } PS: tu pourrais aussi facilement éviter cet horrible GoTo... Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
PhilBat Posté(e) le 25 avril 2012 Auteur Posté(e) le 25 avril 2012 Oui pour les filtresmais il est facile de les créer quand on sait d'avance les calques concernésce qui n'est pas mon cas : d'un dwg à l'autre je n'ai pas la même chose (le nombre de calque peut varier). Il faut que je les traite dans l'ordre croissant.Je doute que le code suivant me donne un listing qui respecte cela : Using Tr As Transaction = Db.TransactionManager.StartTransaction Dim acLyrTbl As LayerTable acLyrTbl = Tr.GetObject(Db.LayerTableId, OpenMode.ForRead) For Each acObjId As ObjectId In acLyrTbl Dim acLyrTblRec As LayerTableRecord acLyrTblRec = Tr.GetObject(acObjId, OpenMode.ForRead) If acLyrTblRec.Name = "1" Then .......... End If Next End Using Il faut que le programme s'adapte. Pardon pour le goto, il faut absolument le retirer des commandes de vs2010... :blink:nota: le nom des calques peut varier de "1","2","3" à l'infini.
(gile) Posté(e) le 25 avril 2012 Posté(e) le 25 avril 2012 Pour faire ce que tu veux, si je comprends bien faire un Wblock par calque, le plus "simple" est d'utiliser Linq qui permet de faire des requêtes sur tout type de collection et donc de grouper les ObjectId des entités par calque. Un exemple: public void Test() { Document doc = AcAp.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptSelectionResult psr = ed.SelectAll(); if (psr.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { var grps = from id in psr.Value.GetObjectIds() group id by ((Entity)id.GetObject(OpenMode.ForRead)).Layer; foreach (IGrouping<string, ObjectId> grp in grps) { if (!TemForcSuf) txtSuffixe.Text = grp.Key; ObjectIdCollection ids = new ObjectIdCollection(grp.ToArray()); string filename = string.Format("{0}\\{1}{2}_{3}.dwg", PathAff, txtPrefixe.Text.Trim(), txtRacine.Text.Trim(), txtSuffixe.Text.Trim()); using (Database target = new Database()) { db.Wblock(target, ids, Point3d.Origin, DuplicateRecordCloning.Replace); target.SaveAs(filename, DwgVersion.Current); } } tr.Commit(); } } Le même code en VB: Public Sub Test() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim psr As PromptSelectionResult = ed.SelectAll If psr.Status <> PromptStatus.OK Then Return Using tr As Transaction = db.TransactionManager.StartTransaction() Dim grps = From id In psr.Value.GetObjectIds() Group id By DirectCast(id.GetObject(OpenMode.ForRead), Entity).Layer Into Group For Each grp In grps If Not TemForcSuf Then txtSuffixe.Text = grp.Layer Dim ids As ObjectIdCollection = New ObjectIdCollection(grp.Group.ToArray()) Dim filename As String = String.Format("{0}\\{1}{2}_{3}.dwg", _ PathAff, txtPrefixe.Text.Trim(), txtRacine.Text.Trim(), txtSuffixe.Text.Trim()) Using target As New Database db.Wblock(target, ids, Point3d.Origin, DuplicateRecordCloning.Ignore) target.SaveAs(filename, DwgVersion.Current) End Using Next tr.Commit() End Using End Sub On peut aussi écrire les requêtes Linq sous forme de "chaînage" de méthodes. L'interface générique IEnumerable fournit de nombreuses méthodes d'extensions (plus que ce permettent les requêtes SQL classiques. Ces méthodes requièrent souvent une (ou plusieurs) méthode comme argument (qu'on peut passer sous forme d'expression lambda). La requête ci dessus :Dim grps = psr.Value.GetObjectIds() _ .GroupBy(Function(id) DirectCast(id.GetObject(OpenMode.ForRead), Entity).Layer)Dans ce cas, dans l'expression For Each, on accède à la clé de chaque IGrouping par grp.Key et au groupe d'ObjectId directement par grp :For Each grp In grps If Not TemForcSuf Then txtSuffixe.Text = grp.Key Dim ids As ObjectIdCollection = New ObjectIdCollection(grp.ToArray()) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
(gile) Posté(e) le 25 avril 2012 Posté(e) le 25 avril 2012 Pour le fun, l'équivalent F# : let Test() = let doc = AcAp.DocumentManager.MdiActiveDocument let db = doc.Database let ed = doc.Editor let psr = ed.SelectAll() if psr.Status = PromptStatus.OK then use tr = db.TransactionManager.StartTransaction() psr.Value.GetObjectIds() |> Seq.groupBy(fun id -> (id.GetObject(OpenMode.ForRead) :?> Entity).Layer) |> Seq.iter(fun grp -> let ids = new ObjectIdCollection(snd grp |> Seq.toArray) let filename = String.Format(@"C:\Temp\{0}.dwg", fst grp) use target = new Database() db.Wblock(target, ids, Point3d.Origin, DuplicateRecordCloning.Ignore) target.SaveAs(filename, DwgVersion.Current)) tr.Commit() Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
PhilBat Posté(e) le 26 avril 2012 Auteur Posté(e) le 26 avril 2012 Salut GileMerci pour toutTu es vraiment trop fort. B) Existe t-il un livre pour en savoir plussur la prog. vb net avec autoCAD ?a+Phil
(gile) Posté(e) le 26 avril 2012 Posté(e) le 26 avril 2012 Salut, À ma connaissance il n'y en a qu'un en anglais : VB.NET Programming for AutoCAD Customization de Jerry Winters.Je ne l'ai pas lu, donc je ne peux pas en dire plus peut être que Patrick, s'il passe par là, pourra en dire plus (il me semble qu'il l'a lu). Dans tout les cas, encore une fois, avant de s'attaquer à la programmation d'AutoCAD en .NET, il est, à mon avis, indispensable de se familiariser avec .NET en général (Visual Studio, la POO, les bibliothèques de classe du Framework). Et pour ça, il y a pléthore de sites , tutoriels, livres en français comme en anglais.Par exemple, l'utilisation de Linq telle que montrée ci-dessus, n'est pas du tout spécifique à AutoCAD (Linq sert avant tout pour l'accès aux bases de données). Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Messages recommandés
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 compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant