PROGRAMMING WORKSHOP

VSTO|
작업일정관리_1

uno-weekly등을
조금씩 기능을 개선한다고 해 놓고는 게으름을 피우다가..
드디어는 에라가 나요..!! 라는 메일을 받는다

스케쥴을 그리는 부분인데 ..기간중에 중단일자가 , 토,일요일쉬는 경우가 없을때
즉 전체 시작일자와 종료일자가 주욱 중단없이 업무를 진행할때
진행기간별로 S-Curve라인챠트가 표현되어 현재일자의 진행률을 시각적으로
보게 한 부분에서 에러가 난다..
즉..S곡선(실은 직선을 연결한 것)을 그리려고 하는데 이 부분의 계산에서
에러가 난 것이다..에라가 나고..당연 S-Line그리기가 포기된다



VBA 모듈같이 한눈에 들어 오는 것을 할때는 척보면 에러를 찾지만..
변수도 많고 이놈이 저놈같고, 저놈이 이놈 같을 때는..
에고..주석이라도 좀 잘 달아 놓지..
로직도 생각이 나지 않고
어떻게 할까...방법이 없다 정공법으로 가는 것..
중단점 걸어 놓고 한줄 한줄 프로세스 라인을 점검하는 것이 가장 빠른 길이다
공장에서 불량이 나오면 라인을 하나,하나 점검하듯이 그것이 가장 빠르고
좋은 방법이다
그러면 잠깐이면 찾는데..그냥 어떻게 한번에 찾는 방법이 없을까..하고
이리 뒤적, 저리 뒤적하다가 골에 지진만 난다..
참 Visual Studio에서 한줄한줄 실행하는 것(Step Through)은 F11 키를 사용한다
VBA에서와 같이 F8키를 사용하면 쌩뚱맞게 오피스의 OUTLOOK이 뜨고
희안한 짓거리를 한다..Visual Studio는 VB만 사용하는 것이 아니고
C#, C++등 다른 언어등도 사용하는 공통개발도구이니..그렇게 정리된 것 같다
아무튼 VBA에서 F8키에 대신되는 키는 F11키이다

아래와 같이 중단일정을 표현하는 것과 아닌 것 두가지인데
중단일정이 없을때 S-Line을 못그린 것이다



위와 같이 변화가 일어나기 위하여 필요한 것은 무엇인가..
딴 것없다 정보의 갯수가 많아지는 것이 다를뿐이다
즉 변수가 많아지는 것이다
전체기간의 시작..datProejctStart As Date
전체기간의 종료..datProjectEnd As Date
중간에 쉬는 날들이 들어 오면
변경기간의 시작...datProjectAdjustStart As Date
변경기간의 종료...datProjectAdjustEnd As Date
또 날짜를 주욱 표현하는 일정 밴드를 표현하기 위하여서는
카렌다시작일자....datProjectCalendarStart As Date
카렌다종료일자....datProjectCalendarEnd As Date
등과 같이 변수들이 작업내용만 잠깐 바꾸면 수도 없이 늘어나는 것이 변수들이다

전체Project단위로 변수도 있겠지만
또 각 작업하나,하나에도 시작일자,종료일자,변경종료,변경시작등이
모두 붙게 되는 것이니..완존히 변수판이라는 점..조금 큰 프로젝트에서 하여야할 일들이다
그러니 개체를 만들지 않을수 없게 된다..
개체가 없이는 도저히 변수관리가 되지 않는 것이다
그래서 개체를 만든다고 생각해도 과언이 아니다,더불어 다른 중요한 점도 있지만..
복잡한 정보의 체계적관리가 목적이라고 해도 과언이 아닌 것이다
그러니..VBA에서 간단한 것을 하면서도 변수명을 설명적으로
즉 변수명만 보면 어떤정보를 담고자 하는 것인지 잘 이해하기 쉽게
지어주는 습관이 좋은 습관이 된다

