Как убрать все символы форматирования из строки?

Автор Тема: Как убрать все символы форматирования из строки?  (Прочитано 11498 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 167
    • Мои плагины к Автокаду
Нужно получить текст размера, как его видит пользователь. То же самое, что у MText в свойстве Text, только для размеров.
Попробовал получать через dim.FormatMeasurement(dim.Measurement, dim.DimensionText). Все бы хорошо, но функция возвращает не только видимый текст, но и все символы форматирования, выравнивания, шрифтов и т.п. Парсить все на свете форматирования только чтоб их удалить - это как-то слишком сложно. Может есть какая-то функция удаления этого мусора?
Единственное, что приходит в голову - создавать MText, назначить ему Contents и считать получившийся Text. Но создавать неуправляемый объект из-за такой ерунды не очень хочется.

Оффлайн alz

  • ADN OPEN
  • **
  • Сообщений: 97
  • Карма: 11
создавать MText, назначить ему Contents и считать получившийся Text
Без дополнительной обработки даже это не поможет, символ <> придется менять на считанный размер, это вроде специальный управляющий символ размеров.
Как вариант Explode() и считать из списка получившийся MText
« Последнее редактирование: 05-08-2023, 06:00:38 от alz »

Отмечено как Решение avc 21-08-2023, 17:58:17

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1116
  • Карма: 173
Вижу два варианта.
1. Создать MTEXT, туда скопировать полученную строку, а потом забрать TextString.
2. Создать расширение для строки, которое снесет все форматирование.
Я пошел по второму пути :)
Извините, вам запрещён просмотр содержимого спойлеров.
А у размера нет ничего типа TextString? Просто с ними почти не работал пока еще.
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Нужно получить текст размера, как его видит пользователь
Пользователь видит текст размера с форматированием, что противоречит условию задачи.
Нужно оценить, есть ли форматирование, которое требуется сохранить, например верхние, нижние индексы, подчеркивание.
Если ничего не требуется наверное проще создать MText и считать Text.
А если требуется, либо MText.Text работает не корректно, сделать свою функцию.

Сейчас попробовал в AutoCAD 2015
Было "Test"
es сделал индексом
MText.Contents = \A1;T{\H0.7x;\Ses^;}t
в MgdDbg:
MText.Text = "Tes/t"
странно.

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

Оффлайн alz

  • ADN OPEN
  • **
  • Сообщений: 97
  • Карма: 11
Тут еще надо учитывать что сам размер цифрами у строке DimensionText не прописан а показан символом <> так что все равно придется лезть в дебри размера что бы считать как сам размер так и точность с которой он будет прописан, если же размер идет дефолтный то строка вообще пустая будет, так же есть суффиксы и префиксы, которые надо отдельно считывать так как в строке DimensionText  они не отображаются, в общем гемора столько что самый простой вариант получить строку, как ее видит пользователь это вот так:

Код - C# [Выбрать]
  1. using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  2. {
  3.     if (tr.GetObject(dimId, OpenMode.ForRead, false, true) is Dimension d)
  4.     {                  
  5.         using (DBObjectCollection oic = new DBObjectCollection())
  6.         {
  7.             d.Explode(oic);
  8.             foreach (Object o in oic)
  9.             {
  10.                 if (o is MText m)
  11.                 {
  12.                     //получаем текст строки размера
  13.                     string s = m.Text;      
  14.                     break;
  15.                 }                        
  16.             }
  17.         }
  18.     }
  19.     tr.Commit();            
  20. }

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
alz,
Не забыть еще o.Dispose() для освобождения памяти.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн alz

  • ADN OPEN
  • **
  • Сообщений: 97
  • Карма: 11
Не забыть еще o.Dispose() для освобождения памяти.

а при выходе из
     
Код - C# [Выбрать]
  1.    using (DBObjectCollection oic = new DBObjectCollection())
  2.         {
  3.             d.Explode(oic);        
  4.         }
Очистится только коллекция, объекты, в ней состоящие остаются в памяти?

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Единственное, что приходит в голову - создавать MText, назначить ему Contents и считать получившийся Text. Но создавать неуправляемый объект из-за такой ерунды не очень хочется.

Если чертеж большой или много чертежей и размеров к примеру 300.
Оптимальнее будет создать 1 Mtext и работать с ним, чем 300 раз разбивать размеры, а потом вызывать o.Dispose().

Оффлайн alz

  • ADN OPEN
  • **
  • Сообщений: 97
  • Карма: 11
Если чертеж большой или много чертежей и размеров к примеру 300.
Оптимальнее будет создать 1 Mtext и работать с ним, чем 300 раз разбивать размеры, а потом вызывать o.Dispose().

Чем вот такая функция плоха по сравнению с созданием одного мтекста и работой с ним? Будет принципиальная разница в быстродействии или количестве выделяемой памяти?

Код - C# [Выбрать]
  1. private string DimString(Dimension d, bool ps)
  2. {
  3.     using (MText m = new MText())
  4.     {
  5.         string contents = d.Prefix;
  6.         if (string.IsNullOrEmpty(d.DimensionText)) contents += d.Measurement.ToString("F" + d.Dimdec);
  7.         else contents += d.DimensionText;
  8.         contents = contents.Replace("<>", d.Measurement.ToString("F" + d.Dimdec)) + d.Suffix;
  9.         if (ps)
  10.         {
  11.             contents = contents.Replace("\r\n", " ");
  12.             contents = contents.Replace("\\P", " ");
  13.         }
  14.         m.Contents = contents;
  15.         return m.Text;
  16.     }                  
  17. }

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Будет принципиальная разница в быстродействии или количестве выделяемой памяти?
Функционально разницы не будет.
Принципиальная разница будет с определенного количества разбиваемых объектов.
Функция выше, это не то, о чем я писал, объект MText m нужно создать один раз, а не на каждый размер

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Очистится только коллекция, объекты, в ней состоящие остаются в памяти?
Проверь.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн alz

  • ADN OPEN
  • **
  • Сообщений: 97
  • Карма: 11
