Тема: LISP. Очистка форматирования многострочного текста

;|=============================================================================
*    Функция сносит форматирование многострочного текста. Удаляются символы "{"
* и "}", поскольку именно символ "}" является окончанием применения определенного
* фонта. Удаляются наборы типа {fTimes New Roman|b0|i0|c204|p18; и т.п.
*    Параметры вызова:
*  string-to-normalize  - строка, которую надо нормализовать
*    Примеры вызова:
(_kpblc-clear-mtext (cdr (assoc 1 (entget(car(entsel))))))
  ; для выбранного многострочного текста очищает форматирование.
=============================================================================|;
(defun _kpblc-clear-mtext (string-to-normalize               /
               sub_string         sub_pos           left_string
               right_string
               )
  (if (or
    (setq sub_pos (vl-string-search "{f" string-to-normalize))
    (setq sub_pos (vl-string-search "{\\" string-to-normalize))
    (setq sub_pos (vl-string-search "\\f" string-to-normalize))
    (setq sub_pos (vl-string-search "{\\f" string-to-normalize))
    ) ;_ end of or
    (progn
      (setq left_string            ;все, что до "{"
         (vl-string-trim
           "{"
           (substr
         string-to-normalize
         1
         (vl-string-position
           (ascii "\\")
           string-to-normalize
           sub_pos
           ) ;_ end of vl-string-position
         ) ;_ end of substr
           ) ;_ end of vl-string-trim
        ) ;_ end of setq
      ;; Вот здесь была ошибка при некоторых условиях
      (if (vl-string-position
        (ascii ";")
        string-to-normalize
        sub_pos
        ) ;_ end of vl-string-position
    (setq right_string        ;все, что между {f и ;
           (substr
         string-to-normalize
         (+ (vl-string-position
              (ascii ";")
              string-to-normalize
              sub_pos
              ) ;_ end of vl-string-position
            2
            ) ;_ end of +
         ) ;_ end of substr
          ) ;_ end of setq
    (setq right_string "")
    ) ;_ end of if
      (_kpblc-clear-mtext (strcat left_string right_string))
      ) ;_ end of progn
    ;; Старый вариант попытки снесения "}"
    ;;(vl-string-trim "}" string-to-normalize)
    ;; Новый вариант снесения "}"
    (vl-list->string
      (vl-remove
    (ascii "}")
    (vl-string->list string-to-normalize)
    ) ;_ end of vl-remove
      ) ;_ end of vl-list->string
    ) ;_ end of if
  ) ;_ end of defun
;|=============================================================================
*    Функция удаления форматирования на выбранных элементах многострочного
* текста
=============================================================================|;
(defun c:unf-sel (/ selset item)
  (setq selset (ssget '((0 . "MTEXT"))))
  (while (and
       selset
       (> (sslength selset) 0)
       ) ;_ end of and
    (setq item (ssname selset 0))
    (ssdel item selset)
    (vlax-put-property
      (vlax-ename->vla-object item)
      "TextString"
      (_kpblc-clear-mtext
    (vlax-get-property (vlax-ename->vla-object item) "TextString")
    ) ;_ end of _kpblc-clear-mtext
      ) ;_ end of vlax-put-property
    ) ;_ end of while
  ) ;_ end of defun
;|=============================================================================
*    Функция удаления форматирования на всех элементах многострочного текста
=============================================================================|;
(defun c:unf-all (/ selset item)
  (setq selset (ssget "_X" '((0 . "MTEXT"))))
  (while (and
       selset
       (> (sslength selset) 0)
       ) ;_ end of and
    (setq item (ssname selset 0))
    (ssdel item selset)
    (vlax-put-property
      (vlax-ename->vla-object item)
      "TextString"
      (_kpblc-clear-mtext
    (vlax-get-property (vlax-ename->vla-object item) "TextString")
    ) ;_ end of _kpblc-clear-mtext
      ) ;_ end of vlax-put-property
    ) ;_ end of while
  ) ;_ end of defun
(princ (strcat
     "\nНаберите unf-sel для очистки форматирования выбранных текстов;"
     "\nunf-all - для полной очистки на всем файле"
     ) ;_ end of strcat
       ) ;_ end of princ

Re: LISP. Очистка форматирования многострочного текста

Как кстати, а я уже некоторое время подумывал не спросить есть ли у кого-нибудь готовое решение для борьбы с форматированием.
Есть такие вопросы и пожелания
1. Неплохо бы откат заиметь (коль уж это готовая программа).
2. В следующем примере у меня удалилось не все форматирование:
до применения функции:

{\fArial Narrow|b0|i0|c204|p34;\H2x;Воздухозаборная
решетка
900х600 (\fArial Narrow|b0|i0|c0|p34;h\fArial Narrow|b0|i0|c204|p34;)
на отм.2,600}

после:

[b]\H2x;[/b]Воздухозаборная
решетка
900х600 (h)
на отм.2,600

3. А в текстах с фигурными скобкаи количество накладок еще прирастает (в данном примере Acad даже ругаться начинает при попытке редактирования):
до:

{\fArial Narrow|b0|i0|c204|p34;Воздухозаборная
\fArial Narrow|b0|i0|c0|p34;\{\fArial Narrow|b0|i0|c204|p34;решетка\fArial Narrow|b0|i0|c0|p34;\}
\fArial Narrow|b0|i0|c204|p34;900х600 (\fArial Narrow|b0|i0|c0|p34;h\fArial Narrow|b0|i0|c204|p34;)
на отм.2,600}

после:

Воздухозаборная
\решетка\
900х600 (h)
на отм.2,600

Re: LISP. Очистка форматирования многострочного текста

Так а все правильно - все дело в том, что по идее для многострочного текста символы "{" и "}" являются служебными, обрамляющими форматирование, насколько я понял. Можно, конечно, снять это дело, и обращаться только к частям "\\f" и ";" (который идет после "\\f" и означает окончание описания фонта), но тогда гарантированно будут оставаться символы "}".
п.1: вот вариант с глобальным откатом для вызовов unf-all и unf-sel (я прошу прощения, упустил как-то из виду) - код просто заменить:

;|=============================================================================
*    Функция удаления форматирования на выбранных элементах многострочного
* текста
=============================================================================|;
(defun c:unf-sel (/ selset item *kpblc-activedoc*)
  (setq    selset          (ssget '((0 . "MTEXT")))
    *kpblc-activedoc* (vla-get-activedocument (vlax-get-acad-object))
    ) ;_ end of setq
  (vla-startundomark *kpblc-activedoc*)
  (while (and
       selset
       (> (sslength selset) 0)
       ) ;_ end of and
    (setq item (ssname selset 0))
    (ssdel item selset)
    (vlax-put-property
      (vlax-ename->vla-object item)
      "TextString"
      (_kpblc-clear-mtext
    (vlax-get-property (vlax-ename->vla-object item) "TextString")
    ) ;_ end of _kpblc-clear-mtext
      ) ;_ end of vlax-put-property
    ) ;_ end of while
  (vla-endundomark *kpblc-activedoc*)
  ) ;_ end of defun
;|=============================================================================
*    Функция удаления форматирования на всех элементах многострочного текста
=============================================================================|;
(defun c:unf-all (/ selset item *kpblc-activedoc*)
  (setq    selset          (ssget "_X" '((0 . "MTEXT")))
    *kpblc-activedoc* (vla-get-activedocument (vlax-get-acad-object))
    ) ;_ end of setq
  (vla-startundomark *kpblc-activedoc*)
  (while (and
       selset
       (> (sslength selset) 0)
       ) ;_ end of and
    (setq item (ssname selset 0))
    (ssdel item selset)
    (vlax-put-property
      (vlax-ename->vla-object item)
      "TextString"
      (_kpblc-clear-mtext
    (vlax-get-property (vlax-ename->vla-object item) "TextString")
    ) ;_ end of _kpblc-clear-mtext
      ) ;_ end of vlax-put-property
    ) ;_ end of while
  (vla-endundomark *kpblc-activedoc*)
  ) ;_ end of defun

п.2 Форматирование вида \h2x не является форматированием шрифта, оно задает только высоту следующего текста. Поэтому и не сносится.
п.3. А что там должно быть изначально-то?
Смотри логику поведения - полужирным выделено сносимое. для удобства еще и на разные строки разбил ;)

[b]{\fArial Narrow|b0|i0|c204|p34;[/b]
Воздухозаборная
[b]\fArial Narrow|b0|i0|c0|p34;[/b]
\
[b]{\fArial Narrow|b0|i0|c204|p34;[/b]
решетка
[b]\fArial Narrow|b0|i0|c0|p34;[/b]
\
[b]}[/b]
[b]\fArial Narrow|b0|i0|c204|p34;[/b]
900х600 (
[b]\fArial Narrow|b0|i0|c0|p34;[/b]
h
[b]\fArial Narrow|b0|i0|c204|p34;[/b]
) на отм.2,600
[b]}[/b]

Так что в принципе все правильно - надо либо сносить лишние "\", либо как-то еще выкручиваться - например, в функции _kpblc-clear-mtext на моменте назначения sub_pos поиграться с выбираемыми моментами. Только тут надо учесть, что просто "\\" сносить низзя - таким манером еще и подчеркивание, бывает, назначается.

Re: LISP. Очистка форматирования многострочного текста

Хотя стоп, насчет \H2x я, похоже, погорячился... Как в таком варианте поступать - даже не представляю.

Re: LISP. Очистка форматирования многострочного текста

> kpblc
Не знаю на счет \H2x, но ребята чертежники доходили до того, что применяли даже Explode (когда нет времени редактировать каждый мультитекст), чтобы исправлять стили шрифта. Попробовал твою прогу - экономит кучу времени. Многократно не тестировал, пока нам подходит, спасибо.

Re: LISP. Очистка форматирования многострочного текста

Да не мне в общем-то спасибо, а ViC ( https://www.caduser.ru/forum/topic20827.html ) - с его подачи все сделано. Он и первый тестировщик.

> che
Прога по созданию текстового и размерного стилей (если вообще требуется) болтается на http://dwg.ru/forum/viewtopic.php?t=4680 - сделано под строителей, под машиностроение надо перерабатывать.

Re: LISP. Очистка форматирования многострочного текста

> kpblc
по п.1 Есть мнение, что если после
(vla-startundomark *kpblc-activedoc*)
произойдет ошибка (например если попадется
текст на заблокированном слое)
то (vla-endundomark *kpblc-activedoc*) не сработает
и при оставшейся открытой метке теоретически возможна
ситуация, когда при вызове undo откатит так, что
мало не покажется. Поэтому либо ставить обработчик,
либо перехват, либо вообще не ставить меток.
(мне так кажется)
по п.3
Если на экране текст выглядит так

Воздухозаборная
{решетка}
900х600 (h) на отм.2,600

то в идеале хотелось бы чтоб после "очистки" он выглядел
так (не на экране, а "внутри")

Воздухозаборная
\{решетка\}
900х600 (h) на отм.2,600

т.е. чтоб из связки \{ не проподала фигурная скобка
Впрочем фигурные скобки в текстах относительно редки,
я их вставил исключительно для теста, и с этим можно мириться.
зы касательно \{ выяснился нежелательный момент -
при EXPLODE текст все равно взрывается в "труху" именно в начале
и в конце скобки. Т.е. столь желательный эффект корректного EXPLODE
в отсутствии форматирования пропадает :(

Re: LISP. Очистка форматирования многострочного текста

> AY
Ну ты уж реши - либо нужны метки, либо нет ;) Хотя на самом деле перед первой меткой можно поставить (vla-endundomark) - оно закроет все открытые метки. Правда, тогда *kpblc-activedoc* придется делать глобальным, что в данном варианте в принципе не помеха.
"Обрамления" unf-all и unf-sel на самом деле лично у меня нет - я все равно это делаю сразу на весь файл, вызывается внутри другой функции, которая еще из одной вызывается, и вот только в последней у меня уже все - и отлов ошибок, и закрывание меток отмены, и восстановление системы.
Насчет заблокированного слоя тоже не проблема обойти (причем не внутри цикла, чтобы не загружать машину впустую).
Насчет связки "\\{" И "\\}" - в принципе, сделать можно. Если сильно надо, сделаю, только уже явно не сегодня - не поспеваю. И сюда же: мне не удалось (ADT 2005 Eng + SP1, mtexted - любое значение, специально проверил) повторить "в труху". Если втупую колотить текст

Воздухозаборная
{решетка}
900х600 (h) на отм.2,600

то символы { и } на экране не отображаются (для внешнего редактора), да и в кодах нет такой пары "\{" ("\}"). Стоит поставить \{ (\}) в тексте внешнего редактора, как скобки начинают отображаться, но в кодах появляются связки "\\{" и "\\}". В общем, тут совсем темный лес. Как таковой пары \{ нет.

Re: LISP. Очистка форматирования многострочного текста

Или вариант "в труху" понимать как ни с того ни с сего отображение \\P? Так это из-за снесения "}".

Re: LISP. Очистка форматирования многострочного текста

> kpblc
Про EXPLODE я вот, что имел в виду - такой текст:
(кстати см. жирно связка \{ )

{\fArial Narrow|b0|i0|c204|p34;Воздухозаборная
\fArial Narrow|b0|i0|c0|p34;[b]\{[/b]\fArial Narrow|b0|i0|c204|p34;решетка\fArial Narrow|b0|i0|c0|p34;[b]\}[/b]
\fArial Narrow|b0|i0|c204|p34;900х600 (\fArial Narrow|b0|i0|c0|p34;h\fArial Narrow|b0|i0|c204|p34;)
на отм.2,600}

отображается нормально и при стиле на основе ttf и при shx,
но при взрыве (Acad 2000) - скобки и все что между
ними превращаются в отдельные text'ы
(т.е. по примитиву на каждую единицу формарирования).
Такой текст -

Воздухозаборная
\{решетка\}
900х600 (h) на отм.2,600

отображается нормально, в общем случае только при стиле на основе shx
(что вполне объяснимо), но при EXPLODE скобки все равно отваливаются
в отдельные примитивы (правда, в отличии от первого варианта,
здесь отваливаются только фигурные)
И соответственно вариант без фигурных скобок

Воздухозаборная
решетка
900х600 (h) на отм.2,600

взрывается совсем красиво - на три text'a.

Re: LISP. Очистка форматирования многострочного текста

ок. А если для этого текста посмотреть такой код:

(vlax-get-property (vlax-ename->vla-object (car(entsel))) "textstring")

Чего вернется? Я имею в виду именно внутреннее представление текста.
Насчет 2000-го: к сожалению, протестировать именно на нем не могу - нет его у меня.
И вопрос: насчет меток и переделки для этой несчастной связки "\\{" "\\}" - добиваем или ну его нафиг?

Re: LISP. Очистка форматирования многострочного текста

kpblc пишет:

Чего вернется?

Так я и показывал именно "внутреннее наполнение" mtext'a,
кроме тех мест о которых отдельно оговорил, только брал
его из окна внешнего текстового редактора, т.к.
лисп отображает все с двойными бекслешами, что в его понимании
является одним символом бекслеша (если строку с двойными бекслешами
вставить в mtext получится "каша").
Если надо корректно увидеть содержание то должен помочь (prompt ...)

(prompt (vla-get-textstring (vlax-ename->vla-object (car(entsel)))))

Доделать, наверное, стоит откат, а остальное оставить до лучших времен :)

Re: LISP. Очистка форматирования многострочного текста

ок. Мне тут еще Apelsinov кое-что подсказал, попробую сделать.

Re: LISP. Очистка форматирования многострочного текста

Ну вот, кое-что получилось вроде как.
Тут дополнительный запрос по поводу "чего обрабатывать" - либо весь файл, либо выбор. Может, более удобно?
Обрабатываются примитивы на блокированных и замороженных слоях. Активный слой невозможно заморозить, так что пришлось немного поизвращаться. Уже когда сделал, понял, что можно было попробовать по-другому, но было уже лень.
На всякий случай добавил свой стандартный обработчик ошибок (вообще без правки).

;|=============================================================================
*    Функция сносит форматирование многострочного текста. Удаляются символы "{"
* и "}", поскольку именно символ "}" является окончанием применения определенного
* фонта. Удаляются наборы типа {fTimes New Roman|b0|i0|c204|p18; и т.п.
*    Параметры вызова:
*  string-to-normalize  - строка, которую надо нормализовать
*    Примеры вызова:
(_kpblc-clear-mtext (cdr (assoc 1 (entget(car(entsel))))))
  ; для выбранного многострочного текста очищает форматирование.
=============================================================================|;
(defun _kpblc-clear-mtext (string-to-normalize               /
               sub_string         sub_pos           left_string
               right_string
               )
  (if (or
    (setq sub_pos (vl-string-search "{f" string-to-normalize))
    (setq sub_pos (vl-string-search "{\\" string-to-normalize))
    (setq sub_pos (vl-string-search "\\f" string-to-normalize))
    (setq sub_pos (vl-string-search "{\\f" string-to-normalize))
    ) ;_ end of or
    (progn
      (setq left_string            ;все, что до "{"
         (vl-string-trim
           "{"
           (substr
         string-to-normalize
         1
         (vl-string-position
           (ascii "\\")
           string-to-normalize
           sub_pos
           ) ;_ end of vl-string-position
         ) ;_ end of substr
           ) ;_ end of vl-string-trim
        ) ;_ end of setq
      (if (vl-string-position
        (ascii ";")
        string-to-normalize
        sub_pos
        ) ;_ end of vl-string-position
    (setq right_string        ;все, что между {f и ;
           (substr
         string-to-normalize
         (+ (vl-string-position
              (ascii ";")
              string-to-normalize
              sub_pos
              ) ;_ end of vl-string-position
            2
            ) ;_ end of +
         ) ;_ end of substr
          ) ;_ end of setq
    (setq right_string "")
    ) ;_ end of if
      (_kpblc-clear-mtext (strcat left_string right_string))
      ) ;_ end of progn
    (vl-list->string
      (vl-remove
    (ascii "}")
    (vl-string->list string-to-normalize)
    ) ;_ end of vl-remove
      ) ;_ end of vl-list->string
    ) ;_ end of if
  ) ;_ end of defun
;|=============================================================================
*    Функция удаления форматирования на выбранных элементах
=============================================================================|;
(defun c:unf-mtext (/ selset item _error_ _answer_ layer_set_list layer_status_list)
  ;; Локальные функции
  ;; Обработчик ошибок
  (defun kpblc-error (message)
    (if    (member    message
        '("console break"        "Function cancelled"
          "Функция отменена"        "quit / exit abort"
          "выйти прервать"
          ) ;_list
        ) ;_member
      (princ "\nКоманда прервана пользователем")
      (princ
    (strcat    "\ERRNO # "
        (itoa (getvar "ERRNO"))
        ": "
        message
        "\n"
        ) ;_strcat
    ) ;_princ
      ) ;_if
    ;; Завершение активных команд
    (while (/= (getvar "cmdactive") 0)
      (command nil)
      ) ;_while
    (vla-endundomark *kpblc-activedoc*)
    (setq *error* _error_)
    ) ;_ end of defun
  ;; Делает слой включенным, разблокированным и незамороженным (глобально)
  (defun _kpblc-make-layer-free    (layer-name / layer_item)
    (if    layer_status_list
      (alert (strcat "Остались настройки слоя " layer-name))
      ) ;_ end of if
    (setq layer_status_list nil
      layer_item        (vlax-ename->vla-object
                  (tblobjname "layer" layer-name)
                  ) ;_ end of vlax-ename->vla-object
      layer_status_list (list
                  (cons
                "LayerOn"
                (vlax-get-property layer_item "LayerOn")
                ) ;_ end of cons
                  (cons
                "Lock"
                (vlax-get-property layer_item "Lock")
                ) ;_ end of cons
                  (cons
                "Freeze"
                (vlax-get-property layer_item "Freeze")
                ) ;_ end of cons
                  ) ;_ end of list
      ) ;_ end of setq
    (vlax-put-property layer_item "LayerOn" :vlax-true)
    (vlax-put-property layer_item "Lock" :vlax-false)
    (if    (/=
      (vlax-get-property
        (vlax-get-property *kpblc-activedoc* "ActiveLayer")
        "Name"
        ) ;_ end of vlax-get-property
      layer-name
      ) ;_ end of /=
      (vlax-put-property layer_item "freeze" :vlax-false)
      ) ;_ end of if
    ) ;_ end of defun
  ;; Возвращает установки слоя
  (defun _kpblc-restore-layer (layer-name / layer_item)
    (if    layer_status_list
      (progn
    (setq layer_item (vlax-ename->vla-object (tblobjname "layer" layer-name)))
    (foreach loc_item '("LayerOn" "Lock" "Freeze")
      (if (and
        (/=
          (vlax-get-property
            (vlax-get-property *dsk-activedoc* "ActiveLayer")
            "Name"
            ) ;_ end of vlax-get-property
          layer-name
          ) ;_ end of /=
        (/= loc_item "Freeze")
        ) ;_ end of and
        (vlax-put-property
          layer_item
          loc_item
          (cdr
        (assoc loc_item layer_status_list)
        ) ;_ end of cdr
          ) ;_ end of vlax-put-property
        ) ;_ end of if
      ) ;_ end of foreach
    ) ;_ end of progn
      ) ;_ end of if
    (setq layer_status_list nil)
    ) ;_ end of defun
  ;; Конец локальных функций
  ;; Запросы опций
  (vl-load-com)
  (initget "вЕсь Выбор _ All Selection")
  (setq    _error_     *error*
    *error*     kpblc-error
    _answer_ (getkword
           "Обрабатывать объем [вЕсь файл/Выбор] ? <Весь файл> : "
           ) ;_ end of getkword
    ) ;_ end of setq
  (if (not *kpblc-activedoc*)
    (setq *kpblc-activedoc* (vla-get-activedocument (vlax-get-acad-object)))
    ) ;_ end of if
  (vla-startundomark *kpblc-activedoc*)
  (if (= _answer_ "Selection")
    (setq selset (ssget '((0 . "MTEXT"))))
    (setq selset (ssget "_X" '((0 . "MTEXT"))))
    ) ;_ end of if
  (while (and
       selset
       (> (sslength selset) 0)
       ) ;_ end of and
    (setq item (ssname selset 0))
    (ssdel item selset)
    (_kpblc-make-layer-free (cdr (assoc 8 (entget item))))
    (vlax-put-property
      (vlax-ename->vla-object item)
      "TextString"
      (_kpblc-clear-mtext
    (vlax-get-property (vlax-ename->vla-object item) "TextString")
    ) ;_ end of _kpblc-clear-mtext
      ) ;_ end of vlax-put-property
    (_kpblc-restore-layer (cdr (assoc 8 (entget item))))
    ) ;_ end of while
  (vla-endundomark *kpblc-activedoc*)
  (setq *error* _error_)        ;Возврат старого обработчика ошибок
  ) ;_ end of defun
(princ "\nНаберите unf-mtext для очистки форматирования многострочных текстов"
       ) ;_ end of princ

Если надо сделать 2 функции, как было вначале, скажите, там работы не так уж и много.

Re: LISP. Очистка форматирования многострочного текста

Да, вот еще. Советы Apelsinova для меня оказались слишком тяжелы в смысле понимания, поэтому я ими практически не воспользовался.

Re: LISP. Очистка форматирования многострочного текста

Протестируйте плиз и эту функцию. Писал очень давно и не помню, правильно работает или нет. Это вместо функции _kpblc-clear-mtext.

(defun z-mtext-purge-format-all    (string / pos pos_next)
  (setq pos 0)
  (while (setq pos (vl-string-search "\\" string pos))
    (setq pos_next pos)
    (while (= (substr string (+ 2 pos_next) 1) "\\")
      (setq pos_next (1+ pos_next))
      ) ;_ while
    (if    (= (lsh (- pos_next pos) 0) 0)
      (progn
    (setq pos pos_next)
    (cond ((member (substr string (+ 2 pos) 1) '("}" "{" "~"))
           (setq pos (1+ pos))
           )
          ((member (substr string (+ 2 pos) 1)
               '("P" "p" "L" "l" "O" "o" "S" "s")
               ) ;_ member
           (setq string (strcat (substr string 1 pos)
                    (substr string (+ 3 pos))
                    ) ;_ strcat
             ) ;_ setq
           )
          ((vl-string-search ";" string pos)
           (setq
         string
          (strcat
            (substr string 1 pos)
            (substr string
                (+ 2 (vl-string-search ";" string pos))
                ) ;_ substr
            ) ;_ strcat
         ) ;_ setq
           )
          (t
           (setq pos (1+ pos))
           )
          ) ;_ cond
    ) ;_ progn
      (setq pos (1+ pos_next))
      ) ;_ if
    ) ;_ while
  (setq pos 0)
  (while (setq pos (vl-string-search "}" string pos))
    (setq pos_next pos)
    (while (and
         (> pos_next 0)
         (= (substr string pos_next 1) "\\")
         ) ;_ and
      (setq pos_next (1- pos_next))
      ) ;_ while
    (if    (= (lsh (- pos_next pos) 0) 0)
      (setq string (strcat (substr string 1 pos)
               (substr string (+ 2 pos))
               ) ;_ strcat
        ) ;_ setq
      (setq pos (1+ pos))
      ) ;_ if
    ) ;_ while
  (setq pos 0)
  (while (setq pos (vl-string-search "{" string pos))
    (setq pos_next pos)
    (while (and
         (> pos_next 0)
         (= (substr string pos_next 1) "\\")
         ) ;_ and
      (setq pos_next (1- pos_next))
      ) ;_ while
    (if    (= (lsh (- pos_next pos) 0) 0)
      (setq string (strcat (substr string 1 pos)
               (substr string (+ 2 pos))
               ) ;_ strcat
        ) ;_ setq
      (setq pos (1+ pos))
      ) ;_ if
    ) ;_ while
  string
  )

тут ещё напрашивается очистка от юникодов(может иногда не корректно работать, в зависимости от кодовой страницы создания, что редко у меня встречалось):

;;;(string_Unicod->ASCII "\\U+00E2 \\U+00EF\\U+00E5\\U+00F0\\U+00E5\\U+00EA\\U+00F0\\U+00E8\\U+00F2\\U+00F2\\U+00B3")
(defun string_Unicod->ASCII  (string / n)
  (while (setq n (vl-string-search "\\U+00" string))
    (setq string
       (vl-string-subst
         (chr (+
            (* 16
               (if (< (ascii (strcase (substr string (+ n 6) 1))) 58)
             (- (ascii (strcase (substr string (+ n 6) 1))) 48)
             (- (ascii (strcase (substr string (+ n 6) 1))) 55)))
            (if    (< (ascii (strcase (substr string (+ n 7) 1))) 58)
              (- (ascii (strcase (substr string (+ n 7) 1))) 48)
              (- (ascii (strcase (substr string (+ n 7) 1))) 55))))
         (substr string (1+ n) 7)
         string)))
  string
  )

А вообще мало понятно, что следует оставлять от форматирования, иногда следует оставить подчёркивание или форматирование дробей. Тут каждому по потребностям!?

Re: LISP. Очистка форматирования многострочного текста

Также забыл добавить. Иногда используешь функцию очисти для дальнейшей обработки в программах поиска и замены, то там форматирование вообще не нужно. А когда корректируешь мтекст на месте то часть форматирования следует оставлять.

Re: LISP. Очистка форматирования многострочного текста

Вот, фактически то, что я сватал kpblc - чуть подправлено. Все понятно. Это правда.

(defun APEL-MTEXT-PURGE_FONT (/ *error* SS)
  (vla-startundomark (APEL-ACTIVE_DOCUMENT))
  (defun *error* (msg /)
    (princ (strcat "apel-mtext-purge_font Local-Error:" msg))
    (vla-endundomark (APEL-ACTIVE_DOCUMENT))
  )
  (if (setq SS (APEL-SSGET-VLA '((0 . "MTEXT")) "Выбери мультитекст:"))
    (vlax-for i    SS
      (if (APEL-OBJECT-MODIFED i)
    (vla-put-TextString
      i
      (APEL-MTEXT-STR_PURGE_FONT (vla-get-TextString i))
    )
      )
    )
  )
  (vla-endundomark (APEL-ACTIVE_DOCUMENT))
  (princ)
)
;;;Apelsinov
;;;18.05.05
(defun APEL-ACTIVE_DOCUMENT ()
  (if (null *apel_active_document*)
    (setq *apel_active_document*
       (vla-get-activedocument
         (APEL-ACAD_APPLICATION)
       )
    )
    *apel_active_document*
  )
)
;;;Apelsinov
;;;13.05.05
(defun APEL-ACAD_APPLICATION ()
  (if (null *apel_acad_application*)
    (setq *apel_acad_application* (vlax-get-acad-object))
    *apel_acad_application*
  )
)
;;;******************************
;;;Apelsinov
;;;apelsinov@pochta.ru
;;;05.05.05
;;;******************************
;;;SSget с запросом и предвыбором, если обьекты уже выделены заранее
;;;Аргументы:
;;;filtr -!!! Список, аналогичный фильтру для ssget !!!
;;;str - строка запроса
;;;Аозвращает - обьект AcadSelectionSet
(defun apel-ssget-vla (filtr str / *error* ss)
;;; (apel-ssget-vla '((0 . "lINE")) "Выбери примитивы:") -> Выбери примитивы:
;;; -> #<VLA-OBJECT IAcadSelectionSet 010c4224>
  (defun *error* (msg /)
    (setvar "nomutt" 0)
    (princ (strcat "apel-ssget-vla Local-Error:" msg))
  )
  (princ (strcat "\n" str))
  (setvar "nomutt" 1)
  (if
    (cond ((ssget "I" filtr) T)
      ((ssget filtr))
    )
     (setq SS
        (vla-get-ActiveSelectionSet
          (APEL-ACTIVE_DOCUMENT)
        )
     )
  )
  (setvar "nomutt" 0)
  SS
)
;;;  APEL-OBJECT-MODIFED
;;;  проверка обьекта на возможность модификации закрытость слоя
;;;  param - изменяемое свойство, строка
;;;  Возврат T или nil
;;;  Apelsinov
;;;  27.09.05
  (defun APEL-OBJECT-MODIFED (object param /)
    (and (vlax-property-available-p object param t)
     (if (vlax-property-available-p object "layer")
       (null (APEL-TRUE_FALSE-T_NIL
           (vla-get-Lock
             (vla-item (vla-get-Layers (APEL-ACTIVE_DOCUMENT))
                   (vla-get-Layer object)
             )
           )
         )
       )
       nil
     )
    )
  )
;;;Преобразование TRUE_FALSE в T или NIL
;;;Apelsinov
;;;24.06.05
;;;A - TRUE_FALSE
(defun APEL-TRUE_FALSE-T_NIL (A /)
  (cond ((eq A :vlax-true) t)
        ((eq A :vlax-false) NIL)
  )
)
;;;(APEL-TRUE_FALSE-T_NIL :vlax-true) -> T
;;;(APEL-TRUE_FALSE-T_NIL :vlax-false) -> nil

это только оболочка для обработки текста, саму программу преобразования строк я не трогал (у меня это APEL-MTEXT-STR_PURGE_FONT - аналог _kpblc-clear-mtext).
Почему все так, ИМХО:
1. не нужно ветвление для выбора всего или части, с этим прекрасно справляется ssget , если в ответ на запрос ввести all.
2. Необх. возможность предвыбора.
3. не нужно вкл, разм, и открывать слои, если кому-то потребуется- это лучше сделать вручную, вдруг потребуется обработать только те что открыты и включены, не надо усложнять. ошибки с выкл слоя решаются проверкой.
4.С обработчиком ошибок, что-то там намудрено лишнего.

Re: LISP. Очистка форматирования многострочного текста

Чуть-чуть не согласен. Если в файле хотя бы 10 листов (а ведь может быть и больше!), то на каждый заходить и ставить _select _all замучаешься. (ssget "_X") как раз и обработает весь файл.
Насчет предвыбора не спорю, у меня мозгов не хватило.
Насчет "неактивных" слоев (которые заморожены / заблокированы) не знаю, не знаю. У меня тут такое приносят, что уже и не знаешь, с какой стороны подступиться к файлу. А всех проблем - 2-3 десятка замороженных слоев, на каждом и стиль свой болтается (ttf-ный), и mtext тоже с прямым назначением фонта. Мне лень ползать по чужим слоям и пытаться потом вспомнить, что в каком виде было - засунул сюда. С восстановлением состояния.
В обработчике на самом деле всей лишности - это строки (while (/= (getvar "cmdactive") 0) (command nil)) - можно не закрывать активные команды, поскольку их нет.
Ладно. Похоже, тему надо либо переименовывать, либо переносить в ЛИСП, либо объединять с исходной (https://www.caduser.ru/forum/topic20827.html), либо и то, и другое, и третье. Идеала, видать, не достичь. По крайней мере мне. Я издох на пути.

Re: LISP. Очистка форматирования многострочного текста

> kpblc

;; Возвращает установки слоя
  (defun _kpblc-restore-layer (layer-name / layer_item)
    (if  layer_status_list
      (progn
  (setq layer_item (vlax-ename->vla-object (tblobjname "layer" layer-name)))
  (foreach loc_item '("LayerOn" "Lock" "Freeze")
    (if (and
    (/=
      (vlax-get-property
        (vlax-get-property *dsk-activedoc* "ActiveLayer")
        "Name"
        ) ;_ end of vlax-get-property
      layer-name
      ) ;_ end of /=
    (/= loc_item "Freeze") ; [b]НЕ СОВСЕМ ПОНЯТНО,ТО ЕСТЬ ЕСЛИ УМЕНЯ БЫЛ ЗАМОРОЖЕННЫЙ СЛОЙ ТО Я ЕГО НЕ ЗАМОРОЖУ ОПЯТЬ[/b]
    ) ;_ end of and
      (vlax-put-property
        layer_item
        loc_item
        (cdr
    (assoc loc_item layer_status_list)
    ) ;_ end of cdr
        ) ;_ end of vlax-put-property
      ) ;_ end of if
    ) ;_ end of foreach
  ) ;_ end of progn
      ) ;_ end of if
    (setq layer_status_list nil)
    ) ;_ end of defun

Re: LISP. Очистка форматирования многострочного текста

> Vic
Чуть-чуть не так. Нельзя заморозить активный слой (чуток повыше идет проверка на активность слоя, и, если имя слоя активно, не пытаться обработать свойство Freeze - кад иначе вываливает ошибку). Причем это не только программно, но и руками не провернуть - можно проверить, при попытке сделать замороженным активный слой вывалится соответствующее предупреждение и ничего меняться не будет (в программном варианте уйдет на обработчик ошибок).

Re: LISP. Очистка форматирования многострочного текста

А с таблицами как быть? Можно снести форматирование из содержимого ячеек?

Re: LISP. Очистка форматирования многострочного текста

> Serg01
Можно

;|=============================================================================
*    Функция сносит форматирование многострочного текста. Удаляются символы "{"
* и "}", поскольку именно символ "}" является окончанием применения определенного
* фонта. Удаляются наборы типа {fTimes New Roman|b0|i0|c204|p18; и т.п.
*    Параметры вызова:
*  string-to-normalize  — строка, которую надо нормализовать
*    Примеры вызова:
(_kpblc-clear-mtext (cdr (assoc 1 (entget(car(entsel))))))
  ; для выбранного многострочного текста очищает форматирование.
=============================================================================|;
(defun _kpblc-clear-mtext (string-to-normalize           /
         sub_string       sub_pos         left_string
         right_string
         )
  (if (or
  (setq sub_pos (vl-string-search "{f" string-to-normalize))
  (setq sub_pos (vl-string-search "{\\" string-to-normalize))
  (setq sub_pos (vl-string-search "\\f" string-to-normalize))
  (setq sub_pos (vl-string-search "{\\f" string-to-normalize))
  ) ;_ end of or
    (progn
      (setq left_string      ;все, что до "{"
       (vl-string-trim
         "{"
         (substr
     string-to-normalize
     1
     (vl-string-position
       (ascii "\\")
       string-to-normalize
       sub_pos
       ) ;_ end of vl-string-position
     ) ;_ end of substr
         ) ;_ end of vl-string-trim
      ) ;_ end of setq
      (if (vl-string-position
      (ascii ";")
      string-to-normalize
      sub_pos
      ) ;_ end of vl-string-position
  (setq right_string    ;все, что между {f и ;
         (substr
     string-to-normalize
     (+ (vl-string-position
          (ascii ";")
          string-to-normalize
          sub_pos
          ) ;_ end of vl-string-position
        2
        ) ;_ end of +
     ) ;_ end of substr
        ) ;_ end of setq
  (setq right_string "")
  ) ;_ end of if
      (_kpblc-clear-mtext (strcat left_string right_string))
      ) ;_ end of progn
    (vl-list->string
      (vl-remove
  (ascii "}")
  (vl-string->list string-to-normalize)
  ) ;_ end of vl-remove
      ) ;_ end of vl-list->string
    ) ;_ end of if
  ) ;_ end of defun
;|=============================================================================
*    Функция удаления форматирования на выбранных элементах
=============================================================================|;
(defun c:unf-mtext ( / selset item  _answer_ layer_set_list layer_status_list *error* col row
                       _kpblc-layer-status-restore
                       _kpblc-layer-status-save
                    )
  ;; Локальные функции
  ;; Обработчик ошибок
  (defun *error* (msg)
    (princ msg)
    ;; Завершение активных команд
    (while (/= (getvar "cmdactive") 0)(command))
    (_kpblc-layer-status-restore)
    (vla-endundomark *kpblc-activedoc*)) ;_ end of defun
  (defun _kpblc-layer-status-restore ()
    (foreach item layer_status_list
      (if (not (vlax-erased-p (car item)))
        (vl-catch-all-apply
          '(lambda ()
             (vla-put-lock (car item) (cdr (assoc "lock" (cdr item))))
             (vla-put-freeze (car item) (cdr (assoc "freeze" (cdr item))))
             ) ;_ end of lambda
          ) ;_ end of vl-catch-all-apply
        ) ;_ end of if
      ) ;_ end of foreach
    (setq layer_status_list nil)
    ) ;_ end of defun
  (defun _kpblc-layer-status-save ()
    (setq layer_status_list nil)
    (vlax-for item (vla-get-layers *kpblc-activedoc*)
      (setq layer_status_list (cons (list item
                                  (cons "freeze" (vla-get-freeze item))
                                  (cons "lock" (vla-get-lock item))
                                  ) ;_ end of cons
                            layer_status_list
                            ) ;_ end of cons
            ) ;_ end of setq
      (vla-put-lock item :vlax-false)
      (vl-catch-all-apply '(lambda () (vla-put-freeze item :vlax-false)))
      ) ;_ end of vlax-for
    ) ;_ end of defun
  ;; Конец локальных функций
  ;; Запросы опций
  (vl-load-com)
  (initget "вЕсь Выбор _ All Selection")
  (setq  _answer_ (getkword
         "Обрабатывать объем [вЕсь файл/Выбор] ? <Весь файл> : "
         ) ;_ end of getkword
    ) ;_ end of setq
  (or *kpblc-activedoc*
    (setq *kpblc-activedoc* (vla-get-activedocument (vlax-get-acad-object))))
  (vla-startundomark *kpblc-activedoc*)
  (if (= _answer_ "Selection")
    (setq selset (ssget '((0 . "MTEXT,ACAD_TABLE"))))
    (setq selset (ssget "_X" '((0 . "MTEXT,ACAD_TABLE"))))
    ) ;_ end of if
  (_kpblc-layer-status-save)
  (while (and selset (> (sslength selset) 0))
    (setq item (ssname selset 0))
    (ssdel item selset)
    (setq item (vlax-ename->vla-object item))
    (if (= (vla-get-ObjectName item) "AcDbTable")
      (progn
        (vla-put-RegenerateTableSuppressed item :vlax-true)
        (setq col 0)
        (repeat (vla-get-columns item)
          (setq row 0)
          (repeat (vla-get-rows item)
            (vla-settext item row col (_kpblc-clear-mtext (vla-gettext item row col)))
            (setq row (1+ row))
            )
          (setq col (1+ col))
          )
        (vla-put-RegenerateTableSuppressed item :vlax-false)
        (vla-update item)
        )
      (if (vlax-property-available-p item "TextString")
        (vlax-put-property item "TextString"
          (_kpblc-clear-mtext (vlax-get-property item "TextString")))
        )
      )
    ) ;_ end of while
  (_kpblc-layer-status-restore)
  (vla-endundomark *kpblc-activedoc*)
  ) ;_ end of defun
(princ "\nНаберите unf-mtext для очистки форматирования многострочных текстов")

Re: LISP. Очистка форматирования многострочного текста

> VVA
: метод RegenerateTableSuppressed есть в кадах от 2006 и выше, при работе в 2005 приходится либо не использовать этот метод, либо работать через RecomputeTableBlock.
Я пробовал, вроде работало корректно.

Re: LISP. Очистка форматирования многострочного текста

> Кулик Алексей aka kpblc
Спасибо, Алексей. В 2005 не пробывал.
Надеюсь что у Serg01 как минимум 2006 кад ;)