아무튼 이것을 단편적으로 이야기 하려고 하였으나..
도저히 단편적으로 설명불가!!하여
uno-weekly의 내용을 엑셀 VBA버전으로
하나씩, 하나씩 풀어 나가드리도록 하자
엑셀버전을 이해하고 VSTO를 만드는 것은 단순한 몇가지
Visual Studion의 VSTO상에서의 개체접근을 위한 내용에
숙달 되면 되는 것이다

작업의 일정 관리를 풀어나가기위하여
기본적으로 어떤 작업이 갖고 있는 정보가 무엇인지를 알아야 할 것이다
1,소요일정
2,시작일자
3,종료일자
4,작업명
5,담당자
6,소요금액
정도는 기본일 것이다,
위에서 소요일정,시작일자,종료일자 중 하나는 없어도 될 것이다
위의 작업에 있어서 좀더 전문가적인 기법으로 간다면(CPM,Pert)
선행작업(반드시 해당작업을 위하여 먼저수행되어야할 작업)
이라는 것이 필요하겠지만, 여기에서는 그런 선행이나 후행작업의
개념이 없는 것으로 이야기를 전개해 보도록 하자
여기에서 기본적인 프로그래밍컨셉을 잡아서 각자 좀더
화려하게 확장할수 있다면 무척 다행스러운 일일 것이고
그렇게 되기를 바란다

실은 요사이 안드로이드 폰 프로그래밍에 심취하여
윈도우폰은 아직 많이 사용하지 않으니..안드로이드 하나 더
한다고 힘들 것도 없으니..새로운 언어에 심취하는 맛도 좋다
좀더 심도있게 연구하여 좋은 것을 만들고, 기회가 되면 안드로이드에
대한 이야기도 하도록 하자,아주 흥미로운 이야기들이 많다
언어적측면(Java)보다는 개발도구의 환경이 조금 낯섫어서
버벅거린다
비교하면서 습득한다는 것은 무척 파워를 갖는다..

아무튼 그래서..
좀 게으름을 피웠다..
폰의 프로그래밍을 하다 보면, 역시 느끼는 것은 엑셀은
사무자동화의 꽃이라는 점!! 요지 부동이라는 것을 새삼느낀다
폰은 장난감이다..그냥 요약된 내용을 보는 정보의 것이다
그 정도의 사이즈에서 그 정도의 일만 하는 것..!!
일을 즐기는 사람들은 엑셀을 해야 한다

아무튼 ..
업무일정관리챠트를 그리는 작업을 시리즈로 해보도록 하자
가장 중요하게 컨셉을 잡아야 할 것이..
어떤 A라는 작업이
2012/5/5 일에 시작해서 2012/5/5 일에 끝났다고 하면 작업소요일자를
몇일로 잡을까???0 일로 잡나? 아니면 1일로 잡나?
당연히 1일로 잡아야 한것이다
일정계산을 하기 위하여
2012/5/5-2012/5/5일 하면 0일이다
당연히 1을 추가 하여야 할 것이다