Функция выше, это не то, о чем я писал, объект MText m нужно создать один раз, а не на каждый размер
Ну я как бы это и спрашиваю, вот у нас например 300 объектов, насколько сильно будет различаться быстродействие этих двух вариантов?

Код - C# [Выбрать]
  1. [CommandMethod("test666")]
  2. public void Startcc222()
  3. {    
  4.     List<ObjectId> ids = new List<ObjectId>();
  5.     using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  6.     {
  7.         foreach (ObjectId id in ids)
  8.         {
  9.             if (tr.GetObject(id, OpenMode.ForRead, false, true) is Dimension d)
  10.             {
  11.                 string text = DimString(d, true);
  12.             }
  13.         }
  14.         tr.Commit();            
  15.     }  
  16. }
  17. private string DimString(Dimension d, bool ps)
  18. {
  19.     using (MText m = new MText())
  20.     {
  21.         string contents = d.Prefix;
  22.         if (string.IsNullOrEmpty(d.DimensionText)) contents += d.Measurement.ToString("F" + d.Dimdec);
  23.         else contents += d.DimensionText;
  24.         contents = contents.Replace("<>", d.Measurement.ToString("F" + d.Dimdec)) + d.Suffix;
  25.         if (ps)
  26.         {
  27.             contents = contents.Replace("\r\n", " ");
  28.             contents = contents.Replace("\\P", " ");
  29.         }
  30.         m.Contents = contents;
  31.         return m.Text;
  32.     }                  
  33. }

Код - C# [Выбрать]
  1. [CommandMethod("test666")]
  2. public void Startcc222()
  3. {
  4.     List<ObjectId> ids = new List<ObjectId>();
  5.     using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  6.     {
  7.         using (MText m = new MText())
  8.         {
  9.             foreach (ObjectId id in ids)
  10.             {
  11.                 if (tr.GetObject(id, OpenMode.ForRead, false, true) is Dimension d)
  12.                 {
  13.                     string text = DimString(d, true, m);
  14.                 }
  15.             }
  16.         }
  17.         tr.Commit();
  18.     }
  19. }
  20. private string DimString(Dimension d, bool ps, MText m)
  21. {
  22.     string contents = d.Prefix;
  23.     if (string.IsNullOrEmpty(d.DimensionText)) contents += d.Measurement.ToString("F" + d.Dimdec);
  24.     else contents += d.DimensionText;
  25.     contents = contents.Replace("<>", d.Measurement.ToString("F" + d.Dimdec)) + d.Suffix;
  26.     if (ps)
  27.     {
  28.         contents = contents.Replace("\r\n", " ");
  29.         contents = contents.Replace("\\P", " ");
  30.     }
  31.     m.Contents = contents;
  32.     return m.Text;
  33. }

Оффлайн alz

  • ADN OPEN
  • **
  • Сообщений: 97
  • Карма: 11
Проверь.
Проверил - o.Dispose() вообще не доступно поскольку у класса System.Object нет такого метода) Что бы освободить память надо было проходить по коллекции как по объектам DBObject, и да, если записать этот текст в Object то после выхода из транзакции можно будет с ним работать, а так как Object это вроде бы ссылочный тип то текст таки остается неочищенным. Надеюсь хоть после отработки программы в автокаде это все подчищается, а то чую придется проводить ревизию старых проектов, работают вроде бы без проблем, но вот подчисткой после .Explode() я никогда не занимался.

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
вот у нас например 300 объектов, насколько сильно будет различаться быстродействие этих двух вариантов?
1. врятли кто-то озадачивался именно такой задачей и замерял время.
2. Нужно тестировать самому
3. Будет зависеть от версии автокада, компьютера, чертежа(ей)

В данном контексте разница будет небольшая, т.к. сравниваем не скорости разбития 300 размеров с созданием одного MText, а создание одного MText против создания 300, на фоне tr.GetObject() будет скорее всего не более 1 %.
Если провести сравнение Explode() 300 размеров vs 1 new MText() в реальном чертеже, и более корректно построить тест. То разница по времени выполнения может быть заметна 3-10 раз, при этом само время незначительно 1 сек.
По памяти даже предположений нет, никогда не следил.

Главное не путать реальное приложение и тест, а то можно сделать неправильный вывод, переделать несколько приложений с тем же результатом.
Лучше применить при написании чего-то нового.

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 167
    • Мои плагины к Автокаду
2. Создать расширение для строки, которое снесет все форматирование.
Спасибо за код. Самому такую гору кода писать конечно лень, но раз уже написан - попробовал использовать. В основном работает, но пришлось добавить строчку:   
Код - C# [Выбрать]
  1. text = text.Replace("\\U+00B0", "°");

Это часто встречающийся символ градусов так кодируется. В идеале надо бы как-то любые такие коды конвертировать.

Вообще я надеялся, что в API есть метод для конвертации автокадовского Richtext в обычный текст. ...Ан нет  :-\