Тема: LISP. LIB. Функция получения данных из Excel

Багов вроде не заметно.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;;функция возвращает указанный прямоугольный диапазон ячеек из екселя в виде
;;;((?строки ?столбца Значение) (?строки ?столбца Значение).....(?строки ?столбца Значение))
;;;Причем верхняя левая ячейка диапазона получает номер 1 1 т.е. (1 1 Значение)
;;;Если ячейка пустая, ее значение = "Empty"
;;;
;;;Вызов (get_excel_range path sheet_name_or_number r1 c1)
;;;где:
;;; path - путь к файлу екселя вида "Disk:\\Dir1\\.....\\DirN\\file.xls"
;;; sheet_name_or_number - имя листа(STRING) или его номер(INT)
;;; r1   - верхняя левая ячейка диапазона. например "A1"
;;; c1   - нижняя правая ячейка диапазона. Например "F15"
;;;
;;;Возможные варианты вызова:
;;; - без указания диапазона
;;;   (get_excel_range path sheet_name_or_number nil nil)
;;;Функция попробует открыть файл по указанному пути и, если удастся открыть, попробует активировать указанный лист
;;;и попросит подсветить диапазон вручную. Если не удастся - попросит открыть файл и подсветить диапазон вручную.
;;;если листа с заданным именем(номером) не существует - вылет с ошибкой Automation error
;;; - без указания имени листа и диапазона
;;;   (get_excel_range path nil  nil nil)
;;;Функция попробует открыть файл по указанному пути и, если удастся открыть, попросит подсветить диапазон вручную
;;; - без каких либо параметров
;;;Фyнкция попросит открыть файл и подсветить диапазон вручную
;;;
;;;!!!Проверка на корректность задания диапазона не производится!!!
;;;
;;;
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun get_excel_range     (
                path
                sheet_name_or_number
                r1
                c1
                /
                already_opened
                ExcelApp
                WorkBook
                used_range
                lst
                lis
                liss
                               temp_index
                num_of_collumns
                num_of_rows
                row
                col
                close_app
                old_error
               )
