|
아래의 과정을 설명 보면서 쭈욱 그대로 따라해 보세요..
1. EXCEL의 DATA는 A1 B1 C1...A2 B2 C2...셀의 값들로 이루어져 있는데..이것을 읽은 후 그 값을
(setq Lst (list (list A1의값 B1의값 C1의값...)(list A2의값 B2의값 C2의값...)...)) 리스트로 저장하고
또한 반대로 리스트의 값을 Excel의 셀에 위치에 쓰기 합니다.
여기서 리스트는 다중리스트가 됩니다.
2. Excel의 실행화일 경로 알기
;Excel 프로그램이 설치되어있다는 가정하에 아래의 구문을 실행
(setq excelPath
(vl-registry-read
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Excel.exe"
"Path"
)
)
(setq excelPath (strcat excelPath "Excel.exe"))
;레지스터리 값을 이용해서 엑셀의 실행화일 경로를 알아냅니다.
3. ActiveX에 Excel 연결 시키기
(if (not msxl-acos)
(vlax-import-type-library
:tlb-filename excelPath
:methods-prefix "msxl-"
:properties-prefix "msxl-"
:constants-prefix "msxl-"
)
)
(setq ExcelApp (vlax-get-or-create-object "Excel.Application"))
2번과 3번을 합쳐서 서브함수로 만들어 사용하면 편리할거 같아서 아래와 같이 만들었습니다.
운영체제 및 Excel의 버전에 따라 다를수도 있습니다.
;;;*************************************************************************
;;; 설 명: 엑셀 로딩
;;; 사 용 법: (setq ExcelApp (subLoadExcel))
;;;*************************************************************************
(defun subLoadExcel (/ excelPath)
(if (and
(setq excelPath
(vl-registry-read
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Excel.exe"
"Path"
)
)
(setq excelPath (strcat excelPath "Excel.exe"))
)
(progn
(if (not msxl-acos)
(vlax-import-type-library
:tlb-filename excelPath
:methods-prefix "msxl-"
:properties-prefix "msxl-"
:constants-prefix "msxl-"
)
)
(setq ExcelApp (vlax-get-or-create-object "Excel.Application"))
)
)
ExcelApp
)
* 여기 까지는 이해 못해도 상관없습니다.
4. VLISP에서 Excel을 접근하려면 Excel 구조를 먼저 알아야겠군요..
가. Excel에 열려있는 화일들
나. 선택한 화일
다. 시트들
라. 선택한 시트
마. 셀들
바. 선택한 셀
위의 단계들을 차례대로 해보겠습니다.
;서브함수 (subLoadExcel)를 로딩한다
(setq ExcelApp (subLoadExcel))
;엑셀을 실행시킨다.
(vlax-put Excelapp "visible" :vlax-true) ;<-:vlax-false일 경우는 실행을 안시킴
;엑셀을 실행시키지 않고도 자료를 읽기하거나 쓰는데는 문제가 없지만
;지금은 공부단계 과정이니 실행을 시켜놓고 합니다.
;열려있는 화일들
(setq Workbooks (vlax-get-property ExcelApp 'Workbooks))
;이쯤에서 기록하는 방법과 읽는 방법으로 나누어지네요..
;일단 기록하는 방법부터 해보고 열기해서 값을 읽어오게 하는 것은 맨아래 예제 서브함수로 대치하겠습니다.
;새로운 엑셀화일을 만들때
;>---------------------------------------------------------------------------------------------
(setq CurrentWBook (vlax-invoke-method Workbooks 'Add))
;또 다른 방법 (setq CurrentWBook (msxl-Add Workbooks))
;엑셀의 새로만들기 한 효과가 있으며 그것을 변수 CurrentWBook에 저장한다.
;<---------------------------------------------------------------------------------------------
화일이 열려져 있으니 vlax-get-property 함수를 이용하여 현재 시트들을 변수로 저장시키고
(setq Sheets (vlax-get-property ExcelApp 'Sheets)) ;Sheet의 집합체
현재 활성된 시트도 변수로 저장하고..
(setq AcSheet (vlax-get-property ExcelApp 'ActiveSheet)) ;현재 활성된 시트
;또 다른 방법 (setq AcSheet (msxl-get-ActiveSheet ExcelApp))
* 참고
property와 method의 구분
ActiveX는 객체를 다루는 응용기술인데 특성(property)과 메쏘스(method) 나누어 집니다.
어느글에서 설명을 한것을 인용해서 설명하면
객체를 강아지라고 하고
강아지는 얼굴도 있고 눈도 있고 발도 있고 꼬리도 있고..등등으로 구성되어 있습니다.
여기서 얼굴 눈 발 꼬리...등을 특성(property)이라고 합니다.
그 객체가 고유하게 가지고 있는것들이져..
그런데 여기서 강아지가 꼬리를 흔듭니다.
강아지고 멍멍 하고 짖습니다. 강아지가 뜁니다.
이러한 행동을 하는것을 메쏘스(method)라고 누군가 설명하더군요..
캐드에서 라인객체를 위 설명과 비교해보면
라인은 시작점이 있고 끝점이 있고 레이어도 있고 선의 종류도 있고...이걸 특성(property)이라고 하고요
라인을 지워라..복사해라..이동해라..회전시켜라...등등을 메쏘스(method)라고 할 수 있겠네요..
엑셀을 접근하는 방식에서
특성값을 읽어 올때는 vlax-get-property 함수를 사용하고
특성값을 변경 시킬때는 vlax-put-property 함수를 사용하고
메쏘스를 사용할때는 vlax-invoke-method 함수를 사용합니다.
이거 이외에도 ActiveX에서 연결시키는 것에 따라 msxl- <-이런류의 함수도 사용됩니다.
여기서는 vlax-get-property , vlax-put-property , vlax-invoke-method 이 세가지 함수 위주로 해보겠습니다.
캐드에서 ActiveX 함수로 값을 쓰거나 읽기 할때 배열을 사용하기도 하는데
배열을 만들때는 (setq a (vlax-make-variant "값")) <- 이런식으로 만들고
그 값을 확인할때는 (vlax-variant-value a) <- 이런식으로 확인합니다.
* 구체적인 방법에 대해서는 배열함수를 따로 보세요..
;>--------------------------------------------------------------------------------------------
시트를 다루는 방법 몇가지를 해보겠습니다.
. 시트들의 이름을 알아낸다.
. 내가 알고 있는 시트로 이동하고 현재 활성된 시트로 변경시킨다.
. 새로운 시트를 추가한다.
. 시트 이름을 변경한다.
. 특정 시트를 삭제한다.
시트를 다루는 경우의 수가 몇가지 안되네요..
;시트들의 이름을 알아낸다.
(setq SheetNameList '())
(vlax-for item Sheets
(setq SheetNameList (append SheetNameList (list (vla-get-name item))))
)
변수 SheetNameList의 결과값이 ("Sheet1" "Sheet2" "Sheet3") <- 이렇게 리스트로 나옵니다.
* vlax-for 함수는 ActiveX 의 설명을 참조하고 여기서는 생략합니다.
;현재 활성화된 시트이름을 알아낸다.
(setq AcSheetName (vla-get-name AcSheet))
"Sheet1" 이라고 나오네요
;내가 알고 있는 시트로 이동하고 현재 활성된 시트로 변경시킨다.
"Sheet2"로 이동시켜서 활성화 시킵니다.
먼저 "Sheet2"를 객체로 잡으려면
(setq SheetName "Sheet2")
(setq Sht (vlax-get-property Sheets 'Item SheetName))
변수 Sht는 "Sheet2"의 객체입니다.
Sht객체를 현재 시트로 활성화 합니다.
(setq AcSheet (vlax-invoke-method Sht 'Activate))
;또다른 방법
(setq SheetName "Sheet2")
(vlax-for item Sheets
(if (= (vlax-get-property item 'Name) SheetName)
(vlax-invoke-method item 'Activate)
)
)
;시트를 추가하려면
(setq SheetName "myArchiMore")
(vlax-put-property (vlax-invoke-method Sheets 'Add) 'Name SheetName)
엑셀을 보면 "myArchiMore"란 시트가 생겨났져?
;시트를 삭제하려면
(setq SheetName "Sheet2")
(vlax-for item (vlax-get-property ExcelApp 'Sheets)
(if (= (vlax-get-property item 'Name) SheetName)
(vlax-invoke-method item 'Delete)
)
)
;<----------------------------------------------------------------------------------------
;>----------------------------------------------------------------------------------------
시트에 대해 다루어 봤으니 이젠 셀을 다루어 보겠습니다.
셀에 값을 넣어주고 읽고 하는 방법이 실제로 우리가 필요로 하는것들이져..
셀은 고유의 주소값이 있습니다. A2 B15 C7 등...
엑셀에서 표현하는 주소방식이 여러가지 있는거로 알지만 우리는 캐드 사용자이니..
캐드식의 주소로 사용하겠습니다.
A2 는 가로로 A 이고 세로로 2 입니다.
B15 는 가로로 B 이고 세로로 15 입니다.
C7 는 가로로 C 이고 세로로 7 입니다.
알파벳을 숫자로 표현하면 A B C D E F -> 1 2 3 4 5 이렇게 되겠져
그런데 이걸 둘다 숫자로 표현할때는 세로가 먼저고 가로가 나중입니다.(엑셀에서 정한 규칙인거 같아요)
A2는 2 1 , B15는 15 2 , C7는 7 3
; A1셀에 "I love ArchiMore" 값을 넣으려면
(setq Cells (vlax-get-property AcSheet 'Cells))
(setq colY 1 rowX 1) ;<- 1,1은 A1
(setq val "I love ArchiMore")
(vlax-put-property Cells 'Item colY rowX val)
; 리스트의 값을 셀에 넣으려면
; 만약 B3에서 부터 가로로 쭈욱 넣으려면...B3은 세로3 가로2번의 위치이져
(setq colY 3 rowX 2) ;<- 요건 B3
(setq SomeData '("나는" "아키모아에서" "달수가" "강의하는" "글을" "보고" "있습니다."))
(mapcar
'(lambda (val)
(vlax-put-property Cells 'Item colY rowX val)
(setq rowX (1+ rowX))
)
SomeData
)
반대로 엑셀에 값이 있다고 하고..가로로 한줄을 읽으려면
(setq colY 3 rowX 2)
(setq Lst '())
(while
(setq val
(vlax-variant-value
(vlax-get-property
(vlax-variant-value (vlax-get-property Cells 'Item colY rowX))
'value
)
)
)
(setq Lst (append Lst (list val)))
(setq rowX (1+ rowX))
)
;여기서 값을 읽을때는 vlax-variant-value 함수를 사용했습니다. 기록할때는 배열을 사용하지 않았는데
;읽기 할때는 왜 사용되었을까요? 저의 추정으로는 기록할때는 ActiveX에서 자동으로 배열을 만들어
;준거 같습니다. 문자인지 숫자인지 스스로 알아서 입력 해주는거로 추정됩니다.
;설명서 같은게 없다보니 추정밖에 할 수가 없군요..
여기까지가 캐드에서 얻어진 리스트를 엑셀에 기록하는 과정이었습니다.
젤 중요한거라 생각됩니다.
;<----------------------------------------------------------------------------------------
;>----------------------------------------------------------------------------------------
지금부터는 셀에 폭을 변경하고 색상을 넣어보는 과정을 해보겠습니다.
참고로 저는 엑셀 VBA를 모릅니다. 그런데 그 도움말을 참고해서 이 글을 쓰고 있습니다.
vlax-get-property vlax-put-property vlax-invoke-method vlax-for
<- 이것은 ActiveX 함수이며
'Add 'ActiveSheet 'Item 'Activate 'Name 'Sheets 'Delete
<- 이것은 Excel에서 쓰여지는 특성 및 메쏘스입니다.
특성 및 메쏘스는 Excel VBA 도움말로 확인하세요..
특정한 셀을 객체로 잡아서
(setq colY 1 rowX 1) ;<- 1,1은 A1
(setq cel (vlax-variant-value (vlax-get-property Cells 'Item colY rowX)))
<- cel 변수에 A1셀이라는 객체를 잡았습니다.
배열로 응답해서 vlax-variant-value 함수로 그 값을 확인합니다.
cel에 들어있는 값을 확인하려면
(setq val (vlax-variant-value (vlax-get-property cel 'value)))
cel에 폭을 확인하려면
(setq wid (vlax-variant-value (vlax-get-property cel 'ColumnWidth)))
cel의 배경색을 확인하려니깐..Interior 객체를 잡아야 하는군요..
; interior 정보확인
(setq int (vlax-get-property cel 'Interior))
cel의 배경색 확인
(setq col (vlax-variant-value (vlax-get-property int 'ColorIndex)))
확인이 끝났으니 이번엔 반대로 변경을 시켜보겠습니다.
(vlax-put-property cel 'Item colY rowX "아키모아") <- 값을 변경
(vlax-put-property cel 'ColumnWidth 25) <- 폭을 25로 변경
(vlax-put-property int 'ColorIndex 6) <- 노랑색으로 배경을 변경
위의 구문을 예제로 삼아서 나머지 특성들도 직접 바꾸어 보세요..
;<----------------------------------------------------------------------------------------
닫기, 저장하기, 다른이름으로저장하기 등의 메쏘스는 엑셀 VBA도움말을 참조하시고..
ActiveX에서는 지금 까지 사용된 객체를 메모리에서 모두 제거해야겠지요..
(vlax-release-object AcSheet)
(vlax-release-object Sheets)
(vlax-release-object CurrentWBook)
(vlax-release-object Workbooks)
(vlax-release-object ExcelApp)
위의 구문들을 이용하여 서브함수로 만들어서 사용하면
깊이 공부할 필요없이 읽고 쓰기는 가능해질거 같습니다.
엑셀의 값을 읽어서 리스트화 시키는 과정을 서브함수로 만들어 보면
;;;*************************************************************************
;;; 설 명: 엑셀화일을 읽어 리스트화 시키고 그 리스트값을 변수에 저장한다.
;;; 사 용 법: (setq totValLst (subReadValListMain))
;;;*************************************************************************
(defun subReadValListMain (/ fileName ExcelApp Workbooks CurrentWBook Sheets AcSheet Cells totValLst)
;;;*************************************************************************
;;; 설 명: 엑셀 로딩
;;; 사 용 법: (setq ExcelApp (subLoadExcel))
;;;*************************************************************************
(defun subLoadExcel (/ excelPath)
(if (and
(setq excelPath
(vl-registry-read
(strcat
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows"
"\\CurrentVersion\\App Paths\\Excel.exe"
)
"Path"
)
)
(setq excelPath (strcat excelPath "Excel.exe"))
)
(progn
(if (not msxl-acos)
(vlax-import-type-library
:tlb-filename excelPath
:methods-prefix "msxl-"
:properties-prefix "msxl-"
:constants-prefix "msxl-"
)
)
(setq ExcelApp (vlax-get-or-create-object "Excel.Application"))
)
)
ExcelApp
)
;;;*************************************************************************
;;; 설 명: 셀값을 읽어옴
;;; 매개변수: Cells colY(세로번호) rowX(가로번호)
;;; 사 용 법: (setq val (subReadCell Cells colY rowX))
;;;*************************************************************************
(defun subReadCell (Cells colY rowX)
(vlax-variant-value
(vlax-get-property
(vlax-variant-value (vlax-get-property Cells 'Item colY rowX))
'value
)
)
)
;;;*************************************************************************
;;; 설 명: 엑셀값을 읽어서 리스트화 시킨다.
;;; 매개변수: Cells colY(세로의시작위치) rowX(가로의시작위치)
;;; 사 용 법: (setq totValLst (subReadValList Cells colY rowX))
;;;*************************************************************************
(defun subReadValList (Cells colY rowX / rowXtmp valLst totValLst val)
(setq rowXtmp rowX valLst '() totValLst '())
(while (setq val (subReadCell Cells colY rowXtmp))
(while (setq val (subReadCell Cells colY rowXtmp))
(setq valLst (append valLst (list val)))
(setq rowXtmp (1+ rowXtmp))
)
(setq totValLst (append totValLst (list valLst)))
(setq colY (1+ colY) rowXtmp rowX valLst '())
)
totValLst
)
(if (setq fileName (getfiled "Select Excel file to read :" (getvar "dwgprefix") "xls" 8))
(progn
(setq ExcelApp (subLoadExcel))
(setq Workbooks (vlax-get-property ExcelApp 'Workbooks))
(setq CurrentWBook (vlax-invoke-method Workbooks 'Open fileName))
(setq Sheets (vlax-get-property ExcelApp 'Sheets))
(setq AcSheet (vlax-get-property ExcelApp 'ActiveSheet))
(setq Cells (vlax-get-property AcSheet 'Cells))
(setq totValLst (subReadValList Cells 1 1))
(vlax-invoke-method CurrentWBook 'Close :vlax-False)
(vlax-release-object Cells)
(vlax-release-object AcSheet)
(vlax-release-object Sheets)
(vlax-release-object CurrentWBook)
(vlax-release-object Workbooks)
(vlax-release-object ExcelApp)
totValLst
)
)
)
;메인함수 구문중에 엑셀의 값을 읽어와야 할때 위에서 만든 서브함수를 실행시키면
(setq totValLst (subReadValListMain)) ;<- 엑셀의 값이 totValLst에 저장되어 있습니다.
;참고) 범위지정 하는 방법
(setq Ran (vlax-get-property ExcelApp 'Range "A2:C5"))
(setq acRan (vlax-invoke-method Ran 'Activate))
|
첫댓글 우왓~~~감사합니다. 새로운 사실들이 후두둑 들어오네요~~~입문과정을 마쳤으니....초급과정은 언제쯤?ㅋㅋㅋ
달수님... 수고하셨습니다. ^^*
현 강좌가 입문과정이면... 초급과정은 얼매나 어려울까여? ㅎㅎㅎ
LISP은 입문과 동시에 실전입니다. 초급,중급,고급은 없습니다..ㅎㅎ
처음 발 담구기가 어려운거지..발담구는 순간부터는 자동...^^
우아~달수님 수고하셨습니다.입문과정이라...ㅎㅎ
잘 보았읍니다^
좋은강좌 ~!! 수고하셨습니다. ^^;;
아..달수님 이거 올리셨네요?^^*
역시 멋지십니다^^*
열심히 공부할게요^^*
우와..대단하십니다...
또 기다려도 될까요?
아...첨에 달수님이 올려주셨던 객체지도 봤을때의 느낌과 비슷한 느낌이 납니다^^*
먼가 하날 깨달은 듯한 느낌^^*
이거 정리하시느냐구 엄청 시간 걸렸을거 같네요^^
달수님 다시함 너무너무 감사드립니다^^*
달수님 예전에 공부 엄청 잘하셨을거 같아요^^
정리의 신...^^* 최곱니다 ^0^b
엑셀자체가 ExcelApp <- 이렇게 activeX로 받아진다는게 젤루 중요한 포인트 인거 같습니다^^* 다시함 감사드려요^^* ㅎㅎ
달수님 정말 대단 하십니다. 잘 모르는 분야라 그냥 부럽기만 하네요.
달수님의 멋진 생각 엿보고 갑니다. 수고 하셨습니다. 짝~짝~짝~
허미 맨위에 이미지를 보니 달수님이 드디어 책을 출판하실려고???? 하시나 봐여? ㅎㅎㅎ ^^;;;;
달수님 강의 언제봐도 최고~~~~~~~ ^^
열공! 열공! 하겠습니다.^^
엑셀쪽으로 다시한번 길라잡기가 되어주시는군여.^^
역시![쵝오](https://t1.daumcdn.net/cafe_image/pie2/texticon/ttc/texticon15.gif)
..
감사합니다.
좋은 강좌 너무 감사합니다.
수고하셨습니다~
감사합니다.
멋지십니다
감사합니다~
이런 강좌는 어데가서 눈을 씻고 찾아봐도 없습니다....와우 대박입니다.
감사합니다.
감사합니다
흐미 북마크해야겠네요.. 감사합니다.
넘 넘 대박이네요 감사합니다.
우와 대단하네요 몇번을 봐야 저는 이해가 올려나...^^
좋은자료 감사합니다.
공부하는데 도움이 많이 되네요..
달수님 열심히 따라할게요. 감사
감사합니다,
대단하십니다...걈사합니다...
정말 감사합니다. 이렇게 정리 된건 처음입니다.
감사합니다~~
그런데 저장되있는걸 쓰려면 어떻게해야되나요?
(startapp "C:\\Program Files\\Microsoft Office\\Office14\\EXCEL.EXE" "c:\\축공차.XLS")
이렇게쓰니까 리습실행할때마다 엑셀창이 추가로 계속 뜨고그러네요 ;;;
(vlax-put Excelapp "visible" :vlax-false)
이렇게했는데도 창이 계속 떠요 ;;; 자꾸 nil 이게뜨네요 ㅠ
어떻게해야될지모르겟어요 ㅠㅠ
헐... 대박 감사합니다!
헐~ 님 쫌 짱인듯...ㅋㅋ
남을 위한 배려심! 감사합니다.
와~감사합니다.^^
검은것은 글씨요 하얀 것을 바닥이로세~ ㅠㅠ ... 너무 어렵습니다.
엑셀의 이웃한 두셀의 값을 ctrl +c 하고
이 복사된 2개의 값을
리습의 변수1 변수2에 넣기만하면 되는데요..
리습 울렁증이 심한 제가 해 낼 수 있을지 모르겠습니다.
감사합니다..
정말 대단합니다. 처음부터 하나식 작성해 봐야겠네요~
이렇게 좋은 정보 감사합니다!!^^
유용하게 사용 하겠습니다.
정말 감사합니다.
이거 보면서 공부중입니다.
리습에서 작성한 데이터를
엑셀에 셀을 클릭하면 데이터를 입력을 하고 싶습니다.
셀에 주소 값을 알아내서 지정하면 될거 같은데
이 주소를 알 수 있는 방법을 이거 저거 다 해봐도 않되네요...
설명 좀 부탁드립니다.
^^ 해결 했습니다.
좋은 정보 감사합니다.
감사합니다 함 입문해볼까 하는데요
대박입니다..
열심히 연구하겠습니다감사합니다
감사합니다~^*^황홀