在CAD文件中存储自定义的数据,XData,XRecord,DataTable

基础知识:

  根据CAD官方的资料看来,Database作为一个CAD文件数据库的根对象,其包含10个子对象:九大符号表(SymbolTable)和命名对象词典(NamedObjectsDictionary)。

   这10个子对象属于整个数据库内的最高层级,直属于Database。除这10个子对象以外,所有DBObject对象都必须有一个所有者(Owner),这个所有者可以是其它的DBObject,或者是这10个子对象之一。因此,整个数据库是一个树形结构,存在于数据库中的对象都直接或间接地属于这10个子对象。

  根据数据库的树形结构,所有DBObject对象根据其自身类别,分别属于不同对象。比如:BlockTable中包含多个BlockTableRecord,某个BlockTableRecord又包含多个Entity,其中每个Entity的存在都依赖于其BlockTableRecord的存在。各种信息就是这样分门别类地存储在数据库中。内存中New()生成的对象要加入数据库中,需要调用数据库中已存在的某个对象对应的方法才行,比如;blockTableRecord.AppendEntity(Entity entity);加入后要使用Database.AddNewlyCreatedDBObject(DBObject obj,bool add)方法进行确认。

存储自定义数据的方式:

  为便于扩展,Autodesk设计了多种方式存储用户自定义的数据。“这些数据由开发者自己进行解释 ,CAD不管其含义,扩展数据以吸附物的形式吸附在实体上”。其中资料最多的是XData形式,其次有XRecord和DataTable。几种方式各有异同。

  在了解这三种方法之前,先要了解两个基础知识:ResultBuffer类和DBDictionary类。

  ResultBuffer是一个键值对集合,key是一个DxfCode(short),value是对应的某个类型的object,其本质就是一个Dxf组码表,其中的数据必须按照Dxf组码类型表进行存储。一个ResultBuffer对象最高存储128K的数据。

  DBDictionary也是一个键值对集合,key是一个开发者自行指定的string,value是一个DBObject实例。

  DBDictionary可以作为附加数据依附在一个DBObject实例上,存储和这个DBObject相关的数据,访问方式为DBObject.ExtensionDictionary。依附于一个DBObject的DBDictionary会随着这个DBObject的删除而删除。类似的,DBDictionary也可以依附于Database存储全局数据;访问方式为Database.NamedObjectsDictionaryId。

  所有的Entity只能存储在BlockTableRecord下,因此Entity不能直接存入DBDictionary。

  不可以把已经添加到Database中的DBObcect添加进DBDictionary,添加操作完成后要使用Database.AddNewlyCreatedDBObject(DBObject obj,bool add)方法进行确认。

  由于九大符号表无法满足所有的数据存储需求,特别是新版本增加功能的同时还要保证向下兼容,很多数据存储是借助于Database的命名对象词典完成的,可以自行遍历求证,以下是我自己遍历的代码和结果。 

