Aller au contenu

modification de xrefs


PhilOctet

Messages recommandés

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.

Lien vers le commentaire
Partager sur d’autres sites

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

Lien vers le commentaire
Partager sur d’autres sites

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

Lien vers le commentaire
Partager sur d’autres sites

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.

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é