明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
12
返回列表 发新帖
楼主: fatkids

菜鸟求助:关于两个文档之间BlockReference复制的问题!

[复制链接]
发表于 2014-6-17 15:45:39 | 显示全部楼层
Dim trx1 As Transaction = dbInsert.TransactionManager.StartTransaction
            Dim bt1 As BlockTable = dbInsert.BlockTableId.GetObject(OpenMode.ForRead)
----------------------------
Dim trx1 As Transaction = db.TransactionManager.StartTransaction
            Dim bt1 As BlockTable = dbt.BlockTableId.GetObject(OpenMode.ForRead)
自己细心点吧
 楼主| 发表于 2014-6-17 17:02:32 | 显示全部楼层
sieben 发表于 2014-6-17 15:45
Dim trx1 As Transaction = dbInsert.TransactionManager.StartTransaction
            Dim bt1 As Block ...

谢谢sieben!
你的意思是说两个transaction和两个blocktable都应该是一个文档的,是吗?
我是在两个文档之间复制blockreference,代码里分别为另个不同文档的transaction和blocktable。
是应该这样理解吗?怎么觉得有点怪怪的?
这样的话我该如何获取保存有blockreference的文档中的entity呢?
发表于 2014-6-17 17:25:34 | 显示全部楼层
哦,我忘记了你原来的意图,我前面的修改应该错了;
应该是两个文件,两个数据库,两个transaction和两个blocktable
发表于 2014-6-17 17:28:11 | 显示全部楼层
    /// <summary>
    /// 使用一个新建的database从另外一个不打开的文件引入块记录
    /// ImportBlock_DB里的ReadDwgFile方法在编译调试环境下会出错,错误为:尝试读取或写入受保护的内存
    /// 但在正常AutoCAD启动装载程序情况下可用.
    /// </summary>
    /// <param name="fileName">另外一个文件的文件名</param>
    /// <param name="blockName">引入的一个块记录名,若为空字符串"",将引入文件里面的全部图块</param>
    /// <returns>成功返回true,否则返回false</returns>
    static public StringCollection ImportBlock_DB(string fileName, string blockName)
    {
      if (!File.Exists(fileName)) return null;
      Database sourceDb = new Database(false, true);
      try
      {
        //se.WriteMessage("\nadb.ImportBlock_DB");
        //下面的ReadDwgFile方法在编译调试环境下会出错,错误为:尝试读取或写入受保护的内存
        //但在正常AutoCAD启动装载程序情况下可用.
        sourceDb.ReadDwgFile(fileName, System.IO.FileShare.Read, false, "");
        Database destDb = aApp.DocumentManager.MdiActiveDocument.Database;
        ObjectIdCollection blockIds = new ObjectIdCollection();
        StringCollection reValue = new StringCollection();
        using (Transaction ctrans = sourceDb.TransactionManager.StartTransaction())
        {
          BlockTable cbt = (BlockTable)ctrans.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false);
          if (blockName == "")
          {
            foreach (ObjectId btrId in cbt)
            {
              BlockTableRecord cbtr = (BlockTableRecord)ctrans.GetObject(btrId, OpenMode.ForRead, false);
              if (!cbtr.IsAnonymous && !cbtr.IsLayout)
              {
                blockIds.Add(btrId);
                reValue.Add(cbtr.Name);
              }
              cbtr.Dispose();
            }
          }
          else if (cbt.Has(blockName))
          {
            blockIds.Add(cbt[blockName]);
          }
          cbt.Dispose();
          //ctrans.Commit();
        }
        if (blockIds.Count == 0)
        {
          return null;
        }
        else
        {
          IdMapping mapping = new IdMapping();
          sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, new IdMapping(), DuplicateRecordCloning.Replace, false);
          return reValue;
        }
      }
      catch (System.Exception ex)
      {
        //se.WriteMessage("\nfileName = {0}, blockName = {1}", fileName, blockName);
        se.WriteMessage(ex);
        return null;
      }
      finally { sourceDb.Dispose(); }
    }
 楼主| 发表于 2014-6-18 09:33:06 | 显示全部楼层
