Why the List of dbtexts can't add to database?

Why the List of dbtexts can't add to database?

mystarxk-cn
Explorer Explorer
419 Views
2 Replies
Message 1 of 3

Why the List of dbtexts can't add to database?

mystarxk-cn
Explorer
Explorer

Hi,everyone,

I want to explode some blocks and keep text ,like the command "Burst",so,use readdwgfile to load the dwg file and explode it,but,when I cerate the new dbtext,it can't add to database?

 

 

this is my code:

       public static void BurstBlock(Transaction trans, BlockTableRecord blockTableRecord, BlockReference blockRef)
       { 
           List<DBText> textsToAdd = new List<DBText>();
           foreach (ObjectId attId in blockRef.AttributeCollection)
           {
               AttributeReference attRef = (AttributeReference)trans.GetObject(attId, OpenMode.ForRead);
               if (attRef == null || !attRef.Visible) continue;
               DBText newText = new DBText
               {
                   TextString = attRef.TextString,
                   Position = attRef.Position,
                   Height = attRef.Height,
                   Layer = "0",
                   //TextStyleId = attRef.TextStyleId,
                   Rotation = attRef.Rotation,
                   //ColorIndex = 11,
               };
               
               textsToAdd.Add(newText);
           }
           try
           {
               foreach (var text in textsToAdd)
               {
                   if (text.IsNewObject)
                   {
                       blockTableRecord.AppendEntity(text);
                       trans.AddNewlyCreatedDBObject(text, true);
                   }
               }
           }
           catch (System.Exception ex)
           {
               System.Windows.MessageBox.Show(ex.Message.ToString(), "文件级错误2");
           }
           var explodedObjects = new DBObjectCollection();
           blockRef.Explode(explodedObjects);
           foreach (DBObject obj in explodedObjects)
           {
               using (obj)
               {
                   if (obj is BlockReference nestedBlockRef)
                   {
                       BurstBlock(trans, blockTableRecord, nestedBlockRef);
                   }
                   if (obj is Entity ent && !(ent is AttributeDefinition))
                   {
                       blockTableRecord.AppendEntity(ent);
                       trans.AddNewlyCreatedDBObject(ent, true);
                   }
               }
           }
0 Likes
Accepted solutions (1)
420 Views
2 Replies
Replies (2)
Message 2 of 3

norman.yuan
Mentor
Mentor

When you say "... can't...", you probably actually mean that the code DOES NOT add the new DBTexts to the database,  don't you?

 

You did not show the code where the Transaction is created and committed, or not decribed/explained that your code indeed commits the Transaction. So, the very first question to ask is: is the transaction COMMITTED after the code you showed here?

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 3 of 3

ActivistInvestor
Mentor
Mentor
Accepted solution

Your code is a minimal implementation of a managed version of the 'BURST' express tool command, but the problem is a bit more complicated, and requires checking for things like if a block reference can be exploded (based on its insertion scale factors and the Explodable property of the referenced BlockTableRecord). Since you're not showing all of the code involved (e.g., the code that manages the Transaction), I can't speculate on what the problem may be.

 

As far as re-inventing the BURST express tool, long ago I built a class that used a TransformOverrule to recursively explode or 'nuke' block references and all nested block references. I was able to easily adapt that code to add the things the BURST command does. I also cleaned up the code and removed dependencies on other code. I'm posting it here mainly to illustrate the problem in all its depth and complexity.

 

/// BurstOverrule.cs  
/// 
/// ActivistInvestor / Tony T
/// 
/// Distributed under terms of the MIT license.

/// Adapted from code that performs specialized
/// handling of entities produced by exploding
/// a block reference. This adaptation includes 
/// the functionality of the legacy BURST express 
/// tool. As written, this code wasn't tested with
/// and may not support fields in attributes.
///
/// Caveat emptor: 
///
/// This code was only minimally-tested.
/// Use at your own risk.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using AcRx = Autodesk.AutoCAD.Runtime;

namespace AcMgdLib.DatabaseServices
{
   public class BurstOverrule : TransformOverrule
   {
      RXClass target = RXObject.GetClass(typeof(BlockReference));
      bool recursive = false;
      int depth = 0;
      
      public BurstOverrule(bool recursive = false)
      {
         this.recursive = recursive;
         AddOverrule(target, this, true);
      }

      protected override void Dispose(bool disposing)
      {
         if(disposing && target != null)
         {
            RemoveOverrule(target, this);
            target = null;
         }
         base.Dispose(disposing);
      }

      public override void Explode(Entity entity, DBObjectCollection items)
      {
         try
         {
            int begin = items.Count;
            base.Explode(entity, items);
            if(items.Count == begin)
               return;
            var attdefs = items.OfType<AttributeDefinition>().ToArray();
            /// Remove attribute definitions:
            foreach(AttributeDefinition attdef in attdefs)
            {
               items.Remove(attdef);
               attdef.Dispose();
            }

            /// Replace attribute references with text or mtext:
            if(entity is BlockReference blockRef)
            {
               using(var tr = new OpenCloseTransaction())
               {
                  var btr = (BlockTableRecord)tr.GetObject(blockRef.BlockTableRecord, OpenMode.ForRead);
                  if(btr.Explodable)
                  {
                     if(btr.HasAttributeDefinitions)
                     {
                        var atts = blockRef.GetAttributes(tr);
                        foreach(var attref in atts)
                        {
                           if(attref.IsMTextAttribute)
                           {
                              items.Add((MText)attref.MTextAttribute.Clone());
                           }
                           else
                           {
                              var text = new DBText();
                              text.SetDatabaseDefaults(btr.Database);
                              attref.CopyPropertiesTo(text);
                              items.Add(text);
                           }
                        }
                     }
                     if(recursive)
                     {
                        var nested = items.OfType<BlockReference>().ToArray();
                        if(nested.Length > 0)
                        {
                           for(int i = 0; i < nested.Length; i++)
                           {
                              BlockReference nestedRef = nested[i];
                              BlockTableRecord nestedBtr = (BlockTableRecord)
                                 tr.GetObject(nestedRef.BlockTableRecord, OpenMode.ForRead);
                              if(CanExplode(nestedBtr) && nestedRef.ScaleFactors.IsProportional())
                              {
                                 try
                                 {
                                    ++depth;
                                    using(DBObjectCollection nestedResult = new DBObjectCollection())
                                    {
                                       nestedRef.Explode(nestedResult);
                                       items.Remove(nestedRef);
                                       nestedRef.Dispose();
                                       foreach(DBObject obj in nestedResult)
                                          items.Add(obj);
                                       nestedResult.Clear();
                                    }
                                 }
                                 catch(AcRx.Exception ex)
                                 {
                                    DebugOutput.Write(ex.ToString());
                                 }
                                 finally
                                 {
                                    --depth;
                                 }
                              }
                           }
                        }
                     }
                  }
                  tr.Commit();
               }
            }
         }
         catch(System.Exception ex)
         {
            DebugOutput.Write(ex.ToString());
         }

      }

      static bool CanExplode(BlockTableRecord btr)
      {
         return btr.Explodable && 
            !(btr.IsFromExternalReference 
               || btr.IsFromOverlayReference 
               || btr.IsDependent);
      }
   }

   public static class BurstOverruleExtensions
   {
      /// <summary>
      /// Get AttributeReferences from the given block reference (lazy).
      /// Can enumerate AttributeReferences of database resident and
      /// non-database resident BlockReferences.
      /// </summary>

      internal static IEnumerable<AttributeReference> GetAttributes(this BlockReference blkref,
         Transaction tr,
         OpenMode mode = OpenMode.ForRead,
         bool add = true)
      {
         if(blkref is null)
            throw new ArgumentNullException(nameof(blkref));
         if(tr is null)
            throw new ArgumentNullException(nameof(tr));
         var objects = blkref.AttributeCollection.Cast<object>();
         object first = objects.FirstOrDefault();
         if(first != null)
         {
            if(first is AttributeReference)
            {
               foreach(AttributeReference attref in blkref.AttributeCollection)
               {
                  if(add)
                     tr.AddNewlyCreatedDBObject(attref, true);
                  yield return attref;
               }
            }
            else
            {
               foreach(ObjectId id in blkref.AttributeCollection)
                  if(!id.IsErased)
                     yield return (AttributeReference)tr.GetObject(id, mode, false, false);
            }
         }
      }

      internal static void CopyPropertiesTo(this DBObject source, DBObject dest)
      {
         if(source is null)
            throw new ArgumentNullException(nameof(source));
         if(dest is null)
            throw new ArgumentNullException(nameof(dest));
         if(!dest.IsWriteEnabled)
            throw new AcRx.Exception(ErrorStatus.NotOpenForWrite);
         Type destType = dest.GetType();
         foreach(PropertyDescriptor pd in TypeDescriptor.GetProperties(source))
         {
            if(!pd.IsReadOnly && pd.ComponentType.IsAssignableFrom(destType))
            {
               object value = "(null)";
               try
               {
                  value = pd.GetValue(source);
                  if(value != null)
                     pd.SetValue(dest, value);
                  else
                     value = "(null)";
               }
               catch(AcRx.Exception ex)
               {
                  DebugOutput.Write(
                     $"Property {pd.Name} = {value.ToString()} threw ErrorStatus.{ex.ErrorStatus}");
               }
               catch(System.Exception ex)
               {
                  DebugOutput.Write(
                     $"Property {pd.Name} = {value.ToString()} threw {ex.Message}");
               }
            }
         }
      }

   }

   internal static class DebugOutput
   {
      [Conditional("DEBUG")]
      internal static void Write(string msg)
      {
         // CopyPropertiesTo() throws many exceptions
         // that are mostly-benign. Uncomment this to
         // see them on the Console, or just look at
         // the debug console.

         //Application.DocumentManager.MdiActiveDocument
         //   .Editor.WriteMessage(msg);

         Debug.WriteLine(msg);
      }
   }
}

 

Example usage:

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace AcMgdLib.DatabaseServices.Examples
{
   public static class TestBurstOverrule
   {
      [CommandMethod("MGDBURST", CommandFlags.UsePickSet | CommandFlags.Redraw)]
      public static void MgdBurstCommand()
      {
         Document doc = Application.DocumentManager.MdiActiveDocument;
         Editor ed = doc.Editor;
         PromptSelectionOptions pso = new PromptSelectionOptions();
         pso.RejectObjectsFromNonCurrentSpace = true;
         pso.RejectObjectsOnLockedLayers = true;
         pso.RejectPaperspaceViewport = true;
         var psr = ed.GetSelection(pso);
         if(psr.Status != PromptStatus.OK)
            return;
         ed.InitCommandVersion(2);
         using(new BurstOverrule(true))
         {
            ed.Command("._EXPLODE", psr.Value, "");
         }
      }
   }
}