Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: qst от 06-12-2018, 12:44:21

Название: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: qst от 06-12-2018, 12:44:21
Здравствуйте

При поиске текстового значения MText столкнулся с проблемой - не получается найти текст с большим кол-вом знаков.
Эмпирическим путем установил, что это кол-во равно 250 знакам.

Команда

Код - C# [Выбрать]
  1. (entget (car (entsel)))

Выдает:

Select object:
((-1 . <Entity name: 13b26a4ace0>)
(0 . "MTEXT")
(5 . "3CB5EE")
(102 . "{ACAD_XDICTIONARY")
(360 . <Entity name: 13b26a04c30>)
(102 . "}")
(330 . <Entity name: 13b1bcaa1f0>)
(100 . "AcDbEntity")
(67 . 0)
(410 . "Model")
(8 . "TEXT")
(370 . 0)
(100 . "AcDbMText")
(10 1135.16 -927.053 0.0)
(40 . 2.0)
(41 . 107.74)
(46 . 0.0)
(71 . 1)
(72 . 5)
(3 . "{\\L\\C0;NOTES FOR CABINET EXTERNAL ENGRAVED TAG PLATE:\\P\\P\\l\\C7;1. MATERIAL - TRAFFOLYTE 2mm THICK. WHITE/BLACK  ENGRAVE FROM WHITE SIDE OF LAMINATE TO GIVE BLACK LETTERING.\\P\\P2.ENGRAVING TO BE 14mm (ARIAL FONT) HIGH CHARACTERS FOR TEXT LINE 1 AND 8m")
(1 . "m (ARIAL FONT) HIGH CHARACTERS FOR TEXT LINE 2.\\P\\P3.TOLERANCE ± 0.4.\\P\\P4.\\C0;THE TAG PLATE\\C7;S MOUNTING TO BE THROUGH \\C0;DOUBLE SIDED STICKY TAPE.\\P\\P5.THE TAG PLATES WILL BE MOUNTED ON THE RIGHT HAND SIDE DOORS.}")
(7 . "ARIAL")
(210 0.0 0.0 1.0)
(11 1.0 0.0 0.0)
(42 . 106.996)
(43 . 42.3179)
(50 . 0.0)
(73 . 1)
(44 . 1.0))

Похоже, текстовое значение хранится в двух ячейках памяти.
Как можно найти такой текст по значению?
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: Александр Пекшев aka Modis от 06-12-2018, 12:46:06
При поиске текстового значения MText
А как ищете-то?
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: Александр Ривилис от 06-12-2018, 12:50:31
1. Код на Lisp, а раздел .NET. Почему?
2. Текст может хранится в группах 3 и 1 - зависит от размера текста.  Разбивается на строки по 250 байт:

https://knowledge.autodesk.com/ru/search-result/caas/CloudHelp/cloudhelp/2018/RUS/AutoCAD-DXF/files/GUID-5E5DB93B-F8D3-4433-ADF7-E92E250D2BAB-htm.html