复制代码
 1         public static void TraverseNamedObjectsDictionaryDemo()
 2         {
 3             var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.CurrentDocument;
 4             if (doc == null) return;
 5             var db = doc.Database;
 6             var ed = doc.Editor;
 7             using (var trans = db.TransactionManager.StartTransaction())
 8             {
 9                 var dict = trans.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead) as DBDictionary;
10                 foreach (var entry in dict)
11                 {
12                     string s =  $"[{$"{entry.Key}]",-50}=>   ";
13                     var value = trans.GetObject(entry.Value, OpenMode.ForRead);
14                     s+=value.GetType().ToString()+"\n";
15                     ed.WriteMessage(s);
16                 }
17                 ed.WriteMessage("已遍历完NamedObjectsDictionary。\n");
18             }
19         }
20         //以下是遍历结果,我的环境是AutoCAD2019,没有测试其他版本
21         //[ACAD_ASSOCPERSSUBENTMANAGER]=>                             Autodesk.AutoCAD.DatabaseServices.ImpDBObject
22         //[ACAD_BACKGROUND]=>                                         Autodesk.AutoCAD.DatabaseServices.DBDictionary
23         //[ACAD_CIP_PREVIOUS_PRODUCT_INFO]=>                          Autodesk.AutoCAD.DatabaseServices.Xrecord
24         //[ACAD_COLOR]=>                                              Autodesk.AutoCAD.DatabaseServices.DBDictionary
25         //[ACAD_DATALINK]=>                                           Autodesk.AutoCAD.DatabaseServices.DBDictionary
26         //[ACAD_DETAILVIEWSTYLE]=>                                    Autodesk.AutoCAD.DatabaseServices.DBDictionary
27         //[ACAD_DGNDEFINITIONS]=>                                     Autodesk.AutoCAD.DatabaseServices.DBDictionary
28         //[ACAD_DWFDEFINITIONS]=>                                     Autodesk.AutoCAD.DatabaseServices.DBDictionary
29         //[ACAD_FIELDLIST]=>                                          Autodesk.AutoCAD.DatabaseServices.ImpDBObject
30         //[ACAD_GROUP]=>                                              Autodesk.AutoCAD.DatabaseServices.DBDictionary
31         //[ACAD_LAYOUT]=>                                             Autodesk.AutoCAD.DatabaseServices.DBDictionary
32         //[ACAD_MATERIAL]=>                                           Autodesk.AutoCAD.DatabaseServices.DBDictionary
33         //[ACAD_MLEADERSTYLE]=>                                       Autodesk.AutoCAD.DatabaseServices.DBDictionary
34         //[ACAD_MLINESTYLE]=>                                         Autodesk.AutoCAD.DatabaseServices.DBDictionary
35         //[ACAD_PDFDEFINITIONS]=>                                     Autodesk.AutoCAD.DatabaseServices.DBDictionary
36         //[ACAD_PERSUBENTMGR]=>                                       Autodesk.AutoCAD.DatabaseServices.ImpDBObject
37         //[ACAD_PLOTSETTINGS]=>                                       Autodesk.AutoCAD.DatabaseServices.DBDictionary
38         //[ACAD_PLOTSTYLENAME]=>                                      Autodesk.AutoCAD.DatabaseServices.DictionaryWithDefaultDictionary
39         //[ACAD_RENDER_ACTIVE_RAPIDRT_SETTINGS]=>                     Autodesk.AutoCAD.DatabaseServices.RapidRTRenderSettings
40         //[ACAD_RENDER_ACTIVE_SETTINGS]=>                             Autodesk.AutoCAD.DatabaseServices.RenderSettings
41         //[ACAD_SCALELIST]=>                                          Autodesk.AutoCAD.DatabaseServices.DBDictionary
42         //[ACAD_SECTIONVIEWSTYLE]=>                                   Autodesk.AutoCAD.DatabaseServices.DBDictionary
43         //[ACAD_TABLESTYLE]=>                                         Autodesk.AutoCAD.DatabaseServices.DBDictionary
44         //[ACAD_VISUALSTYLE]=>                                        Autodesk.AutoCAD.DatabaseServices.DBDictionary
45         //[AcDbVariableDictionary]=>                                  Autodesk.AutoCAD.DatabaseServices.DBDictionary
46         //[ASE_INDEX_DICTIONARY]=>                                    Autodesk.AutoCAD.DatabaseServices.DBDictionary
View Code
复制代码

XData:

  XData是最简便的附加自定义数据的方式,使用的是ResultBuffer数据类型。

  一个DBObject附加的XData最多只能存储16K的数据,不同的DxfCode对应的存储空间也有最大值限制。

  XData中存储的某些数据可以跟随CAD环境或者Entity进行变化而无需开发者参与,其它语言也能轻松访问,这是使用XData的优势。

  由于存储量的限制,XData方式只适合存储少量数据;并且其中Value的类型必须和DxfCode相对应,限制了它的灵活性。

  大致流程如下:

  1、new一个ResultBuffer,然后调用其Add(new TypedValue((int)code, Value))方法添加键值对。

  2、写模式打开DBObject,赋值Obj.XData = ResultBuffer。

  3、读:ResultBuffer resultBuffer=Obj.XData。

  注意点如下:

  1、为区分不同的用户(开发者),对于DBObject.XData赋值的时候要求:写入的ResultBuffer第一个键值对须使用new TypedValue((int)DxfCode.ExtendedDataRegAppName, AppName),以此来区分不同的用户(开发者);具有不同AppName开始的ResultBuffer在赋值的时候不会相互覆盖。需要读数据时,使用Obj.GetXDataForApplication(AppName)可以只读自己写入的那一段。

  2、写入带有DxfCode.ExtendedDataRegAppName键值对的ResultBuffer的时候,要求AppName在Database中是注册过的。因此,在写入带AppName的ResultBuffer之前,应进行两个操作:将DBObject加入Database,在Database的RegAppTable中注册AppName。

  3、写入的键值对要求DxfCode不小于DxfCode.ExtendedDataAsciiString(1000),可以去查看Dxf组码类型表,小于DxfCode.ExtendedDataAsciiString(1000)的是属于“原生”的组码,这些组码在CAD中有其专有用途,因此不对XData开放。大于等于的是属于“扩展”的,用于存储二次开发的信息。

  4、除DxfCode.ExtendedDataRegAppName外,ResultBuffer中允许连续或间断写入相同的Dxf组码的内容。

  5、写入的部分数据会跟随Entity的Transform而发生改变。利用这个设定,可以达到一些特定的目的,比如将Entity上的特殊点以XData的形式记录在Entity上,当客户利用CAD原生的Move、Rotate等命令操作此Entity时,这些点将跟随同步变化;再如,通过判断Scale是否发生改变来判断客户是否对该实体进行过缩放操作。需要注意的是,这些数据只对Entity整体的Transform敏感,客户的某些操作不会触发Transform操作,因此这些操作不会导致XData发生变化,比如客户使用STRETCH命令拉伸了多段线的部分节点。

  6、XData的数据在写入和读出的时候可能发生类型转换,这很容易导致在验证之前存入的数据时发生意料之外的情况,具体可自行测试。

  具体可参考如下代码:

复制代码
  1     public static class XDataDemo
  2     {
  3         static string AppName = "XDataDemoAppName";
  4         public static void WriteXDataDemo()
  5         {
  6             var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.CurrentDocument;
  7             if (doc == null) return;
  8             var db = doc.Database;
  9             var ed = doc.Editor;
 10             var pResult = ed.GetEntity("选择一个Entity"+"\n");
 11             if (pResult.Status!= Autodesk.AutoCAD.EditorInput.PromptStatus.OK) { ed.WriteMessage("选择Entity失败,退出"+"\n"); return; }
 12             RegisterAppName(db, AppName);
 13             RegisterAppName(db, AppName+"2");
 14             var xData = CreatNewXData();
 15             var xData2 = CreatNewXData2();
 16             using (var trans = db.TransactionManager.StartTransaction())
 17             {
 18                 var ent = trans.GetObject(pResult.ObjectId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite);
 19                 ent.XData = xData;//此处使用的赋值语句
 20                                   //CAD内部好像进行了额外的处理
 21                                   //比如验证AppName是否已注册、验证该实体的XData中是否已有相同的AppName的XData
 22                 ent.XData = xData2;//第二次赋值不会覆盖第一次的赋值,因为两个XData的AppName不相同
 23                 ed.WriteMessage("写入XData成功"+"\n");
 24                 trans.Commit();
 25             }
 26         }
 27         public static void ReadXDataDemo()
 28         {
 29             var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.CurrentDocument;
 30             if (doc == null) return;
 31             var db = doc.Database;
 32             var ed = doc.Editor;
 33             var pResult = ed.GetEntity("选择一个Entity"+"\n");
 34             if (pResult.Status!= Autodesk.AutoCAD.EditorInput.PromptStatus.OK) { ed.WriteMessage("选择Entity失败,退出"+"\n"); return; }
 35             using (var trans = db.TransactionManager.StartTransaction())
 36             {
 37                 var ent = trans.GetObject(pResult.ObjectId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite);
 38                 var xData = ent.XData;//获取全部XData
 39                                       //     xData=ent.GetXDataForApplication(AppName);//获取指定应用的XData
 40                 PrintXData(xData, ed);
 41             }
 42         }
 43         public static void ClearXDataDemo()
 44         {
 45             var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.CurrentDocument;
 46             if (doc == null) return;
 47             var db = doc.Database;
 48             var ed = doc.Editor;
 49             var pResult = ed.GetEntity("选择一个Entity"+"\n");
 50             if (pResult.Status!= Autodesk.AutoCAD.EditorInput.PromptStatus.OK) { ed.WriteMessage("选择Entity失败,退出"+"\n"); return; }
 51             RegisterAppName(db, AppName);
 52 
 53             using (var trans = db.TransactionManager.StartTransaction())
 54             {
 55                 var ent = trans.GetObject(pResult.ObjectId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite);
 56                 //这两种方法不能清除XData
 57                 //ent.XData=null;
 58                 //ent.XData=new ResultBuffer();
 59                 //测试通过的方法如下:
 60                 var xData = new ResultBuffer();
 61                 xData.Add(new TypedValue((int)DxfCode.ExtendedDataRegAppName, AppName));
 62                 //只能清除指定AppName的XData
 63                 //要清除全部XData,需要遍历所有AppName,并删除对应XData
 64                 ent.XData = xData;
 65                 ed.WriteMessage("清除XData成功。"+"\n");
 66                 trans.Commit();
 67             }
 68         }
 69         private static void RegisterAppName(Database db, string appName)
 70         {
 71             using (var trans = db.TransactionManager.StartTransaction())
 72             {
 73                 var regAppTable = trans.GetObject(db.RegAppTableId, OpenMode.ForRead) as RegAppTable;
 74                 if (!regAppTable.Has(appName))
 75                 {
 76                     regAppTable.UpgradeOpen();
 77                     var regAppTableRecord = new RegAppTableRecord();
 78                     regAppTableRecord.Name = appName;
 79                     regAppTable.Add(regAppTableRecord);
 80                     trans.AddNewlyCreatedDBObject(regAppTableRecord, true);
 81                     trans.Commit();
 82                 }
 83             }
 84         }
 85         private static ResultBuffer CreatNewXData()
 86         {
 87             var xData = new ResultBuffer();
 88             //插入了注册的应用名称,用于区分不同应用的XData
 89             xData.Add(new TypedValue((int)DxfCode.ExtendedDataRegAppName, AppName));
 90             //插入了一个字符串,用于记录需要的信息
 91             xData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "Point_1"));
 92             //插入了一个点的坐标,Entity发生Transform时,点的坐标也会发生变化
 93             xData.Add(new TypedValue((int)DxfCode.ExtendedDataWorldXCoordinate, new Point3d(100, 200, 300)));
 94             xData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "Point_2"));
 95             //使用相同的DxfCode插入了第二个点,两次插入的数据都会被保存在ResultBuffer中
 96             xData.Add(new TypedValue((int)DxfCode.ExtendedDataWorldXCoordinate, new Point3d(400, 500, 600)));
 97             xData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "Vector_1"));
 98             //插入了一个向量,此处需要将向量转化为Point3d数据类型
 99             //向量对旋转的Transform敏感,对平移和缩放不敏感