(setq old_error *error*)
  (defun *error* (msg)
    (setq *error* old_error)
    (setq old_error nil)
       (vl-catch-all-error-p (vl-catch-all-apply 'vlax-invoke-method (list WorkBook "Save")))
       (if close_app (vl-catch-all-error-p (vl-catch-all-apply 'vlax-invoke-method (list ExcelApp "Quit"))))
        (mapcar
            (function (lambda (x)
                    (if (and x (if (not (vl-catch-all-error-p x)) (not (vlax-object-released-p x)) nil))
                    (vlax-release-object x)
                        )
                  )
            )
  (list used_range sheet WorkBook ExcelApp)
)
(setq used_range nil sheet nil WorkBook nil ExcelApp nil)
     (gc) (gc)
    (princ (strcat "\nError: " msg))
    (princ)
); end *error*
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  (if (not (setq ExcelApp (vlax-get-object "Excel.Application")))
    (setq ExcelApp (vlax-create-object "Excel.Application")
          close_app :vlax-true))
  (if path ;если путь задан
     (if (not (vl-catch-all-error-p
                (progn
        (princ "\nTrying to open Excel file. Please wait.\n")
        (setq WorkBook (vl-catch-all-apply 'vla-open (list (vlax-get-property ExcelApp "WorkBooks") path)))
           )))
        ;если удалось открыть файл
       (progn
      (if sheet_name_or_number
        (if (not (vl-catch-all-error-p (setq sheet (vl-catch-all-apply 'vlax-get-property (list (vlax-get-property WorkBook "Sheets") "Item" sheet_name_or_number)))))
        (vlax-invoke-method sheet "Activate")
        (princ "\nThe given sheet name is not correct")
        )
      )
      (if (and r1 c1); Если задан диапазон
        (progn
            (vlax-invoke-method WorkBook "Activate"); активировать открытый документ
            (setq used_range (vlax-get-property ExcelApp 'Range (vlax-make-variant r1) (vlax-make-variant c1)); получение указателя на выделенную область
                  lst (vlax-safearray->list (vlax-variant-value (vlax-get-property used_range 'Value)))) ;; получение списка данных с екселя
        )
        ;Если диапазон не задан
        (progn
          ;сказать об этом и попросить указать диапазон вручную
         (princ "\nNo range given. Highlight data area manualy")
             (vlax-put-property ExcelApp 'Visible :vlax-true)
                 (getstring "\nselect data area in Excel and then press enter"); ожидать нажатие клавиши
                 (setq used_range (vlax-get-property ExcelApp 'Selection); получение указателя на выделенную область
                       lst(vlax-safearray->list (vlax-variant-value (vlax-get-property used_range 'Value)))) ;; получение списка данных с екселя
        )
      )
    )
             (progn ;Если файл не открылся
         ;сказать об этом и попросить указать диапазон вручную
         (princ "\nError while opening file. Highlight data area manualy")
         (vlax-put-property ExcelApp 'Visible :vlax-true)
                 (getstring "\nselect data area in Excel and then press enter"); ожидать нажатие клавиши
                 (setq used_range (vlax-get-property ExcelApp 'Selection); получение указателя на выделенную область
                       lst (vlax-safearray->list (vlax-variant-value (vlax-get-property used_range 'Value)))) ;; получение списка данных с екселя
             )
     )
    ;Если путь не задан
             (progn
          ;сказать об этом и попросить указать диапазон вручную
         (princ "\nNo range given. Highlight data area manualy")
             (vlax-put-property ExcelApp 'Visible :vlax-true)
                 (getstring "\nselect data area in Excel and then press enter"); ожидать нажатие клавиши
                 (setq used_range (vlax-get-property ExcelApp 'Selection); получение указателя на выделенную область
                       lst (vlax-safearray->list (vlax-variant-value (vlax-get-property used_range 'Value)))) ;; получение списка данных с екселя
              )
  )
;;;**************************************************************************************
      (setq num_of_rows (length lst);вычислить кол-во строк
            num_of_collumns (/ (vlax-get-property used_range 'Count) num_of_rows)) ;вычислить Кол-во столбцов
                    (setq lis '() temp_index 0);;
                      (while (/= (1- (1- temp_index)) num_of_rows)
                          (setq lis (append lis (nth temp_index lst))
                    temp_index (1+ temp_index))
                      );;end while
               ;;инициализация текущих переменных
                    (setq liss '() row 1 col 1)
               ;; Формирование списка, содержащего элементы типа (Nстроки Nстолбца элемент)
         (foreach n lis
         (setq liss
            (cons
              (list row
                col
               (if (/= (vlax-variant-value n) nil)
                (if    (/= 'STR (type (vlax-variant-value n)))
                  (rtos (vlax-variant-value n) 2 2)
                  (vlax-variant-value n)
                )
                 "Empty"
               )
              )
              liss
            )
         )
         (setq col (1+ col))
         (if (> col num_of_collumns) (progn (setq col 1) (setq row (1+ row))))
     )
;; Закрытие Екселя
(vl-catch-all-error-p (vl-catch-all-apply 'vlax-invoke-method (list WorkBook "Save")))
(if close_app (vl-catch-all-error-p (vl-catch-all-apply 'vlax-invoke-method (list ExcelApp "Quit"))))
(mapcar
  (function (lambda (x)
          (if (and x (if (not (vl-catch-all-error-p x)) (not (vlax-object-released-p x)) nil))
          (vlax-release-object x)
              )
        )
  )
  (list used_range sheet WorkBook ExcelApp)
)
(setq used_range nil sheet nil WorkBook nil ExcelApp nil)
     (gc) (gc)
     (reverse liss)
)

Re: LISP. LIB. Функция получения данных из Excel

Осмелюсь добавить сюда же в ветку запись координат,
указанных на экране, по смыслу близко и кому-нибудь
понадобится, хотя бы для примеру
(для А2000 и выше):

(defun defpoints ()
  (setq lst nil)
  (setq loop T)
  (setq  pt  (getpoint "\nПервая точка :")
  lst (cons pt lst)
  )
  (while
    (setq pt (getpoint "\nСледующая точка :" pt))
     (if (null pt)
       (setq loop nil)
     )
     (setq lst (cons pt lst))
  )
  (reverse lst)
)
(defun C:PUN (/          *aplexcel*      *books-colection*
        *excell-cells*  *new-book*      *sheet#1*
        *sheet-collection*        col
        header        iz_listo        punto_datos
        row
       )
;;; Written by  ALEJANDRO LEGUIZAMON -  http://arquingen.tripod.com.co
;;; edited by FATTY T.O.H. - FattyHallex@gmail.com
  (or (vl-load-com))
  (setq punto_datos (defpoints))
  (alert "Просто закрой Эксель")
  (setq  *AplExcel*     (vlax-get-or-create-object "Excel.Application")
  *Books-Colection*  (vlax-get-property *AplExcel* "Workbooks")
  *New-Book*     (vlax-invoke-method *Books-Colection* "Add")
  *Sheet-Collection* (vlax-get-property *New-Book* "Sheets")
  *Sheet#1*     (vlax-get-property *Sheet-Collection* "Item" 1)
  *excell-cells*     (vlax-get-property *Sheet#1* "Cells")
  )
  (vla-put-visible *AplExcel* :vlax-true)
  (setq row 1)
  (setq col 1)
  (setq header '("X" "Y" "Z"))
  (repeat (length header)
    (vlax-put-property
      *excell-cells*
      "Item"
      row
      col
      (vl-princ-to-string (car header))
    )
    (setq header (cdr header))
    (setq col (1+ col))
  )
  (setq  row 2
  col 1
  )
  (repeat (length punto_datos)
    (setq iz_listo (car punto_datos))
    (repeat (length iz_listo)
      (vlax-put-property
  *excell-cells*
  "Item"
  row
  col
  (vl-princ-to-string (car iz_listo))
      )
      (setq iz_listo (cdr iz_listo))
      (setq col (1+ col))
    )
    (setq punto_datos (cdr punto_datos))
    (setq col 1
    row (1+ row)
    )
  )
  (vlax-invoke-method
    *New-Book*
    'SaveAs
    (strcat (getvar "dwgprefix")
      (vl-string-right-trim ".dwg" (getvar "dwgname"))
    )
    -4143
    nil
    nil
    :vlax-false
    :vlax-false
    1
    2
  )
  (vlax-release-object *excell-cells*)
  (vlax-release-object *Sheet#1*)
  (vlax-release-object *Sheet-Collection*)
  (vlax-release-object *New-Book*)
  (vlax-release-object *Books-Colection*)
  (vlax-release-object *AplExcel*)
  (setq *AplExcel* nil)
  (gc)
  (gc)
  (princ)
)
(prompt "\n\t\t***\tНабери в командной строке PUN \t***\n")
(princ)
;|«Visual LISP© Format Options»
(72 2 50 2 nil "end of " 60 9 0 0 0 T T nil T)
;*** DO NOT add text below the comment! ***|;

(Файл Эксель автоматически сохраняется с именем чертежа)
~'J'~

Re: LISP. LIB. Функция получения данных из Excel

Очень интересная функция. Мне пригодится.

Re: LISP. LIB. Функция получения данных из Excel

Есть еще одна - переводит адрес ячейки к формату r1c1 - понятному функции (get_excel_range) и собсно самому екселю

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;Ф-ция перевода цифр в буквы для перевода цифровых(вычисленных) адресов ячеек
;;;в формат R1C1 - формат екселя
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun letter (num
           /
           1st
           2nd
           )
  (setq 1st 0)
  (setq 2nd num)
  (while (> 2nd 26)
    (setq 1st (1+ 1st))
    (setq 2nd (- 2nd 26))
  )
  (strcat
    (cond
     ((= 1 1st) "A") ((= 9 1st) "I")  ((= 17 1st) "Q") ((= 25 1st) "Y")
     ((= 2 1st) "B") ((= 10 1st) "J") ((= 18 1st) "R") ((= 26 1st) "Z")
     ((= 3 1st) "C") ((= 11 1st) "K") ((= 19 1st) "S") ((= 0 1st) "")
     ((= 4 1st) "D") ((= 12 1st) "L") ((= 20 1st) "T")
     ((= 5 1st) "E") ((= 13 1st) "M") ((= 21 1st) "U")
     ((= 6 1st) "F") ((= 14 1st) "N") ((= 22 1st) "V")
     ((= 7 1st) "G") ((= 15 1st) "O") ((= 23 1st) "W")
     ((= 8 1st) "H") ((= 16 1st) "P") ((= 24 1st) "X")
    )
    (cond
     ((= 1 2nd) "A") ((= 9 2nd) "I")  ((= 17 2nd) "Q") ((= 25 2nd) "Y")
     ((= 2 2nd) "B") ((= 10 2nd) "J") ((= 18 2nd) "R") ((= 26 2nd) "Z")
     ((= 3 2nd) "C") ((= 11 2nd) "K") ((= 19 2nd) "S") ((= 0 2nd) "")
     ((= 4 2nd) "D") ((= 12 2nd) "L") ((= 20 2nd) "T")
     ((= 5 2nd) "E") ((= 13 2nd) "M") ((= 21 2nd) "U")
     ((= 6 2nd) "F") ((= 14 2nd) "N") ((= 22 2nd) "V")
     ((= 7 2nd) "G") ((= 15 2nd) "O") ((= 23 2nd) "W")
     ((= 8 2nd) "H") ((= 16 2nd) "P") ((= 24 2nd) "X")
    )
  )
)

Re: LISP. LIB. Функция получения данных из Excel

А подскажите пожалуйста, как эту функцию можно использовать. Каким образом расположить возращаемые значения на чертеже?

Re: LISP. LIB. Функция получения данных из Excel

Зная базовую точку и высоту вставки текста можно вставить список как таблицу, расчитывая смещение:
Х=Хбаз*(car item)*(макс длина строки)
У=Убаз*(cadr item)*(высота текста)
ну ессно с каким-то интервалом

Re: LISP. LIB. Функция получения данных из Excel

И как этим пользоваться? как сохранить как подгрузить, куча кодов в один
ЗЫ Просьба Юзеров сильно не пинать

Re: LISP. LIB. Функция получения данных из Excel

Посмотрите самую верхнюю тему с префиксом FAQ

Re: LISP. LIB. Функция получения данных из Excel

> Random
Это я все сделал как запустить ее чтобы она заработала какую команду надо набрать?

Re: LISP. LIB. Функция получения данных из Excel

> Raver
Не сочтите за грубость, но вы, видимо, так же как компилятор, игнорируете комментарии после

;;;

smile
Посмотрите внимательно в самом начале:

;;;Вызов (get_excel_range path sheet_name_or_number r1 c1)
;;;где:
;;; path — путь к файлу екселя вида "Disk:\\Dir1\\.....\\DirN\\file.xls"
;;; sheet_name_or_number — имя листа(STRING) или его номер(INT)
;;; r1   — верхняя левая ячейка диапазона. например "A1"
;;; c1   — нижняя правая ячейка диапазона. Например "F15"
;;;
;;;Возможные варианты вызова:
;;; — без указания диапазона
;;;   (get_excel_range path sheet_name_or_number nil nil)
;;;Функция попробует открыть файл по указанному пути и, если удастся открыть, попробует активировать указанный лист
;;;и попросит подсветить диапазон вручную. Если не удастся — попросит открыть файл и подсветить диапазон вручную.
;;;если листа с заданным именем(номером) не существует — вылет с ошибкой Automation error
;;; — без указания имени листа и диапазона
;;;   (get_excel_range path nil  nil nil)
;;;Функция попробует открыть файл по указанному пути и, если удастся открыть, попросит подсветить диапазон вручную
;;; — без каких либо параметров
;;;Фyнкция попросит открыть файл и подсветить диапазон вручную

Re: LISP. LIB. Функция получения данных из Excel

> Random
Вариант ф-ции letter

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;Ф-ция перевода цифр в буквы для перевода цифровых(вычисленных) адресов ячеек
;;;в формат R1C1 — формат Excel
;;;1="A", 2="B", ... 26="Z", 27="AA", 28 = "AB
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun Letter (N            ;_Integer Номер ячейки
          /
          Res        ;_Результирующая строка
          TMP)        ;_Временная переменная
  (setq Res "")
  (while (> N 0)
    (setq TMP (rem N 26)        ;_остаток от деления N на 26
      TMP (if (zerop TMP)    ;_сброс к "Z"
        (setq N      (1- N)    ;_переходим к следующему порядку
              TMP 26    ;_смещение на Z
        ) ;_ end of setq
        TMP)                
      Res (strcat            
        (chr (+ 64 TMP))    ;_Смещение + 64 ("A" = 65)
        Res)                
      N   (/ N 26)        ;_уменьшаем порядок
    ))  Res)

Re: LISP. LIB. Функция получения данных из Excel

А подскажите пожалуйста как следующие строчки на VBA перевести на LISP?.. Не могу разобраться с vlax-invoke-method и vlax-get-property.

    Worksheets("Sheet1").Activate
    Range("A21").Select
    Range(Selection, Selection.End(xlDown)).Select

Re: LISP. LIB. Функция получения данных из Excel

А может кто подскажет как данные из форматки спецификации вроде
Материалы
Рейка Ту 001-01
1000x1000
2000x1500
3500x1000 и т.д. Как их перекинуть в таблицу Excel?

Re: LISP. LIB. Функция получения данных из Excel

> edvard
1. Буфер обмена
2. См. >Олег(jr.) (2005-12-29 12:27:47)
3. Сохрани как *.csv файл (данные разделены ;).
Типа
X;Y;Z;
1;2;3;
4;5;6;
Щелкни по нем в проводнике.

Re: LISP. LIB. Функция получения данных из Excel

> VVA
Можно поконкретнее про п.3?

Re: LISP. LIB. Функция получения данных из Excel

Создай на диске файл test.csv. В блокноте набери

X;Y;Z
1;2;3
4;5;6

Сохрани. Дважды щелкни на нем в проводнике. Должен загрузиться Excel Дальше все увидишь.
В зависимости от настроек не целые данные (типа 1.5) могут восприниматься как дата. Читать здесь
https://www.caduser.ru/forum/topic30532.html

Re: LISP. LIB. Функция получения данных из Excel

Про csv почитай здесь http://ru.wikipedia.org/wiki/CSV