sieben 发表于 2014-6-17 17:28
///
    /// 使用一个新建的database从另外一个不打开的文件引入块记录
    /// ImportBlock_DB里的 ...

多谢sieben!

我读了你的代码,觉得现在的方法关键应该在下面这里:
                acCurDb.WblockCloneObjects(acObjIdColl, acBlkTblRecNewDoc.ObjectId, acIdMap, _
                                           DuplicateRecordCloning.Ignore, False)
我该写了你的代码,改成VB.net的,代码如下:
Public Sub ImportBlock_DB()
        Dim sourceDb As Database = New Database(False, True)
        Try
            ' //se.WriteMessage("\nadb.ImportBlock_DB");
            ' //下面的ReadDwgFile方法在编译调试环境下会出错,错误为:尝试读取或写入受保护的内存
            '//但在正常AutoCAD启动装载程序情况下可用.
            Dim fileName As String = "C:\Program Files\AutoCAD 2010\Sample\Dynamic Blocks\Mechanical - Metric.dwg"
           sourceDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndReadShare, False, "")

            Dim destDb As Database = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database

            Dim blockIds As ObjectIdCollection = New ObjectIdCollection()
            ' Dim reValue As StringCollection = New StringCollection()

            Dim ctrans As Transaction = sourceDb.TransactionManager.StartTransaction()
            Dim cbt As BlockTable = ctrans.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, False)

           For Each btrId As ObjectId In cbt
                Dim cbtr As BlockTableRecord = ctrans.GetObject(btrId, OpenMode.ForRead, False)
                'If cbtr.IsAnonymous <> True And cbtr.IsLayout <> True Then
                blockIds.Add(btrId)
                cbtr.Dispose()
            Next

            cbt.Dispose()

            Dim mapping As IdMapping = New IdMapping()
            sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, New IdMapping(), DuplicateRecordCloning.Replace, False)
            
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        Finally
            sourceDb.Dispose()
        End Try
    End Sub

代码执行完毕后,能够把需要的信息复制过来。但是AutoCAD会报错、死掉、退出,弹出发邮件到AutoDesk公司的窗口。
我想是因为这一句没写好:sourceDb.ReadDwgFile(fileName, System.IO.FileShare.Read, False, "")

我用的是AutoCAD2010 x64, ReadDwgFile的mode参数和你的不太一样。不知道我想的对不对!

为了不让AutoCAD死掉,我后面索性把需要的文档open,open后然后再把blocktable进行了复制,然后关掉文档。其方法就是你上面代码中提到的。

再次感谢Sieben。
发表于 2014-6-21 19:37:14 | 显示全部楼层
本帖最后由 raohuan 于 2014-6-21 19:44 编辑

Database ndb = new Database(false, true);
try
{
   ndb.ReadDwgFile(ExternalDwgFilelName, System.IO.FileShare.None, true, null);
   db.Insert(FileName, ndb, false);     //FileName:将外部文件以FileName为块名称合并到当前DWG数据库中,所以 FileName不要与其它块重名
}
catch (System.Exception ex)
{
  Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(ex.Message);
  return;
}

通过以上代码就将外部Dwg文件中的所有图块加到当前DWG中了,接下来的代码可直接调用。
注意,FileName不要和文件中的图块重名!
 楼主| 发表于 2014-6-26 16:02:38 | 显示全部楼层
raohuan 发表于 2014-6-21 19:37
Database ndb = new Database(false, true);
try
{

感谢raohuan!
该方法效率较高,满足需要。
但是会在块的列表中多出一个以当前文档命名的块,这个可以在后面程序中进行处理。
谢谢!
另外一个帖子正在看。我加你qq了,有机会来玩啊。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 14:35 , Processed in 0.133663 second(s), 16 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表