100             xData.Add(new TypedValue((int)DxfCode.ExtendedDataWorldXDir, new Point3d(100, 0, 0)));
101             xData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "scale"));
102             //插入了一个缩放因子,对平移和旋转不敏感
103             xData.Add(new TypedValue((int)DxfCode.ExtendedDataScale, 1.0));
104             xData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "Vector_2"));
105             xData.Add(new TypedValue((int)DxfCode.ExtendedDataWorldXDir, new Point3d(0, 200, 0)));
106             xData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "RealNumber"));
107             //插入了一个实数,不跟随Entity的Transform变化
108             xData.Add(new TypedValue((int)DxfCode.ExtendedDataReal, 1.0));
109             return xData;
110         }
111         private static ResultBuffer CreatNewXData2()
112         {
113             var xData = new ResultBuffer();
114             xData.Add(new TypedValue((int)DxfCode.ExtendedDataRegAppName, AppName+"2"));
115             xData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "APP2_Point_1"));
116             xData.Add(new TypedValue((int)DxfCode.ExtendedDataWorldXCoordinate, new Point3d(100, 200, 300)));
117             xData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "APP2_Point_2"));
118             return xData;
119         }
120         private static void PrintXData(ResultBuffer xData, Editor ed)
121         {
122             if (ed==null) return;
123             if (xData == null) { ed.WriteMessage("没有XData"+"\n"); return; }
124             ed.WriteMessage("XData内容:"+"\n");
125             foreach (TypedValue tv in xData)
126             {
127                 string s = "";
128                 s+=$"{$"[{tv.TypeCode.ToString()}]",-8}";
129                 s+=$"{$"[{tv.Value.GetType().ToString()}]",-40}";
130                 s+=$"{$"[{tv.Value.ToString()}]",-60}";
131                 s+="\n";
132                 ed.WriteMessage(s);
133             }
134             //打印内容如下:
135             //[1001]  [System.String]                         [XDataDemoAppName]
136             //[1000]  [System.String]                         [Point_1]
137             //[1011]  [Autodesk.AutoCAD.Geometry.Point3d]     [(100,200,300)]
138             //[1000]  [System.String]                         [Point_2]
139             //[1011]  [Autodesk.AutoCAD.Geometry.Point3d]     [(400,500,600)]
140             //[1000]  [System.String]                         [Vector_1]
141             //[1013]  [Autodesk.AutoCAD.Geometry.Point3d]     [(100,0,0)]
142             //[1000]  [System.String]                         [scale]
143             //[1042]  [System.Double]                         [1]
144             //[1000]  [System.String]                         [Vector_2]
145             //[1013]  [Autodesk.AutoCAD.Geometry.Point3d]     [(0,200,0)]
146             //[1000]  [System.String]                         [RealNumber]
147             //[1040]  [System.Double]                         [1]
148             //[1001]  [System.String]                         [XDataDemoAppName2]
149             //[1000]  [System.String]                         [APP2_Point_1]
150             //[1011]  [Autodesk.AutoCAD.Geometry.Point3d]     [(100,200,300)]
151             //[1000]  [System.String]                         [APP2_Point_2]
152         }
153     }
View Code
复制代码

 XRecord:

  如果说XData是标准Dxf组码的扩展,XRecord就是使用标准Dxf组码的专门用来存储数据的类型。

  XRecord存储数据使用的也是ResultBuffer数据类型,也要遵循Dxf组码类型表的规定;有别于XData的是,XData使用的“扩展段”的组码表(DxfCode>=1000);XRecord使用的是“标准段”的组码表(DxfCode<1000),并且,通过其中的四个指向(HardOwner,SoftOwner,HardPointer,SoftPointer),一个XRecord对象可以再存储其它DBObject;因此,XRecord存储的内容比XData更丰富。XRecord的存储上限为2GB。

  XRecord类是DBObject类的子类,通过DBDictionary的方式和Database或者DBObject实例绑定,加入Database后要进行Database.AddNewlyCreatedDBObject(DBObject obj,bool add)确认操作。

  以下是一个简单的例子,仍有很多重要功能未经测试。有空的时候再补上。。

 View Code

 DataTable:

  DataTable是Autodesk开发的另一个专门用来存储数据的类型;它实际是个表格,表头定义了每一列的名称和数据类型,数据被一行一行地添加进去。

  DataTable支持多种数据类型,具体包括:Boolean, integer, double, char*, Point3d, ObjectId, AcDbHardOwnershipId, SoftOwnershipId, AcDbHardPointerId,  AcDbSoftPointerId。

  DataTable类是DBObject类的子类,通过DBDictionary的方式和Database或者DBObject实例绑定,加入Database后要进行Database.AddNewlyCreatedDBObject(DBObject obj,bool add)确认操作。

  以下是一个简单的例子,仍有许多重要功能未经测试。有空的时候再补上。。。

 

