| | | Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für Autodesk Produkte |
Autor
|
Thema: Finde Block nicht mehr unter seinem Namen (1614 mal gelesen)
|
veydan Mitglied
Beiträge: 252 Registriert: 29.05.2008 AutoCAD/Mechanical 2009, Inventor 2009
|
erstellt am: 27. Aug. 2009 14:40 <-- editieren / zitieren --> Unities abgeben:
Hallo! Ich habe folgende kuriose Situation, ich hoffe ich übersehe da jetzt nichts einfaches... Ich suche in einer Zeichnung einen Block nach Namen und möchte den dann Tauschen. Suche erfolgt so: ThisDrawing ist immer die aktuell geöffnete Zeichnung.
Code:
For Each ActBlock As Common.AcadBlock In CollBlocks CollBlocks = ThisDrawing.Blocks If vb.Right(ActBlockname, 1) = "*" And vb.Left(ActBlock.Name, ActBlockname.Length - 1) = vb.Left(ActBlockname, ActBlockname.Length - 1) Then ReplaceBlock(ActBlock.Name, NewBlockName, "TITLE", "AM_BOR") End If Next ActBlock
Da geht er in die Funktion ReplaceBlock rein und dort passiert folgendes:Code:
Dim oBlockRef As Common.AcadBlockReference = Nothing For Each oLayout In ThisDrawing.Layouts For Each oAcadEnt As Common.AcadEntity In oLayout.Block If oAcadEnt.ObjectName = "AcDbBlockReference" Then oBlockRef = CType(oAcadEnt, Common.AcadBlockReference) End If Next oAcadEnt Next oLayout
und hier finde ich den Schriftkopf unter Code: oBlockRef.Name
mit dem Namen "*U45"was geht da vor? mfg [Diese Nachricht wurde von veydan am 27. Aug. 2009 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 27. Aug. 2009 15:59 <-- editieren / zitieren -->
Hi, Zitat: mit dem Namen "*U45"
'unnamed block' ==> das ist eine Eigenheit von AutoCAD für z.B. dynamische Blöcke, wenn sich deren Repräsentation ändert, dann erhalten diese zwar die Eigenschaft, dass sie von einer Blockdefinition 'Schriftkopf' abgeleitet werden, aber in der Liste der Blockdefinitionen wird ein unnamed Block erstellt, der eben die dynamisch veränderte geometrische Darstellung definiert. - alfred - PS: die Codeschnippsel sind zu klein, um ev. auf einen Logik-Fehler zu kommen. ------------------ www.hollaus.at |
veydan Mitglied
Beiträge: 252 Registriert: 29.05.2008 AutoCAD/Mechanical 2009, Inventor 2009
|
erstellt am: 28. Aug. 2009 07:32 <-- editieren / zitieren --> Unities abgeben:
hallo Zitat: 'unnamed block' ==> das ist eine Eigenheit von AutoCAD für z.B. dynamische Blöcke, wenn sich deren Repräsentation ändert,
Was heißt deren Repräsentation ändert? Was passiert da genau? Der Block ist eigentlich mein Schriftkopf. Kann ich da vl bei einer vorigen ausführung einer Funktion in vba oder .net etwas falsch gemacht haben, damit er den Block dann unnamed macht? mfg Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 28. Aug. 2009 08:10 <-- editieren / zitieren -->
Hi, mit anderer Repräsentation meine ich (bei dynamischen Blöcken) z.B. Du hast in einem dyn Block mehrere Sichtbarkeitsparameter, einmal soll der Schriftkopf sich als 'Planungsschriftkopf', einmal als 'Bestandsschriftkopf' darstellen, entsprechend werden mit dem Sichtbarkeitsparameter im Schriftkopf ein paar Attribute/Linien/Texte ausgeschaltet und andere dafür eingeschaltet. Wenn Du diesen Block jetzt einsetzt, dann wird beim Umschalten des Sichtbarkeitsparameters eine neue Blockdefinition in AutoCAD in der Blockdefinitionstabelle erzeugt und dieser (unnamed) Block wird dann anstelle des Originalblocks an der gleichen Position eingesetzt. In der Benutzeroberfläche von AutoCAD merkst Du davon nix, aber beim API-Zugriff dann schon. Ist Dein Schriftkopf nicht als dynamischer Block definiert, dann ist ein Fehler in Deinem Code, bei dem ich Dir aber nicht helfen kann, da die Codeschnippsel hier zu kurz sind, wobei mir folgendes auffiel (ich aber das für einen Fehler beim nachtträglichen Kopieren Deines Codes hier herein halte): Code: For Each ActBlock As Common.AcadBlock In CollBlocks CollBlocks = ThisDrawing.Blocks
...ich meine, diese beiden Zeilen werden wohl vertauscht sein.Und hier sucht er JEDE BlockReference durch (die im Papierbereich des Layouts liegt), nicht nur die mit dem von Dir gesuchten Namen.
Code: For Each oAcadEnt As Common.AcadEntity In oLayout.Block If oAcadEnt.ObjectName = "AcDbBlockReference" Then oBlockRef = CType(oAcadEnt, Common.AcadBlockReference) End If Next oAcadEnt
...und ich sehe hier eigentlich nichts von '...replace...'?- alfred - ------------------ www.hollaus.at |
veydan Mitglied
Beiträge: 252 Registriert: 29.05.2008 AutoCAD/Mechanical 2009, Inventor 2009
|
erstellt am: 28. Aug. 2009 08:31 <-- editieren / zitieren --> Unities abgeben:
Hallo! ok, dann erstmal der Code: Es gibt noch ein weiteres Programm dass sich mit Schriftkopftausch beschäftigt, aber der Grundcode zum diesen ist fast gleich.Evtl haben sich dann dort die Fehler eingeschlichen mit dem unnamed Block, wobei der Tausch dort immer funktionierte. Code:
Public Function ChangeRaSK() Dim i As Integer = 0 Dim ActBlockname As String = "" Dim NewBlockFormat As String = "" Dim minExt As Object = Nothing Dim maxExt As Object = Nothing Dim insertionPoint(0 To 2) As Double Dim ValidBorder As Boolean = False AcadPrompt("change border, titleblock...") ActLayer = CreateLayer("AM_BOR", Common.AcColor.acRed) CollBlocks = ThisDrawing.Blocks For Each border In ValidBorders ChangeBorder(border, ThisDrawing) Next Dim NewBlockName As String NewBlockName = GetValueFromSettingsXML("NEWSKFILE", XMLFileSettings) ActBlockname = GetValueFromSettingsXML("TITLEBLOCKNAMESEARCHVALUE", XMLFileSettings) If ActBlockname = "" Then ActBlockname = "TITLE_*" End If For Each ActBlock As Common.AcadBlock In CollBlocks If vb.Left(ActBlockname, 1) = "*" And InStr(UCase(ActBlock.Name), UCase(Mid(ActBlockname, 2))) > 0 Then ReplaceBlock(ActBlock.Name, NewBlockName, "TITLE", "AM_BOR") ElseIf UCase(ActBlock.Name) = UCase(ActBlockname) Then ReplaceBlock(ActBlock.Name, NewBlockName, "TITLE", "AM_BOR") ElseIf vb.Right(ActBlockname, 1) = "*" And vb.Left(ActBlock.Name, ActBlockname.Length - 1) = vb.Left(ActBlockname, ActBlockname.Length - 1) Then ReplaceBlock(ActBlock.Name, NewBlockName, "TITLE", "AM_BOR") End If Next ActBlock Dim RahmenObj As Common.AcadBlockReference = Nothing Dim SkObj As Common.AcadBlockReference = Nothing SkObj = Nothing RahmenObj = Nothing End Function Public Function ReplaceBlock(ByVal oBlockName As String, ByVal sDwgFullPath As String, Optional ByVal WhatToBeChanged As String = "", Optional ByVal NewLayer As String = "") As Boolean Try Dim ActBl As Common.AcadBlock = Nothing Dim oLayout As Common.AcadLayout = Nothing Dim oAcadEntity As Common.AcadEntity = Nothing Dim oBlockRef As Common.AcadBlockReference = Nothing Dim oNewBlockRef As Common.AcadBlockReference = Nothing Dim BlockColl As Common.AcadBlocks = Nothing Dim Foundflag As Boolean Dim tmpBlockName As String = Nothing Dim vinsertionPoint As Object Dim sNewBlockName As String = Nothing Dim NewAttrib As String = Nothing Dim vXScaleFactor As Double Dim vYScaleFactor As Double Dim vZScaleFactor As Double Dim RetVal As Boolean = False Dim vinsertionPoint1(0 To 2) As Double Dim minExt As Object = Nothing Dim maxExt As Object = Nothing Dim newminExt As Double() = Nothing Dim newmaxExt As Double() = Nothing BlockColl = ThisDrawing.Blocks Foundflag = False For Each ActBlx As Common.AcadBlock In BlockColl If UCase(ActBlx.Name) = UCase(oBlockName) Then Foundflag = True ActBl = ActBlx Exit For End If Next ActBlx If UCase(WhatToBeChanged) = "BORDER" Then vinsertionPoint1(0) = 0 vinsertionPoint1(1) = 0 oNewBlockRef = ThisDrawing.ActiveLayout.Block.InsertBlock(vinsertionPoint1, ActBl.Name, 1, 1, 1, 0) oNewBlockRef.GetBoundingBox(minExt, maxExt) newminExt = CType(minExt, Double()) newmaxExt = CType(maxExt, Double()) oNewBlockRef.Delete() If newmaxExt(0) - newminExt(0) < 400 Then Foundflag = False End If Else For Each CopyRightBlock As Common.AcadBlock In BlockColl If InStr(UCase(CopyRightBlock.Name), "COPYRIGHT") > 0 And InStr(UCase(CopyRightBlock.Name), "VAI") > 0 Then tmpBlockName = CopyRightBlock.Name & "_old_" & Now.Year & Now.Month & Now.Day & Now.Hour & Now.Minute & Now.Second CopyRightBlock.Name = tmpBlockName Exit For End If Next CopyRightBlock End If If Foundflag Then tmpBlockName = ActBl.Name & "XXX_CHANGEBLOCK" & Now().Millisecond 'statt now(), Format(Date, "yyyymmdd") & Format(Time, "hhmmss") ActBl.Name = tmpBlockName For Each oLayout In ThisDrawing.Layouts For Each oAcadEnt As Common.AcadEntity In oLayout.Block If oAcadEnt.ObjectName = "AcDbBlockReference" Then oBlockRef = CType(oAcadEnt, Common.AcadBlockReference) If oBlockRef.Name = "*U45" Then 'tmpBlockName Then If sDwgFullPath <> "" Then vinsertionPoint = oBlockRef.InsertionPoint vXScaleFactor = oBlockRef.XScaleFactor vYScaleFactor = oBlockRef.YScaleFactor vZScaleFactor = oBlockRef.ZScaleFactor If sNewBlockName = "" Then oNewBlockRef = oLayout.Block.InsertBlock(vinsertionPoint, sDwgFullPath, vXScaleFactor, vYScaleFactor, vZScaleFactor, 0) sNewBlockName = oNewBlockRef.Name Else oNewBlockRef = oLayout.Block.InsertBlock(vinsertionPoint, sNewBlockName, vXScaleFactor, vYScaleFactor, vZScaleFactor, 0) End If If NewLayer <> "" Then oNewBlockRef.Layer = NewLayer End If Dim varAttributesORG As System.Array varAttributesORG = CType(oBlockRef.GetAttributes, System.Array) Dim varAttributesNEW As System.Array varAttributesNEW = CType(oNewBlockRef.GetAttributes, System.Array) 'Alle Neuen Attribute durchgehen Dim FoundAttribute As Boolean = False For j = LBound(CType(varAttributesNEW, System.Array)) To UBound(CType(varAttributesNEW, System.Array)) 'neue Attribute durchgehen FixValue = "" SourceAttributes = Nothing 'Alle SourceWerte von XML Holen, und auch FixValue, falls vorhanden GetMappingAttributeOrValue(varAttributesNEW(j).TagString, XMLFileAttributeMapping) If SourceAttributes IsNot Nothing Then 'Alle SourceAttribute durchgehen For k = 1 To SourceAttributes.Length 'Alle Alten Attribute durchgehen und schauen welches mit denen vom XML Mappingfile zusammenpasst For i = LBound(CType(varAttributesORG, System.Array)) To UBound(CType(varAttributesORG, System.Array)) 'alle Attribute durchgehen If UCase(varAttributesORG(i).TagString) = UCase(SourceAttributes(i)) Then varAttributesNEW(j).TextString = varAttributesORG(i).TextString FoundAttribute = True Exit For Else FoundAttribute = False End If Next If FoundAttribute = True Then Exit For End If Next SourceAttributes = Nothing ElseIf FixValue IsNot "" Then varAttributesNEW(j).TextString = FixValue End If Next RetVal = True End If oBlockRef.Delete() End If End If Next oAcadEnt Next oLayout End If Return RetVal Catch ex As Exception MsgBox(ex.Message & vbNewLine & ex.StackTrace) Return False End Try End Function
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
CADmium Ehrenmitglied V.I.P. h.c. Maschinenbaukonstrukteur
Beiträge: 13508 Registriert: 30.11.2003 ACAD 2004DX Mechanical PP
|
erstellt am: 28. Aug. 2009 08:37 <-- editieren / zitieren --> Unities abgeben: Nur für veydan
Referenzen eines dynamischen Blockes haben auch noch die Eigenschaft (zumindest im COM) EFFEKTIVENAME .. vielleicht sollte mal daruf gestestet werden ------------------ - Thomas - "Bei 99% aller Probleme ist die umfassende Beschreibung des Problems bereits mehr als die Hälfte der Lösung desselben." Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
veydan Mitglied
Beiträge: 252 Registriert: 29.05.2008 AutoCAD/Mechanical 2009, Inventor 2009
|
erstellt am: 28. Aug. 2009 08:48 <-- editieren / zitieren --> Unities abgeben:
|
Ex-Mitglied
|
erstellt am: 28. Aug. 2009 09:01 <-- editieren / zitieren -->
Hi, gibt's eine Zeichnung auch dazu, wo dieser unnamed Block Deiner Meinung nach vorkommt? Hilft wahrscheinlich. - alfred - ------------------ www.hollaus.at |
veydan Mitglied
Beiträge: 252 Registriert: 29.05.2008 AutoCAD/Mechanical 2009, Inventor 2009
|
erstellt am: 28. Aug. 2009 09:43 <-- editieren / zitieren --> Unities abgeben:
Würde gerne eine Datei hochladen, aber davor muss ich den Schriftkopf bearbeiten und gewissen Informationen entfernen, und sobald ich dass mache und die Datei speicher, findet er den Schriftkopf im Programm unter dem Namen TITLE_xyz und nicht unter *U45, also dann funktioniert es. Ist jetzt etwas blöd... Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 28. Aug. 2009 09:53 <-- editieren / zitieren -->
|
Ex-Mitglied
|
erstellt am: 28. Aug. 2009 11:17 <-- editieren / zitieren -->
Hi, (nach Erhalt der Zeichnung über PM)... An Deinem Block hängt ein Dictionary dran, dieses Dictionary zeigt Inhalte mit z.B. "AcDbBlockRepresentation" an, das wäre ein Hinweis, dass entweder in der Blockdefinition mal Parameter drin waren oder eine Appliktion bei der Erstellung der Blockdefinition (oder dann bei Einfügen) 'mitgewirkt' hat. Damit bleibt wohl der Weg, den CADmium schon vorgeschlagen hat ==> verwende im Code bei der Prüfung des Blocknames die Eigenschaft 'EffectiveName'. Wenn Dein Problem damit noch nicht gelöst ist, dann lass es mich/uns wissen. Zur grundsätzlichen Vorgehensweise Deiner Aufgabenstellung: wenn Du mit COM arbeitest, dann musst Du durchscannen, wie Du es auch jetzt machst (in den vielen Suchschleifen komm ich beim schnellen Hinsehen nicht ganz klar und würde mal behaupten, das sind mal unnötige For...Next drin). Solltest Du doch mal den Schritt richtung ManagedCode wagen, dann hättest Du beim BlockTableRecord eine Funktion, die Dir sofort alle ObjectID's der verwendeten Referenzen bringt, damit müsstest Du nicht durch alle Layouts durch. - alfred - ------------------ www.hollaus.at |
veydan Mitglied
Beiträge: 252 Registriert: 29.05.2008 AutoCAD/Mechanical 2009, Inventor 2009
|
erstellt am: 28. Aug. 2009 11:21 <-- editieren / zitieren --> Unities abgeben:
Managed Code geht aber nur bei dll's oder? Dieses kleine Tool soll aber über eine EXE laufen. Edit: Du hast geschriben: Zitat: oder eine Appliktion bei der Erstellung der Blockdefinition (oder dann bei Einfügen) 'mitgewirkt' hat.
also so wie es bei mir im Code jetzt geschieht mit
Code: oNewBlockRef = oLayout.Block.InsertBlock(vinsertionPoint, sDwgFullPath, vXScaleFactor, vYScaleFactor, vZScaleFactor, 0)
?? Wenn ja, wie kann ich dass verhindern, dass der Block dann Undefined ist?mfg
[Diese Nachricht wurde von veydan am 28. Aug. 2009 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Ex-Mitglied
|
erstellt am: 28. Aug. 2009 12:13 <-- editieren / zitieren -->
Hi, Zitat: Managed Code geht aber nur bei dll's oder? Dieses kleine Tool soll aber über eine EXE laufen.
..na dann ist es mit COM einfacher, ich hab aber noch nie probiert (weil OutOfProcessMemory) mit einer EXE das AutoCAD zu steuern und dabei direkt hinzugreifen. Wobei ich in solchen Fällen trotzdem eine EXE+DLL-Struktur machen würde, die EXE startet Befehle, die vom DLL dann exekutiert werden. ;) Zitat: Wenn ja, wie kann ich dass verhindern, dass der Block dann Undefined ist?
...ohne zu wissen, wann sich die Blockreference auf unnamed ändert, kann ich das nicht sagen , Dein gezeigtes 'Insert'-Statement alleine kann es nicht sein. Als erstes hätte ich mir mal die Zeichnung angesehen, die Du einfügst und dann mal händisch in eine neue Zeichnung plazieren und wenn das beides nicht dazu führt, dann überwachen zwischen einzelnen Befehlen. Kontrollieren kannst Du das von der Befehlszeile aus mit (assoc '2 (entget (car (entsel)))) - alfred - ------------------ www.hollaus.at |
| Anzeige.:
Anzeige: (Infos zum Werbeplatz >>)
|