VBA직접실행창에 아래와 같이 실행해도 역시
?datediff("d",#2012/5/5#,#2012/5/5#)
0이 결과 값이다
그래서 +1을 해주어야 소요일자가 된다
또한 시작일자가 있고 소요일자가 있을때 시작일자+소요일자를
한다면 2012/5/5+ 1일을 하면 2012/5/6일이 될것이다
이것은 역시 꺼꾸로 -1을 해주어야 할 것이다
VBA직업실행창에서 아래와 같이 실행하면 역시
?dateadd("d",1,#2012/5/5#)
5일이 되면 좋겠는데 6일이 된다,
그래서 역시 -1을 해준다
이것을 머리속에 팍 박아놓고 전체 프로젝트코딩을 해야지
헷갈리면 일정이 죄도 개판이 된다
아래 그림과 같이 uno-weekly 추가기능화일에서 생성한
작업기본테이블의 정보를 갖고 새로운 정보로 만들어 가는
과정을 보도록 하자



다양한 기능을 섭력하게 될 것이다

척 보면 무엇부터 따지고 싶으신가?
버튼을 크릭하여 그림을 그리라고 시켰는데..

테이블에 정보는 있기는 있는가?
ID는 중복되지 않는가?
WBS코드는 중복되지 않는가?
WBS코드는 논리적으로 맞게 구성되었는가?
작업명은 제대로 있는가?
시작일자,종료일자,기간중에 유효한 계산할수 있는 조건이 갖추어 졌는가?
이렇게 따져서 무엇이 유효하지 않으면 메시지를 띄울까..?
아니면 시치미 뚝떼고 아무것도 하지 않게 할까?
다양한 생각이 날 것이다
사용자가 어떻게 입력을 하였던
유효한 정보가 되는 작업명이 있을때만 작업을 하자!!
WBS의 관계가 논리에 맞지 않는다면 WBS는 없는 것으로
간주하고 그냥 유효한 작업내용만 그리자!!
요점은 사용자입맛에 맞게 하는 것인데..
사용자의 마음을 못읽으면 허당이다
아무리 잘 만들어도 사용자가 사용하지 않겠다는데..뭔 소용있겠는가?
한마디로 User Friendly 한 것이 되어야 하는데
그것이 그렇게 만만치 않은 것이다
각자그런 부분에 많은 관심을 갖는 것이 또한 엑셀프로그래밍이다

아무튼 uno-weekly이 현재 되어있는대로 하도록 하고
각자가 생각을 확장하여 또 멋있게 기능을 추가하여도 좋을 것이고
VSTO의 VB.Net으로 작성된 것에서 몇가지를 VBA방식으로
바꿔야 할 것이다
집합체를 다루는 List ( Of T) 라는 집합체 다루는 개체를 버리고
VBA의 것에서 배열을 사용하던, 집합체를 사용하던 하면 될 것이다

엑셀로 스텝바이스템으로 만들어서 올려 나갈 것이니
이것을 VSTO로 하나, 하나 따라서 구현해 보시기 바란다
잘 안되면 질문하시고..

우선 위의 사용자가 입력한 기본테이블을 아래와 같은
일정 분석테이블을 만드는 것을 하도록 하자



기본테이블을 위와 같이 분석처리하는 것만 해도 많은 생각을 하여야 할것이다
또한 위와 같은 재가공된 정보가 있어야 도형으로 차트를 마음대로
그려 나갈 수 있는 중간 과정이 된다

VSTO에서는 크래스모듈을 사용하는 것은 상식이고
VBA에서는 크래스모듈은 선택적사항이다..사용해도 되고 안해도 된다
(물론 Application개체의 이벤트를 활용하고 싶으면 필수지만)
그러나 이곳은 엄연히 VSTO를 위한 페이지이니
엑셀 VBA에서도 Class모듈을 사용하도록 한다
그래야 쉽게 VSTO로 옮겨 보는 연습을 하실수 있을 것이니까..
더불어 크래스모듈의 활용이 낯섫지 않게 되는 기회가 되면 더욱 좋고
VBA모듈시트에서 Class모듈을 하나 삽입하여..
이름은 clsGantt 라고 짓고....
아래의 엑셀화일에 만들어 놓았다..우선 문제를 풀어 보시고
얼마 있다가 다음 내용을 올리도록 한다

***[LOG-IN]***

VSTO에서 개발을 하는 Add-In은 아래의 그림과 같이
하나의 크래스모듈에 필요한 크래스모듈을 기능별로 구성해 나가는것이
아주 편리한 점이라고 할 수 있을 것이다



VBA에서는 좀 불편한대로
(VisualStudio를 접하기 전에에는 몰랐던 불편함이라고 할 수 있을것이다)
자알..만들어 나갈수 있다
위에 올린 화일의 VBA편집기에 clsTask라를 크래스모듈을 삽입해 놓았을것이다
내용을 아래와 같이 입력하시기를..

Public WBS As String' WBS
Public ID As String' ID
Public TaskName As String ' 작업명
Public StartDate As Date ' 시작일자
Public EndDate As Date' 종료일자
Public StartDateAdjusted As Date' 중간중단기간이 들어갈때 조정된 시작일자
Public EndDateAdjusted As Date' 중간중단기간 적용시 조정된 종료일자
Public Duration As String' 작업기간
Public DurationAdjusted As Integer' 중간중단기간 적용시 조정된 작업기간
Public Amount As Double' 금액
Public InCharge As String' 담당자
Public Other As String' 기타정보
Public datOffDays As Collection 작업기간중 중단일자모음
Public WBSChilds As Collection WBS상위명일때 갖고 있는 자식모음
Public Type As String ' 실제 작업인지 WBS상위 작업명인지..
Public Level As Integer' WBS상의 계층레벨
Public bHasWBSParent As Boolean' 부모를 갖고 있는지

뭐가 복잡한 것 같으신가????
꼼꼼하지 못하면 못하는 것이 컴퓨터 프로그래밍이다..
우노도 무척이나 덜렁거리는 편인데도 하는 것 보면 ..명상하는 셈치고
차근 차근 하는 것도 별로 나쁜 짓은 아니니까..즐기시기를...

어떤 정보를 분석하려고 한다
가장 먼저 하여야 할 일이 무엇인가..
분석을 위하여 나름대로 로직이 서 있다
즉 주방에서 요리를 하려고 레시피를 다 정해 놓고
이제 재료가 들어오기를 기다린다, 재료가 있어야 이것도 만들고, 저것도 만들수 있으니까..
그러려면 당연히 선행하는 작업이 재료검수작업을 하여야 한다
사람 사는 세상과 똑같은 것이 프로그래밍이다
아니..똑같으니까..프로그래밍이 필요 한 것이다
그런데 실은 이런 검수작업을 한다는 것은 참으로 귀찮아하는 작업이다
준비작업과 일끝난후 뒷정리(디버깅)가 가장 귀찮음과 동시에 가장 중요한 것
실생활처럼 식자재검수하면서 질이 좀 떨어져도 술한번 접대받고 적절히
넘어가는 그런 매력(??)도 없다(앗..이런 말하면 안되지!!)
그냥 삽질을 하여야 하는 그런 과정이 검수과정이라고 할 수 있고
좋은 결과를 얻으려면 좋은 재료가 들어와야 한다

어떤 검수를 하여야 하나
검수 체크리스트가 있어야 한다..
위에서 중복되는 이야기지만 중복할만한 가치가 있는 이야기
1)테이블자체가 주어진 양식을 유지하고 있는가(휠드들)
2)열의 위치는 뒤바뀌지는 않았는가?
3)ID는 중복되는 것은 없나?
4)시작날짜와 종료날짜와 기간중 유효한 값이 있는가?
5)WBS코드는 유효하게 사용할수 있는 것인가?
6)작업명은 들어 있는가?
7)비용이라던가, 기타추가 정보는 있어도,없어도 상관없다
각각의 작업을 행방향으로 순환하면서 따지면서
자격미달 작업명은 모두 걷어내고 정상적인 작업명으로만 분석작업을 할까..
아니면 못하겠다고 버티고..모든 행을 정상적으로입력하라고 할까..
생각하면 할수록 다양하게 체크리스트가 만들어 질 것이다
너무 많이 체크하는 형식이 되어도 사용자가 더러워서 못쓰겠다고 할 것이고
적당한 선을 유지하여야 할 것이다
참 많은 갈등을 갖게 하는 부분 일 것이다
여기에서는 100개의 작업명을 넣었는데..몇개의 작업만 유효하다면
유효한 작업으로만 결과를 만들도록 친철함으로 해보자
이러면 어떤 사용자는 ..틀리면 틀린다고 이야기하고 고친후
다시 모든 작업명으로 하지..쓸데 없이 몇개 안되는 것만 결과를
만들고..보고, 다시만들게 하지..에잇..이라고 할수도 있고..
그러니 사용자의 입맛을 죄다 만족시키는 것은 불가능하다고
할 수 있으니, 여러분들의 다른 어떤 소루션도 어느 적정선을
찾는데 주력하는 것이 좋을 것이다..
백이면 백 모두 만족시키려면 스트레스받아 죽는다