复制代码
  1     public static class DataTableDemo
  2     {
  3         public static void WriteDataTableDemo()
  4         {
  5             var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.CurrentDocument;
  6             if (doc == null) return;
  7             var db = doc.Database;
  8             var ed = doc.Editor;
  9             var pResult = ed.GetEntity("选择一个Entity"+"\n");
 10             if (pResult.Status!= Autodesk.AutoCAD.EditorInput.PromptStatus.OK) { ed.WriteMessage("选择Entity失败,退出"+"\n"); return; }
 11             var dataTable = CreatNewDataTable();
 12             using (var trans = db.TransactionManager.StartTransaction())
 13             {
 14                 var ent = trans.GetObject(pResult.ObjectId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite) as Entity;
 15                 {
 16                     //如果ent.ExtensionDictionary没有创建,则创建
 17                     if (ent.ExtensionDictionary == ObjectId.Null) ent.CreateExtensionDictionary();
 18                     var dicID = ent.ExtensionDictionary;
 19                     var dic = trans.GetObject(dicID, OpenMode.ForWrite) as DBDictionary;
 20                     dic.SetAt("DataTableDemo", dataTable);
 21                     trans.AddNewlyCreatedDBObject(dataTable, true);
 22                     ed.WriteMessage("写入DataTable成功"+"\n");
 23                 }
 24                 trans.Commit();
 25             }
 26         }
 27         private static DataTable CreatNewDataTable()
 28         {
 29             var dataTable = new DataTable();
 30             dataTable.AppendColumn(CellType.CharPtr, "Name");
 31             dataTable.AppendColumn(CellType.Integer, "Index");
 32             dataTable.AppendColumn(CellType.Bool, "HavePoint");
 33             dataTable.AppendColumn(CellType.Point, "PointPosition");
 34 
 35             var row = new DataCellCollection();
 36             var cell1 = new DataCell();
 37             cell1.SetString("NameABC");
 38             var cell2 = new DataCell();
 39             cell2.SetInteger(1);
 40             var cell3 = new DataCell();
 41             cell3.SetBool(true);
 42             var cell4 = new DataCell();
 43             cell4.SetPoint(new Point3d(12, 23, 34));
 44             row.Add(cell1);
 45             row.Add(cell2);
 46             row.Add(cell3);
 47             row.Add(cell4);
 48             //AppendRow()方法的第二个参数是是否对加入的这一行进行检查
 49             //具体指数量检查和类型检查
 50             dataTable.AppendRow(row, true);
 51 
 52             var row2 = new DataCellCollection();
 53             var row2cell1 = new DataCell();
 54             row2cell1.SetString("Row2NameABC");
 55             var row2cell2 = new DataCell();
 56             row2cell2.SetInteger(2);
 57             var row2cell3 = new DataCell();
 58             row2cell3.SetBool(false);
 59             var row2cell4 = new DataCell();
 60             row2cell4.SetPoint(new Point3d(0, 0, 0));
 61             row2.Add(row2cell1);
 62             row2.Add(row2cell2);
 63             row2.Add(row2cell3);
 64             row2.Add(row2cell4);
 65             dataTable.AppendRow(row2, true);
 66             return dataTable;
 67 
 68         }
 69         public static void ReadDataTableDemo()
 70         {
 71             var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.CurrentDocument;
 72             if (doc == null) return;
 73             var db = doc.Database;
 74             var ed = doc.Editor;
 75             var pResult = ed.GetEntity("选择一个Entity"+"\n");
 76             if (pResult.Status!= Autodesk.AutoCAD.EditorInput.PromptStatus.OK) { ed.WriteMessage("选择Entity失败,退出"+"\n"); return; }
 77             using (var trans = db.TransactionManager.StartTransaction())
 78             {
 79                 var ent = trans.GetObject(pResult.ObjectId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite) as Entity;
 80                 {
 81                     if (ent.ExtensionDictionary == ObjectId.Null) { ed.WriteMessage("没有ExtensionDictionary"+"\n"); return; };
 82                     var dicID = ent.ExtensionDictionary;
 83                     var dic = trans.GetObject(dicID, OpenMode.ForRead) as DBDictionary;
 84                     if (dic.Contains("DataTableDemo"))
 85                     {
 86                         var dataTableID = dic.GetAt("DataTableDemo");
 87                         var dataTable = trans.GetObject(dataTableID, OpenMode.ForRead) as DataTable;
 88                         PrintDataTable(dataTable, ed);
 89                     }
 90                     else
 91                     {
 92                         ed.WriteMessage("没有DataTableDemo"+"\n");
 93                     }
 94                 }
 95                 trans.Commit();
 96             }
 97         }
 98         private static void PrintDataTable(DataTable dataTable, Editor ed)
 99         {
100             if (ed == null) return;
101             if (dataTable == null) { ed.WriteMessage("没有DataTable"+"\n"); return; }
102             ed.WriteMessage("DataTable内容:"+"\n");
103             ed.WriteMessage("列数:"+dataTable.NumColumns.ToString()+"\n");
104             ed.WriteMessage("行数:"+dataTable.NumRows.ToString()+"\n");
105             //获取表格内容必须使用dataTable.GetCellAt(i, j)方法,使用GetRowAt()方法获取的行对象无法正确获取单元格内容
106             for (int i = 0; i < dataTable.NumRows; i++)
107             {
108                 for (int j = 0; j < dataTable.NumColumns; j++)
109                 {
110                     var cell = dataTable.GetCellAt(i, j);
111                     string s = "";
112                     s += $"[{cell.CellType.ToString()}] ";
113                     s+= $"[{cell.Value.GetType().ToString()}] ";
114                     s+= $"[{cell.Value.ToString()}]\n";
115                     ed.WriteMessage(s);
116                 }
117             }
118             //打印内容如下:
119             //DataTable内容:
120             //列数:4
121             //行数:2
122             //[CharPtr][System.String][NameABC]
123             //[Integer][System.Int32] [1]
124             //[Bool][System.Boolean][True]
125             //[Point][Autodesk.AutoCAD.Geometry.Point3d][(12, 23, 34)]
126             //[CharPtr][System.String][Row2NameABC]
127             //[Integer][System.Int32] [2]
128             //[Bool][System.Boolean][False]
129             //[Point][Autodesk.AutoCAD.Geometry.Point3d][(0, 0, 0)]
130         }
131     }
View Code
复制代码

 

posted @   羊羊咩咩咩  阅读(100)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示