Тема: LISP. Вычисление суммы чисел (например, в экспликации)

Программа подсчета суммы чисел в чертеже.
Разработона для подсчета площадей помещений,
указанных в экспликации, но может использоваться
в любых случаях.

;*******SUMMA_N.LSP - Сумма числовых значений **********
;       Владимир Громов         Январь 2005 г.
;
(defun C:SUMMA_N ( / p1 p2 ss1 ssn1 n ss pp pp1 sum ssn e et text summa)
      (setvar "cmdecho" 0)
      (setq sum nil)
      (princ "\n Выбор объектов.")
      (setq p1 (getpoint " Первый угол рамки: "))
      (setq p2 (getcorner p2 "\n Второй угол рамки: "))
      (setq ss1 (ssget "_W" p1 p2))
  (if ss1
      (progn
      (setq ssn1 (sslength ss1) n 0)       ;Количество примитивов
      (setq ss (ssadd))                    ;Набор СОЗДАН (пустой пока)
         (repeat ssn1
           (setq pp (ssname ss1 n))        ;Имена примитивов
           (setq pp1 (entget pp))          ;Данные примитива с именем pp
           (cond
           ((= (cdr (assoc '0 pp1)) "TEXT") (ssadd pp ss) ;Набор ТЕКСТОВ
           ))
           (setq n (+ n 1))
         )
      (setq ssn (sslength ss) n 0)
         (repeat ssn
         (setq e (ssname ss n))
         (setq et (entget e))
         (setq text (cdr (assoc '1 et)))
         (setq text (vl-string-trim "%U" text))
         (princ "\n Число ")(princ n)(princ ": ")(princ text)
         (setq sum (cons (atof text) sum))
         (setq n (+ n 1))
         ); repeat
      (princ "\n Количество объектов: ") (princ ssn)
      (setq summa (apply '+ sum))
      (setq summa (strcat " Сумма чисел = " (rtos summa)))
      (princ summa) (alert summa)
      ); progn
      (progn
      (princ "\n Ничего не выбрано! ")
      (alert "\n Ничего не выбрано! ")
      ); progn
  ); if
  (princ)
)

Re: LISP. Вычисление суммы чисел (например, в экспликации)

> Владимир Громов
Я извеняюсь, но предлагаю вариант попроще:

;*** Сумма числовых значений ***
;*     Зуенко Виталий 2003г.   *
;* z-calc-text-value           *
(defun c:z-calc-text-value(/ nab i)
  (print "Выберите текстовые объекты среди которых будет произведененна калькуляция")
  (setq    nab (ssget '((-4 . "<OR")(0 . "TEXT")(0 . "MTEXT")(-4 . "OR>")))
    i   0)
  (while (/= (sslength nab) 0)
    (setq i (+ i
           (atof (vl-string-subst
               "."
               ","
               (cdr (assoc 1 (entget (ssname nab 0))))))))
    (ssdel (ssname nab 0) nab))
  (print (strcat "Сумма = " (rtos i)))
  (princ))

Re: LISP. Вычисление суммы чисел (например, в экспликации)

> ZZZ
Вот и хорошо.

Re: LISP. Вычисление суммы чисел (например, в экспликации)

А в моей программе вкралась ошибка в функции getcorner - не p2, а p1.
Код заново:

;*******SUMMA_N.LSP - Сумма числовых значений **********
;       Владимир Громов         Январь 2005 г.
;
(defun C:SUMMA_N ( / p1 p2 ss1 ssn1 n ss pp pp1 sum ssn e et text summa)
      (setvar "cmdecho" 0)
      (setq sum nil)
      (princ "\n Выбор объектов.")
      (setq p1 (getpoint " Первый угол рамки: "))
      (setq p2 (getcorner p1 "\n Второй угол рамки: "))
      (setq ss1 (ssget "_W" p1 p2))
  (if ss1
      (progn
      (setq ssn1 (sslength ss1) n 0)       ;Количество примитивов
      (setq ss (ssadd))                    ;Набор СОЗДАН (пустой пока)
         (repeat ssn1
           (setq pp (ssname ss1 n))        ;Имена примитивов
           (setq pp1 (entget pp))          ;Данные примитива с именем pp
           (cond
           ((= (cdr (assoc '0 pp1)) "TEXT") (ssadd pp ss) ;Набор ТЕКСТОВ
           ))
           (setq n (+ n 1))
         )
      (setq ssn (sslength ss) n 0)
         (repeat ssn
         (setq e (ssname ss n))
         (setq et (entget e))
         (setq text (cdr (assoc '1 et)))
         (setq text (vl-string-trim "%U" text))
         (princ "\n Число ")(princ n)(princ ": ")(princ text)
         (setq sum (cons (atof text) sum))
         (setq n (+ n 1))
         ); repeat
      (princ "\n Количество объектов: ") (princ ssn)
      (setq summa (apply '+ sum))
      (setq summa (strcat " Сумма чисел = " (rtos summa)))
      (princ summa) (alert summa)
      ); progn
      (progn
      (princ "\n Ничего не выбрано! ")
      (alert "\n Ничего не выбрано! ")
      ); progn
  ); if
  (princ)
)

Описался, когда корректировал программу для Конференции.

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Вот мой взгляд на программу уважаемого ZZZ.
Извиняюсь за плагиат, но мне кажется логичным убрать лишние переменные:

(defun c:z-calc-text-value ()
  (print
    "Выберите текстовые объекты среди которых
будет произведененна калькуляция"
  )
  (print
    (strcat
      "Сумма = "
      (rtos
    (apply
      (function +)
      (mapcar
        (function
          (lambda (a)
        (atof
          (vl-string-subst "." "," (cdr (assoc 1 (entget a)))))))
        (vl-remove-if
          (function listp)
          (mapcar (function cadr)
              (ssnamex (ssget '((0 . "TEXT,MTEXT")))))))))))
  (princ))

Re: LISP. Вычисление суммы чисел (например, в экспликации)

> Евгений Елпанов
Всё очень даже хорошо, спасибо за критику. Мне понравилось. Это даже лучше.
Маленькая отмазка - писал прогу 2-а года назад на заре становления. Пользуюсь всё время и не корректировал из-за отсутствия глюков, кроме одного глюка, когда пользователь не выбрал объекты.

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Использовал программу  Евгения Елпанова (2005-08-08 17:33:22)
Вопрос: можно ли сделать так, чтоб после выделения всех текстовых объектов после нажатия на правую кнопку программа спрашивала какой текст отредактировать, я указываю определенный текст и он испраляется на значение суммы? Как?

Re: LISP. Вычисление суммы чисел (например, в экспликации)

(defun c:z-calc-text-value (/ value ent obj)
  (vl-load-com)
  (princ
    "\nВыберите текстовые объекты среди которых будет произведененна калькуляция"
    ) ;_ princ
  (setq
    value (rtos
        (apply
          (function +)
          (mapcar
        (function
          (lambda (a)
            (atof
              (vl-string-subst
            "."
            ","
            (cdr (assoc 1 (entget a)))
            ) ;_ vl-string-subst
              ) ;_ atof
            ) ;_ lambda
          ) ;_ function
        (vl-remove-if
          (function listp)
          (mapcar (function cadr)
              (ssnamex (ssget '((0 . "TEXT,MTEXT"))))
              ) ;_ mapcar
          ) ;_ vl-remove-if
        ) ;_ mapcar
          ) ;_ apply
        ) ;_ rtos
    ) ;_ setq
  (princ (strcat "\n Сумма = " value))
  (setvar "ERRNO" 0)
  (while
    (and (not (setq ent
             (car
               (nentsel
             (strcat
               "\n Выберите текстовый объект для записи значения <Выход>:"
               ) ;_ strcat
             ) ;_ entsel
               ) ;_ car
            ) ;_ setq
          ) ;_ not
     (equal (getvar "ERRNO") 7)
     ) ;_ and
     (setvar "ERRNO" 0)
     ) ;_ while
  (if (and ent
       (vlax-property-available-p
         (setq obj (vlax-ename->vla-object ent))
         'TextString
         ) ;_ vlax-property-available-p
       ) ;_ and
    (progn
      (vlax-put-property obj 'TextString value)
      (vlax-release-object obj)
      ) ;_ progn
    ) ;_ if
  (princ)
  ) ;_ defun

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Для примера покажу, как нечто аналогичное сделано в ruCAD. Непосредственно этот код выполнить нельзя, в нем используются спецфункции. Общий смысл:
1. Если возникла идея о суммировании текстов, то завтра захочется их перемножать или еще что-то делать. Поэтому требуемое действие передается аргументом.
2. Постоянные действия локализированы в функциях, которые отработаны и надежны. Например, выбор чего-то "похожего на число", хоть откуда (ru-get-calc-number).
3. Результат вычисления можно записать в указанное место, в том числе с опцией выноски.

(defun ru-text-eval (func / n1 n2 pt result txt_result)
;;; Примеры вызова
;;; (ru-text-eval "*") (ru-text-eval "+") (ru-text-eval "-") (ru-text-eval "/")
  (while (setq n1 (ru-get-calc-number
                    "Укажи первое число (размер, текст или атрибут)"
                  ) ;_ end of ru-get-calc-number
         ) ;_ end of setq
    (if (/= n1 0)
      (progn
        (while
          (setq n2 (ru-get-calc-number "Укажи следующее число"))
           (setq result
                            (ru-error-catch
                              (function (lambda ()
                                          ((eval (read func)) n1 n2)
                                        ) ;_ end of lambda
                              ) ;_ end of function
                              (function (lambda (x)
                                          (princ (strcat "Ошибка вычисления "
                                                         (vl-princ-to-string n1)
                                                         func
                                                         (vl-princ-to-string n2)
                                                         "\n"
                                                 ) ;_ end of strcat
                                          ) ;_ end of princ
                                          n1
                                        ) ;_ end of lambda
                              ) ;_ end of function
                            ) ;_ end of ru-error-catch
                 txt_result (vl-princ-to-string result)
           ) ;_ end of setq
           (princ (strcat "\nРезультат: "
                          (vl-princ-to-string n1)
                          func
                          (vl-princ-to-string n2)
                          "="
                          txt_result
                  ) ;_ end of strcat
           ) ;_ end of princ
           (setq
             n1 result
           ) ;_ end of setq
        ) ;_ end of while
        (setq
          pt (ru-get-point-or-exit
               (strcat "\nТочка начала текста результата '"
                       txt_result
                       "'"
               ) ;_ end of strcat
               "Line"
             ) ;_ end of ru-get-point-or-exit
        ) ;_ end of setq
        (cond
          ((= pt "Line")
           (ru-draw-txt-up-line txt_result)
          )
          ((ru-is-point pt)
           (ru-text-add txt_result pt (ru-normal-text-height) 0 NIL)
          )
        ) ;_ end of cond
      ) ;_ end of progn
    ) ;_ end of if
  ) ;_ end of if
  (princ)
) ;_ end of defun

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Народ, огромное СПАСИБО. Вы мне сэкономили минут 30 работы в день

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Как сделать, чтоб после запятой не писалось нулей, т.е. не 18,0000 а 18 или не 18,6500 а 18,65

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Несколько модернизировал функцию, согласно пожеланиям и возможным накладкам.

(defun c:z-calc-text-value (/ value ent obj ss)
  (vl-load-com)
  (princ
    "\nВыберите текстовые объекты среди которых будет произведененна калькуляция"
    ) ;_ princ
  (setq ss (ssget '((0 . "TEXT,MTEXT"))))
  (if (not ss)
    (princ "Не выбраны объекты")
    (progn
      (setq
    value (rtos
        (apply
          (function +)
          (mapcar
            (function
              (lambda (a)
            (atof
              (vl-string-trim
                "%Uu {\\Ll}"
                (vl-string-subst
                  "."
                  ","
                  (cdr (assoc 1 (entget a)))
                  ) ;_ vl-string-subst
                ) ;_ vl-string-trim
              ) ;_ atof
            ) ;_ lambda
              ) ;_ function
            (vl-remove-if
              (function listp)
              (mapcar (function cadr)
                  (ssnamex ss)
                  ) ;_ mapcar
              ) ;_ vl-remove-if
            ) ;_ mapcar
          ) ;_ apply
        ) ;_ rtos
    ) ;_ setq
      (if (vl-string-position (ascii ".") value)
    (setq value (vl-string-right-trim ".0" value))
    ) ;_ if
      (princ (strcat "\n Сумма = " value))
      (alert (strcat "Сумма = " value))
      (setvar "ERRNO" 0)
      (while
    (and (not (setq    ent
             (car
               (nentsel
                 (strcat
                   "\n Выберите текстовый объект для записи значения <Выход>:"
                   ) ;_ strcat
                 ) ;_ entsel
               ) ;_ car
            ) ;_ setq
          ) ;_ not
         (equal (getvar "ERRNO") 7)
         ) ;_ and
     (setvar "ERRNO" 0)
     ) ;_ while
      (if (and ent
           (vlax-property-available-p
         (setq obj (vlax-ename->vla-object ent))
         'TextString
         ) ;_ vlax-property-available-p
           ) ;_ and
    (progn
      (vlax-put-property obj 'TextString value)
      (vlax-release-object obj)
      ) ;_ progn
    ) ;_ if
      ) ;_ progn
    ) ;_ if
  (princ)
  ) ;_ defun

Re: LISP. Вычисление суммы чисел (например, в экспликации)

to ZZZ ЧТО Я НЕ ТАК ДЕЛАЮ?
Скопировал в буфер последнюю прогу (2005-08-18 11:32:34), сохранил ее как файл z-calc-text-value.lsp, вставил в моем случае - в экспресс, загрузил через load applications, ввел в комстроке z-calc-text-value - и ничего...в чем тут хитрость? Я тоже хочу сумму и чтобы редактировать...А-2005.

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Sorry. Сам невнимательный- скобку потерял...
А как хорошо жить стало! Конечно, fields, да еще в 2006 - вешчь, но инда не лучше день потерять, да за пять минут долететь...

Re: LISP. Вычисление суммы чисел (например, в экспликации)

2 ZZZ, старый код от (2005-08-16 23:24:57) рациональнее: теперь нужно лишний раз нажимать OK, что бы закрыть окошко с полученной суммой, одним словом баловство:-). А за программу, большое спасибо, теперь складываю даже то, что раньше и думал smile.
На счет лишних нулей... Меняем в настройках Автокада точность. Format->Units... В поле Precision: выбираем 0.00. Автокад будет округлять полученные данные до двух знаков после запятой.
2  ВитаЛ. У меня Acad 2005 даже с заданной точность 0.0000000 лишние нули не пишет. Например, слаживаю 2.00000+2,000=4. Или 18,0000 и 18,6500=36.65. Обманщик smile. Во глюк нашел: складываем числа разделенные запятой, получаем ответ разделенный точкой smile. Ай да я.

Re: LISP. Вычисление суммы чисел (например, в экспликации)

> Демиан
Советую использовать последний код.
А для того, чтобы не выскакивало окошко с суммой достаточно перед (alert (strcat "Сумма = " value)) поставить точку с зяпятой, тоесть получится ;(alert (strcat "Сумма = " value)). Так будет лучше.

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Как сделать чтоб разделитель был не точкой, а запятой. Замучался уже в ручную каждый раз перебивать.

Re: LISP. Вычисление суммы чисел (например, в экспликации)

> piton
Добавить код

(setq value (vl-string-subst "," "." value))

перед

(princ (strcat "\n Сумма = " value))

Re: LISP. Вычисление суммы чисел (например, в экспликации)

> ZZZ
Спасибо. Все работает как надо

Re: LISP. Вычисление суммы чисел (например, в экспликации)

http://dwg.ru/dwl/35 - Программа суммирования числовой текстовой информации на чертеже

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Или на http://geol-dh/ru/kai_stru.html Программа SUM.
Примерно в духе RuCAD. правда без выноски, но с суммированием набора объектов. А также: операции с константой, изменение объекта TEXT на значение итога.

Re: LISP. Вычисление суммы чисел (например, в экспликации)

> Alexey
Там приведен код программы? Так чтобы немножко чемуто научится, так для саморазвития.

> KAI
Ссылка у меня не окрывается!? :(

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Боюсь код программы утерян sad

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Ссылка у меня так же не открывается.

Re: LISP. Вычисление суммы чисел (например, в экспликации)

Спасибо всем за облегчАние тупого и трудного труда. Как стало хорошо тыкать мышом по числам и получать опять же результат... ВОТ ЕЩЕ УМНОЖАЛКУ БЫ... А х Б = С... Кто постарается, кто умеет?