PhilOctet Posté(e) le 15 novembre 2009 Posté(e) le 15 novembre 2009 Bonjour,J'ai besoin de nettoyer une multitude de dessins. J'ai l'intention de tous les ouvrir, un à un, et d'y faire un nettoyage de base.Pour ce, je voudrais utiliser VB.Net via un netload dans AutoCAD.La boucle "Ouvrir les dessins fonctionne", la première étape du nettoyage "ScanXRef" fonctionne aussi. Mais lorsque j'appelle l'une par un 'Call' dans l'autre, la routine appelée plante.Je vous fourni des extraits de codes. Peut-être que l'un d'entre vous peut m'aider ? 1/ code la boucle d'ouverture : '' Ouvre un à un les fichiers dessin AutoCAD CommandMethod("Open", CommandFlags.Session) Public Shared Sub Open() Dim acDocCol As DocumentCollection = Application.DocumentManager acDocCol.CloseAll() Dim acDoc As Document = Nothing ' ici création d'une boucle de recherche des dessins mais en attendant Dim filePath As String = "F:\SC Dessins\Dev\e2_apd\PLO\Cercle1.dwg" Try acDoc = acDocCol.Open(filePath, False) acDocCol.MdiActiveDocument = acDoc Catch Debug.Print("Abandon de : " & filePath) End Try acDoc.Editor.WriteMessage(vbLf & acDoc.Name) Call ScanXRef() End Sub Remarquez le "Call ScanXRef" 2/ extrait de ScanXRef : CommandMethod("ScanXRef") Public Shared Sub ScanXRef() Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument Dim acCurDb As Database = HostApplicationServices.WorkingDatabase() Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction() '' Retourne la table des blocks dans la base de données courantes Dim acBlkTbl As BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForWrite) Dim acColors(2) As Color '' traite un à un les différents blocs Dim acBlkTblRec As BlockTableRecord Dim acBlkPathName As String Dim SuppXRef As Boolean = False For Each acObjId As ObjectId In acBlkTbl acBlkTblRec = acTrans.GetObject(acObjId, OpenMode.ForWrite) ... Le plantage surgit sur les lignes des "OpenMode.ForWrite". L'erreur est une eLockViolation Pourtant et indépendemment, les deux nouvelles fonctions AutoCAD se déroulent bien. Que faut-il que je modifie à l'une ou à l'autre des routines pour que cela fonctionne bien ?Considérant mon niveau, un peu d'explication ne serait par superflu. Merci de m'aider.
(gile) Posté(e) le 15 novembre 2009 Posté(e) le 15 novembre 2009 Salut, Je ne suis aussi débutant en .NET et j'ai du mal à lire le VB (je préfère C#) mais je vais essayer... Au vu de ton erreur (eLockViolation), j'essayerais : Try acDoc = acDocCol.Open(filePath, False) acDocCol.MdiActiveDocument = acDoc Catch Debug.Print("Abandon de : " & filePath) End Try acDoc.Editor.WriteMessage(vbLf & acDoc.Name) [surligneur]Dim docLock as DocumentLock = acDoc.LockDocument() ScanXRef() docLock.Dispose()[/surligneur] End Sub Ou, plus simplement : Try acDoc = acDocCol.Open(filePath, False) acDocCol.MdiActiveDocument = acDoc Catch Debug.Print("Abandon de : " & filePath) End Try acDoc.Editor.WriteMessage(vbLf & acDoc.Name) [surligneur]acDoc.SendStringToExecute("ScanXRef ", true, fals, false)[/surligneur] End Sub Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
(gile) Posté(e) le 15 novembre 2009 Posté(e) le 15 novembre 2009 Re, Tu n'est peut-être pas obligé d'ouvrir les fichiers que tu as à traiter. On peut accéder à la base de données de fichiers DWG qui ne sont pas ouvert dans l'éditeur AutoCAD, le processus devrait être plus rapide. Un exemple simple :une commande : TEST qui permet de choisir plusieurs fichiers dans une boite de dialogue et appelle la méthode DoIt pour chacun des fichiers.La méthode DoIt accède à la base de donnée du fichier sans l'ouvrir et appelle AddCircle qui dessine un cercle de centre 0,0,0 et de rayon 100 dans l'espace objet puis enregistre le fichier.Par mesure de précaution, dans la méthode DoIt, on teste si le fichier est le document actif ou un fichier ouvert parceque le traitement est différent dans chaque cas.Il va sans dire que l'exécution devrait être plus rapide si tous les fichier à traiter sont fermés.. Le code C#using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.Windows; using acadApp = Autodesk.AutoCAD.ApplicationServices.Application; namespace SideDatabaseSample { public class Commands { // Commande TEST : ouvre la boite de dialogue pour choisir les fichiers à traiter [CommandMethod("TEST")] public void TEST() { Editor ed = acadApp.DocumentManager.MdiActiveDocument.Editor; OpenFileDialog.OpenFileDialogFlags flag = OpenFileDialog.OpenFileDialogFlags.AllowMultiple; OpenFileDialog ofd = new OpenFileDialog("Sélectionnez les fichiers", "", "dwg", "", flag); if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { try { string[] filenames = ofd.GetFilenames(); foreach (string filename in filenames) { DoIt(filename); } } catch (System.Exception ex) { ed.WriteMessage("\nErreur: " + ex.Message); } } } // Accès à la base de donnée d'un ficher dwg ouvert ou fermé private void DoIt(string filename) { DocumentCollection docs = acadApp.DocumentManager; // si le fichier est le document actif if (docs.MdiActiveDocument.Name == filename) AddCircle(docs.MdiActiveDocument.Database); // sinon, else { Database db = null; // si le fichier est ouvert foreach (Document doc in docs) { if (doc.Name == filename) { using (DocumentLock docLock = doc.LockDocument()) { db = doc.Database; AddCircle(db); } doc.CloseAndSave(filename); } } // si le fichier est fermé if (db == null) { using (db = new Database(false, true)) { db.ReadDwgFile(filename, System.IO.FileShare.ReadWrite, true, string.Empty); AddCircle(db); db.SaveAs(filename, DwgVersion.Current); } } } } // Ajout d'un cercle de centre 0,0,0 et de rayon 100 dans l'espace objet et enregistrement private void AddCircle(Database db) { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[blockTableRecord.ModelSpace], OpenMode.ForWrite); Circle circ = new Circle(new Point3d(0.0, 0.0, 0.0), new Vector3d(0.0, 0.0, 1.0), 100.0); btr.AppendEntity(circ); tr.AddNewlyCreatedDBObject(circ, true); tr.Commit(); } } } } La traduction en VB (faite ici)Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.EditorInput Imports Autodesk.AutoCAD.Geometry Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.Windows Imports acadApp = Autodesk.AutoCAD.ApplicationServices.Application Namespace SideDatabaseSample Public Class Commands ' Commande TEST : ouvre la boite de dialogue pour choisir les fichiers à traiter _ Public Sub TEST() Dim ed As Editor = acadApp.DocumentManager.MdiActiveDocument.Editor Dim flag as OpenFileDialog.OpenFileDialogFlags = OpenFileDialog.OpenFileDialogFlags.AllowMultiple; Dim ofd as OpenFileDialog = new OpenFileDialog("Sélectionnez les fichiers", "", "dwg", "", flag); If ofd.ShowDialog() = System.Windows.Forms.DialogResult.OK Then Try Dim filenames As String() = ofd.GetFilenames() For Each filename As String In filenames DoIt(filename) Next Catch ex As System.Exception ed.WriteMessage(vbLf & "Erreur: " & ex.Message) End Try End If End Sub ' Accès à la base de donnée d'un ficher dwg ouvert ou fermé Private Sub DoIt(ByVal filename As String) Dim docs As DocumentCollection = acadApp.DocumentManager ' si le fichier est le document actif If docs.MdiActiveDocument.Name = filename Then AddCircle(docs.MdiActiveDocument.Database) Else ' sinon, Dim db As Database = Nothing ' si le fichier est ouvert For Each doc As Document In docs If doc.Name = filename Then Using docLock As DocumentLock = doc.LockDocument() db = doc.Database AddCircle(db) End Using doc.CloseAndSave(filename) End If Next ' si le fichier est fermé If db Is Nothing Then Using db = New Database(False, True) db.ReadDwgFile(filename, System.IO.FileShare.ReadWrite, True, String.Empty) AddCircle(db) db.SaveAs(filename, DwgVersion.Current) End Using End If End If End Sub ' Ajout d'un cercle de centre 0,0,0 et de rayon 100 dans l'espace objet et enregistrement Private Sub AddCircle(ByVal db As Database) Using tr As Transaction = db.TransactionManager.StartTransaction() Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable) Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord) Dim circ As New Circle(New Point3d(0.0, 0.0, 0.0), New Vector3d(0.0, 0.0, 1.0), 100.0) btr.AppendEntity(circ) tr.AddNewlyCreatedDBObject(circ, True) tr.Commit() End Using End Sub End Class End Namespace Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
PhilOctet Posté(e) le 17 novembre 2009 Auteur Posté(e) le 17 novembre 2009 Bonsoir Gile, Je te remercie pour tes bouts de code. Il m'ont bien aidé. Aussi, l'intérêt de mes routines est qu'elles vont être pouvoir servir à deux titres : - un usage préventif lors de l'intégration des fichiers sur notre serveur, - un usage d'aide aux utilisateurs sur des dessins seront ouverts. Mais il est vrai que j'envisage des outils de traitements sur la masse des dessins et là je m'attacherai à la deuxième partie de ton message. Donc encore merci.
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