검증된 테이블을 순환하면서
Task라는 크래스모듈을 사용하여 Task개체를 집합체에 보관하면 좋겠으나
집합체는 정렬등에서 별로 지능이 없다
물론 VB.Net의 집합체들은 별짓을 다 하지만
그래서 VSTO에서 사용된 집합체를 배열로 바꿔사용하도록 한다
실은 배열은 모든 떼거리정보처리의 원판이니까..
아무리 새로운 것이 나와도 배열만 자유로우면 천하무적이다

그리고 어떤 작업을 할때 이것, 저것 도움을 주는 함수나 프로시져가
필요하게 된다
이런 것을 흔히 Utilities함수들이라고 부르게 되고
이런것은 별도의 모듈에 관리하면 좋을 것이다
예를 들어서 WBS레벨의 깊이가 제일 깊은 것이 얼마인지 알 수없다
사용자가 입력 WBS코드를 읽어서 찾아내어야 할 것이다
제일 깊은 곳의 레벨이 있는 행이 곧 실제 작업행이 되는 것이니
참 중요한 작업일 것이다
이런 레벨을 찾아내는 일을 본래의 작업내에서 수행하려면 복잡해진다
그래서 이런 것을 별도로 함수를 만드는 것이 좋을 것이다
뭐..무지하게 자신만 알아보게 복잡하게 만들어도 누가 잡아가지는
않지만,,,한달 후에 스스로 딜다 보아도 알아 볼수 있게 하려면
분리하는 것이 좋은 습관인 것이다