(https://lh3.googleusercontent.com/-iVVtCg97YeU/XAjwzvMxXlI/AAAAAAAAPVk/OyqrxwPtiAsL_06OXejGz-BP_Rp8JLZmQCHMYCw/s0/clipboard4.png)

Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: qst от 06-12-2018, 13:04:41
Код программы:

Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5. using System.Collections.Generic;
  6. using System.Data.OleDb;
  7.  
  8. namespace CAPP3
  9. {
  10.     public class CommandClass
  11.     {
  12.         [CommandMethod("VJUH")]
  13.  
  14.         public void RunCommand()
  15.         {
  16.             Document adoc = Application.DocumentManager.MdiActiveDocument;
  17.  
  18.                 if (adoc == null)
  19.                 return;
  20.  
  21.             Editor ed = adoc.Editor;
  22.             Database db = adoc.Database;
  23.             Dictionary<string, string> tabTrans = new Dictionary<string, string>();
  24.            
  25.             string excl_connection_string = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=d:\Tst.xlsx;Extended Properties=""Excel 12.0 Xml;HDR=YES""";
  26.  
  27.             string sql = "SELECT * FROM [Sheet1$]";
  28.  
  29.             OleDbConnection con = new OleDbConnection(excl_connection_string);
  30.             OleDbCommand cmd = new OleDbCommand(sql, con);
  31.  
  32.             try
  33.             {
  34.                 con.Open();
  35.                 OleDbDataReader reader = cmd.ExecuteReader();
  36.                 while (reader.Read())
  37.  
  38.                 {                    
  39.                     tabTrans.Add(reader.GetString(0), reader.GetString(1));
  40.                 }
  41.                 reader.Close();
  42.             }
  43.             catch (System.Exception ex)
  44.             {
  45.                 ed.WriteMessage(ex.Message);                
  46.             }        
  47.             finally
  48.             {
  49.                 con.Dispose();
  50.             }
  51.  
  52.             using (Transaction tr = db.TransactionManager.StartTransaction())
  53.             {
  54.                 // Take BTR from BT
  55.                 BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  56.                 foreach (ObjectId btrId in bt)
  57.                 {
  58.                     // Take Id from BTR
  59.                     BlockTableRecord btr = tr.GetObject(btrId, OpenMode.ForRead) as BlockTableRecord;
  60.                     foreach (ObjectId Id in btr)
  61.                     {
  62.                         // Find all DBText
  63.                         if (Id.ObjectClass == RXObject.GetClass(typeof(DBText)))
  64.                         {
  65.                            
  66.                             DBText text = tr.GetObject(Id, OpenMode.ForRead) as DBText;
  67.  
  68.                             //Find match and replace
  69.                             string engText = null;
  70.                             if (tabTrans.TryGetValue(text.TextString, out engText))
  71.                             {
  72.                              
  73.                                 text = tr.GetObject(Id, OpenMode.ForWrite) as DBText;
  74.                                 text.TextString = engText;                              
  75.                             }
  76.                         }
  77.                         // Find all MText
  78.                         else if (Id.ObjectClass == RXObject.GetClass(typeof(MText)))
  79.                         {
  80.                            
  81.                             MText mtxt = tr.GetObject(Id, OpenMode.ForRead) as MText;
  82.  
  83.                             //Find match and replace
  84.                             string engText = null;
  85.                             if (tabTrans.TryGetValue(mtxt.Contents, out engText))
  86.                             {
  87.                                
  88.                                 mtxt = tr.GetObject(Id, OpenMode.ForWrite) as MText;
  89.                                 mtxt.Contents = engText;
  90.                             }
  91.                         }
  92.                         else if (Id.ObjectClass == RXObject.GetClass(typeof(BlockReference)))
  93.                         {
  94.                             BlockReference blkRef = tr.GetObject(Id, OpenMode.ForRead) as BlockReference;
  95.                             AttributeCollection attRefCol = blkRef.AttributeCollection;
  96.                             if (attRefCol != null)
  97.                             {
  98.                                 foreach (ObjectId attRefId in attRefCol)
  99.                                 {
  100.                                     AttributeReference attRef = tr.GetObject(attRefId, OpenMode.ForRead) as AttributeReference;
  101.                                     {
  102.                                         string engText = null;
  103.                                         if (tabTrans.TryGetValue(attRef.TextString, out engText))
  104.                                         {
  105.                                             attRef = tr.GetObject(attRefId, OpenMode.ForWrite) as AttributeReference;
  106.                                             attRef.TextString = engText;
  107.                                         }
  108.                                     }
  109.                                 }
  110.                             }
  111.                         }
  112.                     }
  113.                 }
  114.                 tr.Commit();
  115.             }
  116.             ed.Regen();
  117.         }
  118.     }
  119. }
  120.  

Как тогда можно найти эти фрагменты? Пробовал искать по 250 символов, то что хранится только в одной группе, не находит
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: Александр Ривилис от 06-12-2018, 13:08:48
Как тогда можно найти эти фрагменты? Пробовал искать по 250 символов, то что хранится только в одной группе, не находит
Не понял. А где поиск?
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: qst от 06-12-2018, 13:14:55
Значения для поиска и замены находятся внутри файла Excel.
Потом они записываются в dictionary.
По сути это код для поиска и замены текстовых значений.
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: Александр Ривилис от 06-12-2018, 13:26:23
Я не понимаю в чем проблема. Свойство MText.Contents возвращает уже сцеплённую строку. Если в файле Excel ты хранишь строку в таком же виде, то она должна находится. Не забывай, что в ней могут быть коды форматирования.
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: qst от 06-12-2018, 13:34:16
Я тоже не понимаю, тем более если они передаются в сцепленном виде.
Но, к примеру, такое значение:

{\L\C0;NOTES FOR CABINET EXTERNAL ENGRAVED TAG PLATE:\P\P\l\C7;1. MATERIAL - TRAFFOLYTE 2mm THICK. WHITE/BLACK  ENGRAVE FROM WHITE SIDE OF LAMINATE TO GIVE BLACK LETTERING.\P\P2.ENGRAVING TO BE 14mm (ARIAL FONT) HIGH CHARACTERS FOR TEXT LINE 1 AND 8mm (ARIAL FONT) HIGH CHARACTERS FOR TEXT LINE 2.\P\P3.TOLERANCE ± 0.4.\P\P4.\C0;THE TAG PLATE\C7;S MOUNTING TO BE THROUGH \C0;DOUBLE SIDED STICKY TAPE.\P\P5.THE TAG PLATES WILL BE MOUNTED ON THE RIGHT HAND SIDE DOORS.}

У меня не получается найти и заменить. И такая проблема только с MText, у которого больше 250 знаков.
Впринципе, можно сделать explode.entity для MText c длиной больше 250 символов, но хотелось бы понять в чем проблема.
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: Александр Ривилис от 06-12-2018, 13:38:41
Возьми распечатай что у тебя вытаскивается из ячейки Excel и что у тебя вытаскивается из MText.Contents и сравни побайтово.
Надеюсь, что ты в ячейку Excel засовывал тоже то что у тебя в MText.Contents?
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: qst от 06-12-2018, 13:48:43
Да, предварительно таким же методом записал все текстовые значения из чертежа в текстовый файл.
С другими значениями проблем нет, хотя их достаточно, порядка 500 штук.
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: Александр Ривилис от 06-12-2018, 13:54:25
Значит сравнивай. Где-то есть несоответствие.
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: qst от 06-12-2018, 16:41:50
Сравнивал через плагин npp++ Compare. Разницы не находит.

В любом случае, не находит только значения с кол-вом знаков больше 250, какое-то странное совпадение.
Кто-нибудь может протестировать?
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: Александр Ривилис от 06-12-2018, 17:22:25
В любом случае, не находит только значения с кол-вом знаков больше 250, какое-то странное совпадение.
Замени tabTrans.TryGetValue на какой-нибудь перебор/поиск. Если у тебя и там и там одинаковые значения, то значит это ошибка в Dictionary. Впрочем верится с трудом...
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: Александр Ривилис от 06-12-2018, 17:26:11
Сравнивал через плагин npp++ Compare.
Что с чем ты сравнивал? Еще чтение из файла Excel может что-то отсекать/портить...
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: qst от 07-12-2018, 13:45:07
Александр Ривилис,

Затрудняюсь сказать в чем было дело, но все заработало.
Код не перекомпилировал.
Работал только с одним большим текстовым значением в excel, а заработали все, хотя я их не трогал.

Спасибо за ответы и потраченное время
Название: Re: Поиск текстового значения Mtext в случае большого кол-ва символов
Отправлено: Привалов Дмитрий от 11-12-2018, 08:53:33
Я тоже не понимаю, тем более если они передаются в сцепленном виде.
Но, к примеру, такое значение:

{\L\C0;NOTES FOR CABINET EXTERNAL ENGRAVED TAG PLATE:\P\P\l\C7;1. MATERIAL - TRAFFOLYTE 2mm THICK. WHITE/BLACK  ENGRAVE FROM WHITE SIDE OF LAMINATE TO GIVE BLACK LETTERING.\P\P2.ENGRAVING TO BE 14mm (ARIAL FONT) HIGH CHARACTERS FOR TEXT LINE 1 AND 8mm (ARIAL FONT) HIGH CHARACTERS FOR TEXT LINE 2.\P\P3.TOLERANCE ± 0.4.\P\P4.\C0;THE TAG PLATE\C7;S MOUNTING TO BE THROUGH \C0;DOUBLE SIDED STICKY TAPE.\P\P5.THE TAG PLATES WILL BE MOUNTED ON THE RIGHT HAND SIDE DOORS.}

У меня не получается найти и заменить. И такая проблема только с MText, у которого больше 250 знаков.
Впринципе, можно сделать explode.entity для MText c длиной больше 250 символов, но хотелось бы понять в чем проблема.

Для поиска можешь использовать другое свойство MText.Text, а не MText.Contents
Из справки: Accesses the MText contents with formatting removed.

Для замены свойство не поможет, т.к. Read-only.