Пользовательские свойства чертежа; список аннотативных масштабов

Дата публикации: 08.11.2011


Код писался и тестировался под AutoCAD 2009 SP3 x86.

Задача 1

Нажатием одной кнопки должно происходить автоматическое заполнение пользовательских свойств чертежа (те свойства, которые находятся на вкладке "Custom" диалогового окна "Drawing Properties", открываемого командой _DWGPROPS). 



Имена и значения полей должны браться из внешнего текстового файла. Мои пользователи используют эти свойства для заполнения части информации в блоке основной надписи листов. Оставшаяся информация считывается из подшивки:


Задача 2 

Нажатием второй кнопки должно происходить удаление всех пользовательских свойств чертежа.

Задача 3

Нажатием третьей кнопки из чертежа должны удаляться все не используемые аннотативные масштабы

Задача 4

Нажатием четвёртой кнопки в чертёже должен формироваться необходимый набор аннотативных масштабов. 



Обозначенный набор должен браться из внешнего текстового файла.

Решение указанных задач

Я напишу команды, с помощью которых можно решать эти задачи. Вешать их на кнопки сможет любой пользователь. В коде используется класс Bushman.AutoCAD.DatabaseServices.WorkingDatabaseSwitcher, исходный код которого находится здесь. Сначала пишу xml-файл, в котором будут храниться настройки, используемые в задачах 1 и 4.

ComonUtilSettings.xml

   1:  <?xml version="1.0" encoding="utf-8" ?>
   2:  <Settings>
   3:    <!--Набор предопределённых пользовательских свойств чертежа-->
   4:    <DocumentCustomPropertyGroups>
   5:      <Group Name="GPSM">
   6:        <Property Key="Должность_1">Разработал</Property>
   7:        <Property Key="ФИО_1"></Property>
   8:        <Property Key="Дата_1"></Property>
   9:        
  10:        <Property Key="Должность_2">Проверил</Property>
  11:        <Property Key="ФИО_2"></Property>
  12:        <Property Key="Дата_2"></Property>
  13:        
  14:        <Property Key="Должность_3">ГИП</Property>
  15:        <Property Key="ФИО_3"></Property>
  16:        <Property Key="Дата_3"></Property>
  17:        
  18:        <Property Key="Должность_4">КГИП</Property>
  19:        <Property Key="ФИО_4"></Property>
  20:        <Property Key="Дата_4"></Property>
  21:        
  22:        <Property Key="Должность_5">Н.контроль</Property>
  23:        <Property Key="ФИО_5"></Property>
  24:        <Property Key="Дата_5"></Property>
  25:        
  26:        <Property Key="Должность_6">Утв.</Property>
  27:        <Property Key="ФИО_6"></Property>
  28:        <Property Key="Дата_6"></Property>
  29:      </Group>   
  30:      <Group Name="Возрождение">
  31:        <Property Key="Возр_Должность_1">Зам.Гл.Инж.</Property>
  32:        <Property Key="Возр_ФИО_1">Красноусов</Property>
  33:        <Property Key="Возр_Дата_1"></Property>
  34:                       
  35:        <Property Key="Возр_Должность_2">Проверил</Property>
  36:        <Property Key="Возр_ФИО_2">Осатчий</Property>
  37:        <Property Key="Возр_Дата_2"></Property>
  38:                       
  39:        <Property Key="Возр_Должность_3"></Property>
  40:        <Property Key="Возр_ФИО_3"></Property>
  41:        <Property Key="Возр_Дата_3"></Property>
  42:                       
  43:        <Property Key="Возр_Должность_4"></Property>
  44:        <Property Key="Возр_ФИО_4"></Property>
  45:        <Property Key="Возр_Дата_4"></Property>
  46:                       
  47:        <Property Key="Возр_Должность_5"></Property>
  48:        <Property Key="Возр_ФИО_5"></Property>
  49:        <Property Key="Возр_Дата_5"></Property>
  50:                       
  51:        <Property Key="Возр_Должность_6">Инв. №</Property>
  52:        <Property Key="Возр_ФИО_6"></Property>
  53:        <Property Key="Возр_Дата_6"></Property>
  54:      </Group>
  55:    </DocumentCustomPropertyGroups>
  56:    
  57:    <!--Список допустимых аннотативных масштабов чертежа (по ГОСТ 2.302-68)-->
  58:    <ScaleList>
  59:      <Scale Name="1:1" PaperUnits="1" DrawingUnits="1"/>
  60:      
  61:      <Scale Name="1:1" PaperUnits="1" DrawingUnits="1"/>
  62:      <Scale Name="1:2" PaperUnits="1" DrawingUnits="2"/>
  63:      <Scale Name="1:2,5" PaperUnits="1" DrawingUnits="2.5"/>
  64:      <Scale Name="1:4" PaperUnits="1" DrawingUnits="4"/>
  65:      <Scale Name="1:5" PaperUnits="1" DrawingUnits="5"/>
  66:      <Scale Name="1:10" PaperUnits="1" DrawingUnits="10"/>
  67:      <Scale Name="1:15" PaperUnits="1" DrawingUnits="15"/>
  68:      <Scale Name="1:20" PaperUnits="1" DrawingUnits="20"/>
  69:      <Scale Name="1:25" PaperUnits="1" DrawingUnits="25"/>
  70:      <Scale Name="1:40" PaperUnits="1" DrawingUnits="40"/>
  71:      <Scale Name="1:50" PaperUnits="1" DrawingUnits="50"/>
  72:      <Scale Name="1:75" PaperUnits="1" DrawingUnits="75"/>
  73:      <Scale Name="1:100" PaperUnits="1" DrawingUnits="100"/>
  74:      <Scale Name="1:200" PaperUnits="1" DrawingUnits="200"/>
  75:      <Scale Name="1:400" PaperUnits="1" DrawingUnits="400"/>
  76:      <Scale Name="1:500" PaperUnits="1" DrawingUnits="500"/>
  77:      <Scale Name="1:800" PaperUnits="1" DrawingUnits="800"/>
  78:      <Scale Name="1:1000" PaperUnits="1" DrawingUnits="1000"/>
  79:   
  80:      <Scale Name="1:2000" PaperUnits="1" DrawingUnits="2000"/>
  81:      <Scale Name="1:5000" PaperUnits="1" DrawingUnits="5000"/>
  82:      <Scale Name="1:10000" PaperUnits="1" DrawingUnits="10000"/>
  83:      <Scale Name="1:20000" PaperUnits="1" DrawingUnits="20000"/>
  84:      <Scale Name="1:25000" PaperUnits="1" DrawingUnits="25000"/>
  85:      <Scale Name="1:50000" PaperUnits="1" DrawingUnits="50000"/>
  86:   
  87:      <Scale Name="2:1" PaperUnits="2" DrawingUnits="1"/>
  88:      <Scale Name="2,5:1" PaperUnits="2.5" DrawingUnits="1"/>
  89:      <Scale Name="4:1" PaperUnits="4" DrawingUnits="1"/>
  90:      <Scale Name="5:1" PaperUnits="5" DrawingUnits="1"/>
  91:      <Scale Name="10:1" PaperUnits="10" DrawingUnits="1"/>
  92:      <Scale Name="20:1" PaperUnits="20" DrawingUnits="1"/>
  93:      <Scale Name="40:1" PaperUnits="40" DrawingUnits="1"/>
  94:      <Scale Name="50:1" PaperUnits="50" DrawingUnits="1"/>
  95:      <Scale Name="100:1" PaperUnits="100" DrawingUnits="1"/>
  96:    </ScaleList>
  97:  </Settings>