'매개변수 테이블, WBS가 들어있는 열위치 Function getWBSLastLevel(rTbl As Range, iWBS_Col As Integer) As Integer Dim iLast As Integer Dim iTemp As Integer Dim sWBS As String Dim rRow As Range For Each rRow In rTbl.Rows sWBS = rRow.Cells(iWBS_Col).Value If sWBS <> "" Then iTemp = getLevelOfWBS(sWBS,".") If iLast < iTemp Then iLast = iTemp End If End If Next getWBSLastLevel = iLast End Function ' WBS코드값을 전달받아 계층레벨알아내기 Function getLevelOfWBS(ByVal sValue As String, sDelimiter As String) As Integer getLevelOfWBS = Len(sValue) - Len(Replace(sValue, sDelimiter, "")) End Function

WBS레벨을 사용하지 않으면 해당이 없는 것이지만, WBS코드를 사용한다면
WBS레벨의 가장 깊은 레벨을 알아내야
테이블의 각작업행을 순환하면서 유효한 실제 작업행을
판별하에 배열에 담을 수 있게 될 것이다

WBS 라벨을 1.1.1 이라고 입력하였다면 이것은 WBS레벨은
위의 getLevelOfWBS("1.1.1",".") 로 호출하면 결과값은 2이다
이렇게 하여 전체 작업의 WBS레벨을 알아 보면 가장 큰 값이 이 프로젝트의
실제작업레벨로 간주하겠다는 것
전체행을 순환하면서 가장 큰레벨값과 같은 것만 실제의 작업행이고
나머지는 작업행을 그룹핑하는 그룹명으로 하겠다는 것
이렇게 계층별 그룹핑하는 일은 이런 작업스케쥴뿐만이 아니라 모든 다른 일들에도
중요한 기능이니 잘 챙겨두시면 좋을 것이다
아래의 그림과 같이 사용자가 입력한 내용을 검증과정을 거쳐서
날짜를 계산하고 기간을 계산한후 각 작업내용을 배열에 담는 과정과
배열의 내용을 메시지박스에 풀어서 보고 확인하는 과정까지를 아래 화일에서
해본다



각 작업의 내용을 하나의 개체에 담고
이 개체를 배열에 담는 과정을 직접 하여 보시는 것이 좋습니다
그러면서 좀더 개선하여 보겠다는 생각을 갖으시면 만점!!

***[LOG-IN]***