Далее привожу код решения.

Utilites.cs

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Xml.Linq;
using System.IO;
using acad = Autodesk.AutoCAD.ApplicationServices.Application;
using AcAp = Autodesk.AutoCAD.ApplicationServices;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using AcEd = Autodesk.AutoCAD.EditorInput;
using AcRx = Autodesk.AutoCAD.Runtime;
using AcInt = Autodesk.AutoCAD.Interop;
using AcIntCom = Autodesk.AutoCAD.Interop.Common;
using Bushman.AutoCAD.DatabaseServices;
[assembly: AcRx.CommandClass(typeof(Bushman.AutoCAD.Common.Utilites))]
namespace Bushman.AutoCAD.Common {
public sealed class Utilites {
/// <summary>
/// Удалить все пользовательские свойства чертежа. Это те свойства, которые находятся
/// на вкладке "Custom" диалогового окна "Drawing Properties", открываемого командой _DWGPROPS.
/// </summary>
[AcRx.CommandMethod("RemoveAllCustomPropertiesFromDocument", AcRx.CommandFlags.Session)]
public void RemoveAllCustomPropertiesFromDocument() {
AcAp.Document dwg = acad.DocumentManager.MdiActiveDocument;
AcDb.Database db = dwg.Database;
using (new WorkingDatabaseSwitcher(db)) {
AcDb.DatabaseSummaryInfoBuilder sib = new AcDb.DatabaseSummaryInfoBuilder(db.SummaryInfo);
sib.CustomPropertyTable.Clear();
using (dwg.LockDocument()) {
db.SummaryInfo = sib.ToDatabaseSummaryInfo();
}
}
}
/// <summary>
/// Добавить набор пользовательских свойств в чертёж. Это те свойства, которые находятся
/// на вкладке "Custom" диалогового окна "Drawing Properties", открываемого командой _DWGPROPS.
/// имеющиеся наборы считываются из файла ComonUtilSettings.xml.
/// </summary>
[AcRx.CommandMethod("AddCustomProperties2Document", AcRx.CommandFlags.Session)]
public void AddCustomProperties2Document() {
AcAp.Document dwg = acad.DocumentManager.MdiActiveDocument;
AcDb.Database db = dwg.Database;
AcEd.Editor ed = dwg.Editor;
using (new WorkingDatabaseSwitcher(db)) {
FileInfo xmlFile = new FileInfo(Path.Combine(Path.GetDirectoryName(this.GetType().Assembly.Location),
"ComonUtilSettings.xml"));
if (!xmlFile.Exists) {
ed.WriteMessage("Не найден файл настроек: \"{0}\"\n", xmlFile.FullName);
return;
}
XElement xml = XElement.Load(xmlFile.FullName);
if (xml == null) {
ed.WriteMessage("Не удалось прочитать настройки из файла: \"{0}\"\n", xmlFile.FullName);
return;
}
string[] groups = xml.Element("DocumentCustomPropertyGroups").Elements("Group")
.Select(n => n.Attribute("Name").Value.ToUpper().Trim()).ToArray();
if (groups.Length == 0) {
ed.WriteMessage("В файле настроек нет данных о группах пользовательских свойств чертежа: \n");
return;
}
foreach (string group in groups)
ed.WriteMessage("{0}\n", group);
AcEd.PromptStringOptions opt = new AcEd.PromptStringOptions("Имя группы пользовательских свойств");
opt.AllowSpaces = true;
AcEd.PromptResult result = ed.GetString(opt);
if (result.Status != AcEd.PromptStatus.OK) {
ed.WriteMessage("Выполнение команды прервано.\n");
return;
}
string groupName = result.StringResult.Trim().ToUpper();
if (!groups.Contains(groupName)) {
ed.WriteMessage("Группы с указанным Вами именем не существует.\n");
return;
}
XElement xgroup = xml.Element("DocumentCustomPropertyGroups").Elements("Group")
.First(n => n.Attribute("Name")
.Value.Trim().ToUpper() == groupName);
AcDb.DatabaseSummaryInfoBuilder sib = new AcDb.DatabaseSummaryInfoBuilder(db.SummaryInfo);
foreach (XElement item in xgroup.Elements("Property")) {
try {
sib.CustomPropertyTable.Add(item.Attribute("Key").Value, item.Value == string.Empty ?
" " : item.Value);
}
catch (Exception ex) {
ed.WriteMessage("{0}{1}", ex.Message, Environment.NewLine);
}
}
using (dwg.LockDocument()) {
db.SummaryInfo = sib.ToDatabaseSummaryInfo();
}
}
}
/// <summary>
/// Очистить список аннотативных масштабов чертежа от таких масштабов, которые в чертеже не используются.
/// За основу взят код:
/// http://through-the-interface.typepad.com/through_the_interface/2008/05/deleting-unused.html
/// </summary>
[AcRx.CommandMethod("ClearScaleList", AcRx.CommandFlags.Session)]
public void ClearScaleList() {
AcAp.Document dwg = acad.DocumentManager.MdiActiveDocument;
AcDb.Database db = dwg.Database;
AcEd.Editor ed = dwg.Editor;
using (new WorkingDatabaseSwitcher(db)) {
AcDb.ObjectContextManager ocm = db.ObjectContextManager;
if (ocm != null) {
// Теперь получаем коллекцию контекста аннотативных масштабов
//(именованная как ACDB_ANNOTATIONSCALES_COLLECTION)
AcDb.ObjectContextCollection occ = ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");
if (occ != null) {
//Создаём коллекцию для хранения идентификаторов
AcDb.ObjectIdCollection oic = new AcDb.ObjectIdCollection();
foreach (AcDb.ObjectContext oc in occ) {
if (oc is AcDb.AnnotationScale)
oic.Add(new AcDb.ObjectId(oc.UniqueIdentifier));
}
//Проверяем ссылки на объект, используя для этого
//метод Purge. Этот метод НЕ выполняет очистку, он
//убирает из коллекции идентификаторы таких объектов, которые НЕ
//подлежат очистке - т.е это такие объекты, которые не
//были бы удалены в следствии работы автокадовской команды PURGE.
//В результате коллекция будет содержать идентификаторы только
//таких объектов, которые можно удалить из базы данных чертежа.
db.Purge(oic);
// Теперь удаляем все объекты, идентификаторы которых остались в коллекции
using (AcDb.Transaction tr = db.TransactionManager.StartTransaction()) {
//Получаем общее количество элементов. Это число мы постепенно уменьшаем
//для каждой полученной ошибки открытия/уничтожения
int count = oic.Count;
using (dwg.LockDocument()) {
foreach (AcDb.ObjectId id in oic) {
try {
AcDb.DBObject obj = tr.GetObject(id, AcDb.OpenMode.ForWrite);
obj.Erase();
}
catch {
count--;
}
}
tr.Commit();
}
ed.WriteMessage("Удалено аннотативных масштабов: {0}", count);
}
}
}
}
}
/// <summary>
/// Сформировать в чертеже нужный список аннотативных масштабов. Этот список считывается из
/// файла ComonUtilSettings.xml
/// За основу взят код:
/// http://through-the-interface.typepad.com/through_the_interface/2008/05/deleting-unused.html
/// </summary>
[AcRx.CommandMethod("FillScaleList", AcRx.CommandFlags.Session)]
public void FillScaleList() {
AcAp.Document dwg = acad.DocumentManager.MdiActiveDocument;
AcDb.Database db = dwg.Database;
AcEd.Editor ed = dwg.Editor;
FileInfo xmlFile = new FileInfo(Path.Combine(Path.GetDirectoryName(this.GetType().Assembly.Location),
"ComonUtilSettings.xml"));
if (!xmlFile.Exists) {
ed.WriteMessage("Не найден файл настроек: \"{0}\"\n", xmlFile.FullName);
return;
}
XElement xml = XElement.Load(xmlFile.FullName);
if (xml == null) {
ed.WriteMessage("Не удалось прочитать настройки из файла: \"{0}\"\n", xmlFile.FullName);
return;
}
string[] xscales = xml.Element("ScaleList").Elements("Scale")
.Select(n => n.Attribute("Name").Value.ToUpper().Trim()).ToArray();
if (xscales.Length == 0) {
ed.WriteMessage("В файле настроек нет информации о списке аннотативных масштабов.\n");
return;
}
using (new WorkingDatabaseSwitcher(db)) {
AcDb.ObjectContextManager ocm = db.ObjectContextManager;
if (ocm != null) {
// Теперь получаем коллекцию контекста аннотативных масштабов
//(именованная как ACDB_ANNOTATIONSCALES_COLLECTION)
AcDb.ObjectContextCollection occ = ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");
if (occ != null) {
//Создаём коллекцию для хранения идентификаторов
AcDb.ObjectIdCollection oic = new AcDb.ObjectIdCollection();
List<AcDb.AnnotationScale> scales = new List<AcDb.AnnotationScale>();
foreach (AcDb.ObjectContext oc in occ) {
if (oc is AcDb.AnnotationScale) {
oic.Add(new AcDb.ObjectId(oc.UniqueIdentifier));
scales.Add((AcDb.AnnotationScale) oc);
}
}
//Проверяем ссылки на объект, используя для этого
//метод Purge. Этот метод НЕ выполняет очистку, он
//убирает из коллекции идентификаторы таких объектов, которые НЕ
//подлежат очистке - т.е это такие объекты, которые не
//были бы удалены в следствии работы автокадовской команды PURGE.
//В результате коллекция будет содержать идентификаторы только
//таких объектов, которые можно удалить из базы данных чертежа.
db.Purge(oic);
// Теперь удаляем все объекты, идентификаторы которых остались в коллекции
using (AcDb.Transaction tr = db.TransactionManager.StartTransaction()) {
//Получаем общее количество элементов. Это число мы постепенно уменьшаем
//для каждой полученной ошибки открытия/уничтожения
using (dwg.LockDocument()) {
int count_1 = 1;
int count_2 = 0;
foreach (XElement scale in xml.Element("ScaleList").Elements("Scale")) {
if (scales.Select(n => n.Name.Trim().ToUpper()).Contains(scale.Attribute("Name")
.Value.Trim().ToUpper())) {
AcDb.AnnotationScale x = scales.First(n => n.Name == scale.Attribute("Name")
.Value.Trim());
x.PaperUnits = Double.Parse(scale.Attribute("PaperUnits").Value);
x.DrawingUnits = Double.Parse(scale.Attribute("DrawingUnits").Value);
++count_1;
}
else {
AcDb.AnnotationScale x = new AcDb.AnnotationScale();
x.Name = scale.Attribute("Name").Value.Trim();
x.PaperUnits = Double.Parse(scale.Attribute("PaperUnits").Value);
x.DrawingUnits = Double.Parse(scale.Attribute("DrawingUnits").Value);
occ.AddContext(x);
++count_2;
}
}
tr.Commit();
ed.WriteMessage("Проверено одноимённых аннотативных масштабов: {0}\n", count_1);
ed.WriteMessage("Добавлено новых аннотативных масштабов: {0}\n", count_2);
}
}
}
}
}
}
}
}



Comments