'개~발/Powerbuilder'에 해당되는 글 39건

  1. 2009.04.28 Window의 키보드로 Scroll하기 by 민서정
  2. 2009.03.31 Power Builder 웹서비스 클라이언트 개발예 by 민서정
  3. 2009.03.30 RGB 추출유틸 by 민서정
  4. 2009.03.30 powerbuilder 도움말 by 민서정
  5. 2009.03.30 특정폴더 시간별 백업 및 파일씽크 맞추기 by 민서정
  6. 2009.03.30 system tray 예제 by 민서정
  7. 2009.03.13 DataWindow Title bar 고정시키기 by 민서정
  8. 2009.03.13 MDI에서 최소/최대/닫기 버튼을 사용못하게 by 민서정
  9. 2009.03.13 PowerBuilder 10 으로 Migration 하기 by 민서정
  10. 2009.03.06 DW의 내용을 Excel파일로 전환하기 by 민서정

Window message:
    WM_SCROLL      276    // Horizontal scroll
    WM_VSCROLL     277    // Vertical scroll

Parameters:
    SB_LINEUP      0      // Scrolls one line up.
    SB_LINELEFT    0
    SB_LINEDOWN    1      // Scrolls one line down.
    SB_LINERIGHT   1
    SB_PAGEUP      2      // Scrolls one page up.
    SB_PAGELEFT    2
    SB_PAGEDOWN    3      // Scrolls one page down.
    SB_PAGERIGHT   3
    SB_TOP         6      // Scrolls to the upper left.
    SB_LEFT        6
    SB_BOTTOM      7      // Scrolls to the lower right.
    SB_RIGHT       7
    SB_ENDSCROLL   8      // Ends scroll.
   
[powerscript]
//
//  Scroll Window one page down
//    WM_VSCROLL  = 277
//    SB_PAGEDOWN = 3
//
Send(Handle(this), 277, 3, 0)  // 277은 Vertical scroll,  276   Horizontal scroll , 3:pagedown


[윈도우 Key이벤트에 기술]
/* 윈도우 스크롤*/
choose case  key
 case KeyHome!
  send(handle(this),277,6,0)
 case KeyEnd!
  send(handle(this),277,7,0) 
 case KeyupArrow!
   send(handle(this),277,0,0)

 case  KeyDownArrow!
  send(handle(this),277,1,0)
 case  KeyPageUp!
  send(handle(this),277,2,0)
 case  KeyPageDown!
  send(handle(this),277,3,0)
end choose

 

Posted by 민서정
l
Posted by 민서정
l

RGB 추출유틸
Posted by 민서정
l

powerbuilder 도움말
Posted by 민서정
l

특정폴더 시간별 백업 및 파일씽크 맞추기
Posted by 민서정
l

system tray 예제
Posted by 민서정
l

*칼새*
2007.01.25 15:34:34 (*.147.61.114)
55
Window에 Title bar가 있듯이 DataWindow에도 Title bar가 있다.
DataWindow에서 Title bar를 사용하면 마우스로 DataWindow를 이동시킬 수 있게 된다.
하지만 DataWindow control에서 pbm_syscommand user event를 사용하면 DataWindow를 고정시킬 수 있다.

int a, b

a = message.wordparm

CHOOSE CASE a
CASE 61456, 61458
message.processed = true
message.returnvalue = 0
END CHOOSE

return

이렇게 pbm_syscommand에 script를 작성하면 마우스로 DataWindow를 이동시킬 수 없으면서 DataWindow에서 Title bar를 사용할 수 있다.
Posted by 민서정
l
*칼새*
MDI 시트에서 최소/최대/닫기 버튼을 사용할 수 없게 하려면 먼저 사용자 이벤트를 PBM_SYSCOMMAND로 해서 ue_syscommand라는 사용자 이벤트를 만듭니다.
그 이벤트에서 다음 코드를 사용하면 Minimize/Maximize/Close 버튼을 눌러서 해당 윈도우를 '최소/최대/닫기'하려는 동작은 취소됩니다.

IF message.wordparm = 61488 THEN // 최대화 버튼
message.processed = TRUE
message.returnvalue = 1
END IF
IF message.wordparm = 61472 THEN // 최소화 버튼
message.processed = TRUE
message.returnvalue = 1
END IF
IF message.wordparm = 61536 THEN // 닫기 버튼
message.processed = TRUE
message.returnvalue = 1
END IF
Posted by 민서정
l


PowerBuilder 10 으로 Migration 하기

 발췌 : http://eas.penta.co.kr/pbnews/0503/PB10Migration.htm

기존에 쓰던 파워빌더에서, OS 의 지원 및 DataBase의 지원여부 또는 기존에 쓰는 것보다 상위버전의 파워빌더에서 지원하는 기술을 쓰고 싶은 이유에서 Migration 을 하게 된다.

대체적으로 마이그레이션시 중요한 틀로 보는 것은 파워빌더 7 이전의 버전과 파워빌더 8 이후의 버전으로 나눠서 생각하게 된다.

 

1. 마이그레이션 하기 전에 고려해야 할 사항들

 

1) 예약어 처리

파워빌더 8.0 부터 exception handling을 위해 새로운 예약어들이 PowerScript 에 추가 되었다. 만약 현재 어플리케이션에서 (TRY, CATCH, FINALLY, THROW, and THROWS)과 같은 예약어를 사용했다면 , 그들의  이름을 미리 바꾸어서, 충돌이 나지 않는 이름을 주어야 한다. New dialog box 에 Tool tab page에 있는 Migration Assistant 을 실행해서 새로운 예약어 들의 사용된 위치를 알 수 있다.

 

2) Transport object 의 폐지

Transport object 와 그것과 관련된 properties 와 method들은 파워빌더 8.0 에서 쇠퇴 되었고, 파워빌더 9.0 이후에서는 더 이상 사용되지 않는다. 원래 이 객체는 PowerBuilder application의 분산을 위해 사용되었는데, 파워빌더의 버전이 올라가면서 분산을 위해 새로운 properties 와 methods 들이 추가되면서 다른 함수들에 분산되어 편입되었다. 새로 추가된 함수 및 이벤트 들을 알아보면 다음과 같다.

 

* Application object 에 ConnectionBegin , ConnectionEnd events 이벤트 추가

* Connection Object 에 RemoteStopConnection, RemoteStopListeningGetServerInfo 함수 추가

* proxy objects 위한 SetConnect 함수 추가

* Connection object 에 properties 에 ConnectString , Trace 추가

* ConnectionInfo structure

 

3) SystemError 이벤트의 변화

파워빌더 7.0 이하의 버전에서, error 또는 ExternalException event에 의해서 잡히지 않은 error 가 발생하면, applicatonSystemError event은 즉시 트리거 된다. 만약 SystemError event 와 관련이 있는 코드가 없다면 그 application 은 종료되어진다. 그렇지 않으면, SystemError event 가 수행된 다음에, error 가 발생되어진 code 에 위치에 control들이 리턴된다

파워빌더 8.0 이후의 버전에서는, exception handling mechanism 이나 Error 나 ExternalException event 에 의해 잡히지 않는 error가 발생 한다면, script 는 종료되고, 호출되어진 stack 이 풀린다. 만약 error 가 script에서 Triggerevent call 이 일어나면, script terminate가 호출되어지고, 호출되어진 stack 이 풀린다. 대부분의 경우, SystemError event 는 stack 이 비어지기 전까지 트리거 되어 지지 않는다. 만약 response window의 event 가 Error나 trigger 되어진 SystemError event 의 원인이 된다면 response window event까지 곧 완성한다. 이와 같은 행동에 변화때문에, error에 원인이 되는 문장의 code 는 SystemError event가  제거된 후에 실행되어 지지않고, 그것은 전에 실행되어진다.

이와 같은 변화는 이전 버전에서의 script 에 error가 발생한 control 들에 application 에 큰 영향을 준다. 이와 같은 Code 는 파워빌더 8.0 이나 그 이후에 작성되어진 것에 의존 된다. 전체 code에서 execution error가 발생 할 때, trigger 됨으로써 SystemError event를 try-catch에서 발생되는 error의 원인이 되는 방지하는 것에 의하여 잠재적인 error 들을 조정할 수 있다. 이것은 어떠한 uncaught exception도 SystemError event를 통해서 조정할 수 있고, 코드에 받아들일 수 있다. SystemError event 가 수행되어진 후에 계속 어플리케이션이 실행 되도록 허용할 수 없다. SystemError event 는 어플리케이션을 멈추고 말끔하게 한다.

 

4) IsValid 함수의 변화

파워빌더 7.0 이하 버전에서는, invalid object 에 IsValid 넘겨 주어서 system error가 발생되었으나, 파워빌더 8.0 이상의 버전에서는, Any type의 argument가넘겨지면 Power Object로 바뀌질 수 없고 false 리턴 한다.

 

5) Nested reports 안의 DataWindow objects 들의 이름을 바꿔라.

PowerBuilder 7 이후 버전에서는, DataWindow object 에 모든 object 들은 반드시 이름을 가지고 있어야 하며, Migration 동안 이름을 가지고 있지 않은 object 들은 user-definable prefix settings 에 되어있는 것을 기준으로 이름이 지어지고, 보통 dw_1, dw_2 등등으로 되어 진다. 이러한 이름들은, DataWindow painter 에 있는 Design>Options 에 있는 Prefixes Tab 에 설정되어 있는 것으로 나타내어진다. 이름은 순차적으로 지어지고, 따라서 object 는 DataWindow object 에 다른 object 에 의해 이미 지어져 있는 것들이다. 하지만, 이것은 뜻하지 않는 행동의 이유가 된다. 예를 들어, Dw_2 와 같이 이미 다른 DataWindow object에 사용 되어지고 있는 것들은 Sharedata, GetChild, Retrieve 함수 등 에서, 다른 DataWindow object를 가르키게 된다. 이 문제를 해결하기위해서, 마이그레이션을 하기 전에 DataWindow painter 에 있는 Design>Options 선택하고, Prefixes tab에 있는 DataWindow object prefix 되어진 것을 임시적으로 다른 것으로  바꾸면 된다. DataWindow object 들은 migrate 수행 후에 prefix 다시 바꾸면 된다.

 

6) window의 Icons은 반드시 할당되어야 한다.

window 포함한 application 에서 할당한 icon은 더 이상 window 에 상속 받지 않는다. application icon 을 사용하려면, 반드시 새로운 AppIcon을 사용해서 migration 후에 window에서 그것을 명시 하면 된다.

 

7) ListView , TreeView controls events 의 변화

PowerBuilder 7 이후의 버전에서는 Microsoft의 ListViewTreeView control 들을 사용한다. 그로 인해, 몇 몇의 event들의 재배치가 필요로 하다. mouse actions을 수행할 때, 이 전 버전과는 다른 방식으로 명령을 해야 한다.

 

8) DBCS 관련 변화

DBCS 어플리케이션은 DBCS-compatible locale을 포함하는 운영체제에서는 성공적으로 바꿀 수 있다. 그러나 English locale이 작동하는 운영체제에서는 object의 폰트속성이 DBCS문자를 지원하지 않을 경우, DBCS문자들이 깨져서 나타나게 된다. 이 문제를 해결하기 위해서는 변환 후에 그 폰트를 Tahoma로 바꾸어 줘야한다.

 

9) Unicode 관련 변화

파워빌더 10은 유니코드를 사용할 수 있게 되었다. 파워빌더 10에서 PBL의 소스코드는 ‘UTF-16LE’ 인코딩 되어있다. UTF-16LE는 little-endian format 안의 바이트 순서처럼 UTF-16 code unit 순서가 나열된 Unicode encoding scheme 이다. 또한, multiple-byte numerical values는 the least significant byte first와 함께 저장되어져 있다.

 파워빌더 이전버전에서 마이그레이션된 PBL은 ANSI 나 DBCS의 소스코드를 포함하고 있다. 어플리케이션을 파워빌더 10버전으로 바꿀 때는 우선 이전버전으로 되어있는 각 PBL을 파워빌더10으로 마이그레이션 한 후, ANSI나 DBCS의 소스코드를 유니코드로 전환시키고, ‘full build’ 실행시킨다.

 

2. 파워빌더 7 버전 이하 버전으로부터 의 Migration

먼저, 파워빌더 7 버전 이하 에서 (pbl 단위로 시작되었던 의 프로그램) 파워빌더 8.0 이상으로 마이그레이션 할 경우의 주의 사항 및 방법에 대하여 알아보자.

 

이전 버전의 파워빌더를 사용하여 만들어진 PBL 들은, PowerBuilder 9.0으로 migrate 해야 한다. 항상 migrate 하기 전에 PBL 들을 항상 Back up 해야 한다. PowerBuilder 7 이하의 버전으로 만들어진 어플리케이션에서 workspace Target을 추가하기 위해서는 Target page of the New dialog box의 Existing Application Target wizard를 사용한다.

마법사를 끝낸 후에, Migrate Application dialog box 가 열려지고, application 을 선택해서, PowerBuilder 9.0로 migrate 한다

개발의 시작점이 Workspace 올라갔으므로, Workspace 만들어야 한다.

의 시작점이 Workspace 올라갔으므로, Workspace 만들어야 한다.

migration 할 PBL 에 문법적으로 변화가 생기는 것이 어떠한 것인지 미리 알아보기 위해서 메뉴바 Files>New 에서 Tool 탭에 Migration Assistant를 실행시켜보도록 하자.

Migration Assistant 실행시키면 다음과 같은 화면을 볼 수 있을 것이다. 해당 PBL에 Obsolete Syntax 미리 조사하는 Obsolete Syntax 선택하거나,  PowerScript 에서 새로 생겨난 것이나, 사라진 것이나, 추후의 파워빌더의 버전에서는 지원되지 않을 함수나 이벤트들에 대한 것을 조사하려면, PowerScript New, Obsolete or Removed Syntax, .text 파일로 되어진 결과를 조사하려면 Syntax in Custom File 을 선택하면 된다. 대부분 여기에서는 PowerScript New, Obsolete or Removed Syntax를 선택한다.

 

어떠한 버전에 대해서 체크 할 것인지 체크한다. 모든 버전을 체크하도록 하자.

체크할 PBL 을 선택한다. 선택하면, 오른쪽 부분에 선택한 pbl 이 표시된다.

PBL 을 선택한 후 Next 버튼을 눌러서 다음단계로 가고, Finish 누르면 파워빌더 자체적으로 조사를 하게 되고, 조사한 Report 결과를 다음과 같이 출력한다.

문법적으로 틀릴 것이 없다면 마이그레이션을 진행하도록 하고, 발견 된 경우에는 마이그레이션 하기 전의 파워빌더에서 해당 스크립트를 수정한 후, 마이그레이션을 진행하도록 하자. Workspace 는 기존에 생성했으니, PBL 을 붙이기 위해서는 Target 이 필요로 하다. 메뉴바 Files>New 에서 Target 탭에서 Existing Application 을 선택하자.

Workspace 에 붙이고자 하는 Pbl 에 Application Object 선택하자.

Library Search Path 설정 할 수 있다. 이번 예제는 pbl 이 하나이므로, Next 버튼을 누르자.

Workspace 에 PBL 을 붙이기 위해서는 Target 이 필요로 하다. Target 이 생성되는 위치 및 이름을 설정할 수 있다.

마이그레이션 Pbl 의 리스트 이다. 만약 하나의 Target 에 더 많은 pbl마이그레이션 하고 싶다면, Browse 버튼을 선택해서, 원하는 pbl 들을 모두 선택하고 OK 버튼을 클릭한다.

마이그레이션이 성공적으로 마쳐졌으며, System Tree 창에 Workspace, Target 이 생성되었고, 그 밑에 pbl 이 붙게 되었다.

 

3. 파워빌더 8 이상의 버전으로부터 의 Migration

파워빌더 8 이상에서 (Workspace 와 Target 이 존재하는 경우) 파워빌더 10 마이그레이션 할 경우를 알아보자.

파워빌더 8 이상의 버전으로 작성된 Workspace 열면 다음과 같은 화면을 보게 된다.

기존의 Target 안에 있는 pbl 들은 자동으로 경로를 가지고 와서 연결이 되어있는데 , 이것 이외에, Target에 쓰이는 다른 library 가 있다면, Browse 버튼을 눌러서 그 library 가 존재하는 경로로 찾아가서 선택하면 된다.

 

하단부의 DBCS(Double-Byte Charter Set)를 Check 하는 옵션은 String 조작에 관련된 함수, 예를 들어, 파워빌더 9 이하의 버전에서는 Len, Mid, Pos 같은 String 에서의 Byte 형의 숫자를 Return 되고, Argument Byte 형 숫자가 사용되어 졌는데, 파워빌더 10 부터는 Character 형의 숫자로 모두 바뀌게 되었다. 이 체크를 하게되면 자동으로 변환이 되어 지게 되는 것이다. 그러나, 파워빌더가 SBCS(Single-Byte Character Set) 환경에서 동작한다면, 이 체크를 하지 말아야 한다.

원하는 것을 선택하고 OK 버튼을 누르면 변환과정이 자동으로 진행되어지게 된다.

위의 그림과 같이 Output 창의 제일 하단부에는  ‘ Finished Migrate of target window_type’ 이라고 나타나고, Error 가 발생하지 않았다.

이것은 성공적으로 Migration 이 이루어 진 것이다.

 

4. Migration 시 발생되는 문제점

마이그레이션을 할 때, 여러분들이 당면할 수 있는 에러에 대하여 살펴보고,  그에 대한 해결책을 알아보자.

 

1) 마이그레이션시, 접하게 되는 문구

 

Error

-> 마이그레이션을 할 때, Error 가 발생된 경우이다. Error 가 발생되는 이유는 크게, 마이그레이션 도중에 내부적으로 소스가 깨져서 발생되는 문제와 이전 버전에서는 문제 없이 넘어 갔던, 문제 있던 구문들이 파워빌더 버전이 올라가면서Complier 가 강화되면서, 구문 에러를 내는 경우 이렇게 두 가지 경우이다.

 

Warning

-> 경고는 무시해도 좋으나, 가급적이면 고쳐주는 것이 좋다.

 

Information

-> 대부분 동일한 이름의 객체가 중복해서 존재할 때 발생한다.

 

Obsolete

-> 이 메시지는 추후의 파워빌더의 버전에서는 지원되지 않을 함수나 이벤트들에 대한 경고 메시지이다. 이번 버전까지는 그냥 넘어가도 상관없지만, 다음버전으로 마이그레이션을 하면, Error 뜨게 될 것이다. Obsolete 메시지 뒤에 어떠한 함수로 바꾸면 좋을 것이라는 말이 나오므로, 나온 대로 이행하는게 좋다.

 

2) 에러 메시지의 의미

마이그레이션 과정에서 에러메세지가 나타났을 때, 당황해 할 필요 없다. 이런 에러메세지의 의미를 몇 가지 알아보도록 하자.

 

[mig.pbl(w_frame).dw_con.11: Error C0031: Syntax error]

 

위의 에러 메시지를 분석하면 mig.pbl 파일의 w_frame 이라는 윈도우 오브젝트의 dw_con 의 선언부의 11번째 줄에 에러코드가 C0031인 Syntax error가 발생했다. 라는 뜻이다.

'C0031' 은 'Syntax error' 의미하는 에러코드 이며, 여기서 에러가 발생되는 w_frame 윈도우를 Edit Source 보면 'type dw_con from datawindow ...'

이런 형태의 dw_con 선언부가 있는데, 그 중 11번째 줄에서 오류가 발생한 것이다.

 

Warning : Instance variables of local structure type ('ws_customer') will be implicitly private in the next release

 

Instance로 선언 시 Default가 Public으로 선언이 된다. 해당 Structure는 해당 Object에서만 사용할 것 이니 Private로 선언해서 사용하라는 메시지 이다.

선언시에 Private를 붙여주면 문제가 해결 됨으로, 선언 부분을 찾아서 앞에 private를 선언 하면 된다.

 

3) 많이 발생되는 에러

 

) Unknown function name , Undefine Variable name ,  Illegal data type

PBL 은 오브젝트의 소스코드와 컴파일된 바이너리 코드로 구성이 된다. 마이그레이션 시에 소스가 내부적으로 깨져서 2개의 파일 정보가 일치 하지 않아서 해당 함수 또는 변수, 데이터 타입을 인식하지 못하는 경우이다. 이러한 경우는 해당 앞이나 뒤에 space bar 한 칸(공란)을 주고 다시 저장하면 된다.

 

) EditMask Contol

Unclosed quoted string 이란 메시지와 Syntax error 메시지가 출력 되게 된다.

일반적으로 파워빌더 7 버전 미만에서 파워빌더 8 이상으로 마이그레이션 할 때, 가장 많이 발생하는 문제는 EditMask Control 이 깨져서 발생된다.

윈도우에서 다음와 같은 에러 메시지가 발생하는 경우 아래에서 제시한 방법대로 고치면 문제가 해결된다.

 

에러문구에서 제시하는 오브젝트를 System Tree 상황에서 해당 객체에서 오른쪽 마우스를 하고, Edit Source 보면, 아래의 그림과 같이 EditMask의 속성 중DisplayData =”? (?)로 표시되는 부분이 있다.

? 특수문자로 인식하여 ?뒤의 소스가 다 사라짐. 이전 버전의 소스에서 해당 부분의 뒤에 붙이고, DisplayData=”” 형태로 수정한 후 저장을 하면, 해당 문제가 해결된다.

 

 

) SetNull 관련 에러

The argument to SetNull cannot be an autoinstantiate or structure

위와 같은 메시지를 나타낸다.

파워빌더 6.0 이상부터 는 배열을 초기화 할 때 setnull()을 사용할 수 없다.

배열을 초기화 시키기 위해서는

string sNewArray[], sNullArray[]

sNewArray = sNullArray

위와 같이 아무런 값도 갖질 않는 변수를 대입해서 초기화하면 된다.

 

) Any Type

파워빌더 9.0 부터는 파워오브젝트의 프로퍼티나 함수를 Any type변수에 사용할 수 없다. 따라서 기존에 만약 변수를 Any 할당 했다면, 해당 오브젝트로 변수를 주면 된다.

)

any ga_btn  으로 선언 한 것을 button  ga_btn 바꾸면 된다.

 

) Size Change 문제

윈도우의 크기는 일관성있는 개발과 다른 디스플레이 설정을 가진 시스템을 지원하기 위해 계산되어 변하게 된다 특히, 파워빌더 5나 6 버전에서 파워빌더 9 이나 파워빌더 10으로 올라가게 될 때, 크기의 변화는 고려해야 할 사항 중 하나이다. 마이그레이션을 하면, 화면의 사이즈가 변화가 일어나는 경우가 있다. 폰트 크기 및 Window Control Object 의 크기, Window 의 크기 , Data Object 의 크기등이 변하는 경우가 있다. 이유는 파워빌더에서의 모든 객체들은 OS 에 의존적인 크기를 가지고 있는데, OS 자체의 환경의 주종을 이루는 XP 나 2000 으로 바꿔지면서 나타나게 된다. 그중 윈도우의 크기는 타이틀 바, 스크롤 바, 보더와 같은 다양한 플렛폼들의 구성요소들로 나타나게 된다. 예를 들면, 윈도우 XP 스타일로 보여주는 윈도우 XP 기반에서의 active 타이틀바와 inactive 타이틀바 크기는 25이지만, 윈도우 클래식 스타일의 XP 와 2000 기반에서의 타이틀 바 크기는 18이다. 사용자는 이 설정 값을 윈도우 컨트롤 패널에 있는 프러퍼티 다이얼로그 창의 탭 페이지에서 조정할 수 있다. 또한,  Data Object 같은 경우는 아래의 그림 7 과 같이 마이그레이션을 하기 전에 Propeties 창에서 Units Centimeter 해놓고 한다면, 마이그레이션 이후의 사이즈의 변화가 일어 나지 않을 것이다.

) Duplicate variable

해당 변수를 여러 번 선언해서 발생되는 문제로,  파워빌더 8.0에서는 발생하지 않았지만, Compiler 의 강화로 Error 가 발생되며, Edit Source로 해당 오브젝트를 수정한 후 저장하면 된다.

 

4) 그 밖의 주의 사항

) 복잡한 Stored Procedure

많은 양의 Query를 포함하는 Stored Procedure를 사용했을 경우 ‘ORA-00936: 식이 없습니다’ 또는 ‘SQL 명령어가 불완전 합니다’ 등의 에러가 발생된다.

파워빌더 10 버전이 PBDBMS를 이용한 SQL Query문을 최대 60라인 까지만 인식하는 문제로써, 해당 오류가 발생하는 SQL 문을 60라인 이내로 줄여서 해결해야 한다. 한 라인에 입력 가능한 컬럼은 250 까지이다.

 

) Return expression in subroutine

 

subrutine으로 선언 하고 return value를 준 곳이 있다라는 것이다. 해당 오브젝트를 source edit 열고 해당 함수를 주석 처리한 후, 페인터로 들어가 고치시면 된다.

 

) scanning object source entry: w_test

w_test 객체를 찾을 수 없다는 에러다. 만약 해당 오브젝트가 있다면 Regenerate 하고, 다시 저장하면 된다.

 

) Internal overflow, script is too large

해당 메시지는 스크립트의 사이즈가 클 때 발생을 하는 메시지이다.

파워빌더 5.0 이하의 프로그램에서는 컴파일러 상에서 잡지 못하는 것인데, 파워빌더 6.0 이상으로 마이그레이션 할 때 너무 비대해져서 문제가 되는 것이다.

이러한 경우는 해당 스크립트를 따로 Function으로 빼시거나 상속을 받아 사용해야한다.

 

) conversion failed. Probable library file I/O error

 

해당 PBL 파일을 Optimize 후 다시 Full Build 한 후, 해당 PBL 파일이 위치한 디스크 영역에 오류가 또는 해당 PBL이 읽기 전용 파일인지 확인하면 된다.

이전 소스를 Export 해서 워드패드에서 보면 특수문자가 들어가있는 것을 확인할수 있을 것이다. 특수문자뒤의 Source는 다 없어지는 현상이 나타난다. 이 외에도 특수문자 중 @ 만나도 같은 현상이 나타나기 때문에, 원본 Source를 수정 후 다시 마이그레이션 작업해야한다. 만약 그 후에도 문제가 계속 발생이 되면, 물리적인 HDD 디스크의 문제일 가능성이 높으므로, 윈도우 디스크검사를 수행해 문제가 없는지 확인하면 된다.

 

) Unresolved resource 'c:\pic\bmp\exit.bmp' Referenced from object 'w_exit'

 

위의 위치경로에 해당 그림이 존재 하지 않는 경우로써, PBR(PowerBuilder Resource File)에는 이러한 경로를 주었을 때 발생됩니다. 해당 경로에 맞는 그림을 넣던가, PBR의 내용을 바꿔야 한다.

 

) SQLSTATE = 37000

SQL 컬럼갯수가 많은 경우(약 40개 이상)에 프로그램 개발 및 실행시에 모두 에러가 발생한다. 이러한 경우는 Database 연결 시 DisableBind = 1 옵션을 추가하면된다.

 

)select error: ora-00907: 누락된 우괄호 에러

주석이 문제를 발생 시키는 것이며, 주석 내에서도 ":" 이 문제이다.

예를 들어 주석이 다음과 같다고 할 때

aa : bbb

":" 뒤에 있는 "bbb" Retrieval Argument로 인식하는 것이 문제이다.

 

따라서 주석에서 ":" 을 다른 문자로 바꾸면 된다.

 


Posted by 민서정
l

이것은 http://blog.naver.com/mojirhi/150002732458 모지리님의 블로그를 발췌한 내용입니다.
너무 잘 만드신 것 같습니다. 부럽습니다.


소스: http://blog.naver.com/mojirhi/150002732458 (모지리님)

argument는 2가지나 3가지를 받도록 했습니다.
//my_excel.of_excel(DW or DS,ib_detailonly,ib_saveobjectinfo)

1.
첫번째는 Excel로 전환할 개체인데 Powerobject로 변경하여
         Datawiindowsk datastore 아무거나 입력받을 수 있도록 하였습니다.
두번째는 ib_detailonly로 grid와 closstab에서만 효고가 있으며 true일때는
         detail만 grid 형태로 출력하며 숫자형 문자열을 정확히 문자열로 읽어줍니다.
세번째는 ib_saveobjectinfo로 생략가능하며 일반적으로는 사용하지 않습니다.
         개발자를 위해서  dw나 ds의 object들의 각종 속성을 excel로 출력해줍니다.

 

2.ib_detailonly가 false이면 saveasascii를 사용합니다.
  ib_detailonly가 True이면 Processing에 따라서
  '0'(=form/tabular/group/n-up)과 '2'(=label)은 무조건 SaveAsAscii를 사용하고
  '1'(=grid)과 '4'(=closstab)은 of_savedetailonly방식을 사용합니다.
  '5'(composite)는 SaveAsAscii방식이 안되므로 모둔 report를 Grid형태로 변경하여 하나의 Excel파일에 Report별로 Sheet를
     구분하여 출력합니다.

3. 입력object를 powerobject로 변경하여 관련함수를 공통함수로 재정의하여 사용합니다.
   of_describe(),of_modify(),of_getitemstring(),of_getitemnumber(),of_getchild()등입니다.

4.QueryTable관련 부분은 잘 확인해보시기 바라며 column정보는 of_analyze에서 설정합니다.

 


/* 사용방법 */

my_n_excel my_excel
my_excel = create my_n_excel
my_excel.of_excel(dw_2,false)


/* 엑셀 Userobject*/
/* 아래소스 import 하면 됨*/


$PBExportHeader$my_n_excel.sru
$PBExportComments$Excel 저장 서비스
forward
global type my_n_excel from nonvisualobject
end type
end forward

global type my_n_excel from nonvisualobject
end type
global my_n_excel my_n_excel

type variables
protected:
datastore       ids_excel           // display값을 임시 저장하기 위한 것.
datastore       ids_object          // dwo 정보를 정리하기 위한 것
unsignedinteger ii_excelcol = 40    // excel의 열 제한 (255이하)
unsignedinteger ii_excelrow = 65535 // excel의 행 제한 (65535이하)
unsignedinteger ii_titlerow = 1     // header부위의 행 (확장예비용)
unsignedinteger ii_celllen  = 255   // excel의 cell값 길이 Max제한
boolean  ib_detailonly =True        // False는 saveasascii를 사용
                                    // Grid, Crosstab 에서만 효과가 있음.
boolean  ib_saveobjectinfo = False  // object 정보를 저장할 지
boolean  ib_composite = False       // Composite인지
            
//*************************************************************
powerobject     ipo_source          // Excel로 전환할 개체
object          ipo_sourcetype      // Datawindow!, Datastore!, Datawindowchild! ,,,
string          is_processing       // ipo_source의 processing
long            il_rowcount         // 전환할 row 수
datawindow      idw_source          // DataWindow용
datastore       ids_source          // DataStore용
datawindowchild idc_source          // DataWindowChild용
datawindowchild idc_report          // Composite의 Report용         
string          is_detail[]         // detail밴드의 column, compute 개체이름
string          is_objtype[]        // is_detail의 objtype
string          is_label[]          // is_detail의 Label
string          is_coltype[]        // is_detail의 coltype
long            il_objx[]           // is_detail의 x좌표

end variables

forward prototypes
public function string of_describe (string as_exp)
public function string of_modify (string as_exp)
public function integer of_string2array (string as_source, string as_separator, ref string as_result[])
public function string of_replaceall (string as_source, string as_before, string as_after)
public function string of_replaceall (string as_source, string as_before, string as_after, boolean ab_matchcase)
public function integer of_analyze ()
public function integer of_saveasascii ()
public function string of_getitemstring (long al_row, string as_colname)
public function string of_getitemnumber (long al_row, string as_colname)
public function integer of_saveinformation ()
public function integer of_savecomposite ()
public function integer of_savedetailonly ()
public function string of_datacopy ()
public function integer of_getchild (string as_report, ref datawindowchild adc_source)
public function long of_writetext (string as_string, string as_filepath)
public function integer of_createdwo (ref datastore ads_source, integer ai_col, boolean ab_header)
public function integer of_excel (powerobject apo_source, boolean ab_detailonly)
public function integer of_excel (powerobject apo_source, boolean ab_detailonly, boolean ab_saveobjectinfo)
end prototypes

public function string of_describe (string as_exp);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_describe
//
// DESCRIPTION : idw_source, ids_source, idc_surce, idc_report에 대하여
//               Describe함수를 공용으로 사용할 수 있도록 함.
//
// RETURN  : String
//               성공 - as_exp의 결과
//               실패 - '!'
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
// as_exp                describe()에 전달할 내용 
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

if ib_composite then
 return idc_report.describe(as_exp)
else
 Choose Case ipo_sourcetype
  Case DataWindow!
   Return idw_source.describe(as_exp)
  Case DataStore!
   Return ids_source.describe(as_exp)
  Case DataWindowChild!
   Return idc_source.describe(as_exp)
  Case Else
   Return "!"
 End Choose
end if

end function

public function string of_modify (string as_exp);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_modify
//
// DESCRIPTION : idw_source, ids_source, idc_surce, idc_report에 대하여
//               Modify함수를 공용으로 사용할 수 있도록 함.
//
// RETURN  : String
//               성공 - as_exp의 결과
//               실패 - '!'
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
// as_exp                Modify()에 전달할 내용 
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

if ib_composite then
 return idc_report.modify(as_exp)
else
 Choose Case ipo_sourcetype
  Case DataWindow!
   Return idw_source.modify(as_exp)
  Case DataStore!
   Return ids_source.modify(as_exp)
  Case DataWindowChild!
   Return idc_source.modify(as_exp)
  Case Else
   Return "!"
 End Choose 
end if

end function

public function integer of_string2array (string as_source, string as_separator, ref string as_result[]);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_string2array
//
// DESCRIPTION : 주어진 문자열을 특정 구분자(예, 탭)로 구분하여
//               배열에 저장하는 함수
//
// RETURN  : Integer
//
// ARGUMENTS         DESCRIPTION
// ------------------------------------------------------------------------
// as_source       string soruce_string
// as_separator    string separate_charactor
// as_result[]     string array result_saved
//
///////////////////////////////////////////////////////////////////////////////
//                 mojirhi @ gmail . com
///////////////////////////////////////////////////////////////////////////////

string ret[]
integer li_pos, i, li_nextpos, li_len

// Argument 확인
IF len(as_source) = 0 or isnull(as_source) then return -1
IF len(as_separator) = 0 or isnull(as_source) then as_separator = '~t'
IF isnull(as_result) then return -1

as_result = ret //결과배열 초기화
li_len = len(as_separator) - 1

//li_pos = 1
do while(true)
 i++
 li_pos = li_nextpos + 1
 li_nextpos = pos(as_source, as_separator, li_pos)
 
 if li_nextpos > 0 then
  if i = 1 then //맨 처음이면
   as_result[i] = mid(as_source, li_pos, li_nextpos - li_pos)
  else //중간부분
   as_result[i] = mid(as_source, li_pos + li_len, li_nextpos - li_pos - li_len)
  end if
 else //맨 끝이면
  as_result[i] = mid(as_source, li_pos + li_len, len(as_source))
  exit
 end if
loop

return 1

end function

public function string of_replaceall (string as_source, string as_before, string as_after);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_replaceall
//
// DESCRIPTION : 지정된 문자열을 source에서 모두 찾아 바꾸기 함.
//               (ib_matchcase를 항상 False로 함.)
//
// RETURN  : String
//               바꾸기 된 문자열
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
// as_source            전환할 대상 문자열 (~에서)
// as_before            전환전 문자열(~를)
// as_after             전환후 문자열(~으로)
//
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

return of_replaceall(as_source, as_before, as_after, False)
end function

public function string of_replaceall (string as_source, string as_before, string as_after, boolean ab_matchcase);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_replaceall
//
// DESCRIPTION : 지정된 문자열을 source에서 모두 찾아 바꾸기 함.
//
// RETURN  : String
//               바꾸기 된 문자열
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
// as_source            전환할 대상 문자열 (~에서)
// as_before            전환전 문자열(~를)
// as_after             전환후 문자열(~으로)
// ab_matchcase         대/소문자 구별(True이면 구별함)
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

long ll_pos

if isnull(ab_matchcase) then ab_matchcase = False

if ab_matchcase then
 ll_pos = posW(as_source, as_before)
 do while ll_pos > 0
  //as_Source = Replace(as_Source, ll_Start, ll_OldLen, as_New)
  as_source = replaceW(as_source, ll_pos, len(as_before), as_after)
  ll_pos = posW(as_source, as_before)
 loop
else
 ll_pos = posW(upper(as_source), upper(as_before))
 do while ll_pos > 0
  as_source = replaceW(as_source, ll_pos, len(as_before), as_after)
  ll_pos = posW(upper(as_source), upper(as_before))
 loop 
end if

return as_source
end function

public function integer of_analyze ();///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_analyze
//
// DESCRIPTION : idw_source, ids_source, idc_source, idc_report에 대하여
//               DWObject들의 정보를 수집한다.
//               결과는 is_detail[],  is_label[], is_objtype[],
//               is_coltype[], il_objx[] 에 남긴다.
//
// RETURN  : Integer
//               1 = 성공, -1 = 실패
//
// ARGUMENTS         DESCRIPTION
// ------------------------------------------------------------------------
//   None
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

string ls_objects, ls_object[], ls_labelx[], ls_null[]
string ls_objname, ls_band, ls_type, ls_pos, ls_label, ls_coltype
long   i, ll_pos, ll_row, ll_rowcount, ll_null[]

// 결과배열을 초기화 한다.
is_detail = ls_null[];    is_objtype = ls_null
is_label  = ls_null[];    is_coltype = ls_null
il_objx   = ll_null[]

//-----------------------------------------------------------------------------
// 데이터윈도의 모든 오브젝트를 읽어와서 배열에 담는다.
//-----------------------------------------------------------------------------
ls_objects = of_describe('Datawindow.objects' )
of_string2array(ls_objects, '~t', ls_object)

//-----------------------------------------------------------------------------
// datastore를 이용하여 모든 control의 기본정보를 가져오고
// column의 배열순서를 정하고 Header Text를 가져오도록 한다.
//-----------------------------------------------------------------------------
ids_object.reset()

//개발용 출력을 위해서 Label을 설정함.
ids_object.modify('C1_t.text = "Object_Name"')
ids_object.modify('C2_t.text = "V"')
ids_object.modify('C3_t.text = "Band"')
ids_object.modify('C4_t.text = "Obj_Type"')
ids_object.modify('C5_t.text = "Label"')
ids_object.modify('C6_t.text = "Col_Type"')
ids_object.modify('C7_t.text = "Text"')
ids_object.modify('C8_t.text = "X"')
ids_object.modify('C9_t.text = "Width"')
ids_object.modify('C10_t.text = "X2"')
ids_object.modify('C11_t.text = "Y"')
ids_object.modify('C12_t.text = "Height"')
ids_object.modify('C13_t.text = "Y2"')
ids_object.modify('C14_t.text = "Border"')
ids_object.modify('C15_t.text = "Font.Weight"')
ids_object.modify('C16_t.text = "Color"')
ids_object.modify('C17_t.text = "Bg_Color"')

For i = 1 to upperbound(ls_object)
 ls_objname = ls_object[i]
 ids_object.InsertRow(0)
 ids_object.SetItem(i , 'C1' , ls_objname) // object name
 ids_object.SetItem(i , 'C2' , upper(of_describe( ls_objname + '.visible' ))) // True = '1'
 ls_band = upper(of_describe( ls_objname + '.band' ))
  ids_object.SetItem(i , 'C3' , ls_band) // 'DETAIL', 'HEADER' ,,,
 ls_type = upper(of_describe( ls_objname + ".type" ))
  ids_object.SetItem(i , 'C4' , ls_type) // 'COLUMN', 'TEXT' ,,,
 if ls_type = 'COLUMN' or ls_type = 'COMPUTE' then
  ls_label = of_describe(ls_objname + '_t.text')
   ids_object.SetItem(i , 'C5' , ls_label) // Label 없으면 '!'
  ls_coltype = of_describe(ls_objname + '.coltype')
   ids_object.SetItem(i , 'C6' , ls_coltype) // coltype
 end if
 if ls_type = 'TEXT' then
  ids_object.SetItem(i , 'C7' , of_describe( ls_objname + '.text' )) // Label의 내용
 end if
 ll_pos = integer(of_describe( ls_objname + ".x" ))
  //column의 x값이 32766이상은 음수로 나올때의 에러 정정
  IF ll_pos < 0 then ll_pos += 65536
  ls_pos = right('000000' + string(ll_pos),6)
  ids_object.SetItem(i , 'C8' , ls_pos) // X position
 ids_object.SetItem(i , 'C9' , of_describe( ls_objname + '.width' )) // 너비
 ids_object.SetItem(i , 'C10' , string(ll_pos + long(of_describe( ls_objname + '.width' )))) // X2
 ids_object.SetItem(i , 'C11' , right('000000' + (of_describe( ls_objname + ".y" )),6)) // Y Pisition
 ids_object.SetItem(i , 'C12' , of_describe( ls_objname + '.height' )) // 높이
 ids_object.SetItem(i , 'C13' , string(long(of_describe( ls_objname + ".y" )) + long(of_describe( ls_objname + '.height' )))) // Y2
 ids_object.SetItem(i , 'C14' , of_describe( ls_objname + '.border' )) // 테두리
 ids_object.SetItem(i , 'C15' , of_describe( ls_objname + '.font.weight' )) // 굵게 보통-400, 굵게 700
 ids_object.SetItem(i , 'C16' , of_describe( ls_objname + '.color' ))   // 글자색
 ids_object.SetItem(i , 'C17' , of_describe( ls_objname + '.background.color' ))   // 배경색
Next

//-----------------------------------------------------------------------------
// Header Text가 '_t'로 되어 있지 않은 것을 x좌표로 재확인
// Visible='1', label ='' 것을 모은다.
//-----------------------------------------------------------------------------
ls_object = ls_null //배열 초기화
ids_object.setfilter('C2="1" and C5="!"')
ids_object.filter()
if ids_object.rowcount() > 0 then
 for i = 1 to ids_object.rowcount()
  ls_object[i] = ids_object.getitemstring(i, 'C1') // object.name
  ls_labelx[i] = ids_object.getitemstring(i, 'C8') // object.x
 next
end if

ids_object.setfilter('')   // filter제거
ids_object.filter()
ids_object.setsort('C9 D') // header중에서 아래쪽에 있는 것을 우선 찾기 위해.
ids_object.sort()

ll_rowcount = ids_object.rowcount()
if upperbound(ls_object) > 0 then
 for i = 1 to upperbound(ls_object)
  ls_label = ''
  ll_row = ids_object.find('C3 > "HEAD" and C4="TEXT" and C8="' + ls_labelx[i] + '"', 1, ll_rowcount)
  
  if ll_row > 0 then
   ls_label = ids_object.getitemstring(ll_row, 'C7')
   ll_row = ids_object.find('C1="' + ls_object[i] + '"', 1, ll_rowcount)
   ids_object.setitem(ll_row, 'C5', ls_label)
  end if
 next
end if

//-----------------------------------------------------------------------------
// detail밴드에 있는 것을 출력순서로 sort한다.
//-----------------------------------------------------------------------------
ids_object.setfilter('C2="1" and C3="DETAIL" and (C4="COLUMN" or C4="COMPUTE") ')
ids_object.filter()
if is_processing = '2' or is_processing = '4' then
 // 출력순서를 'x'좌표를 기준으로 순서대로 출력(왼쪽 순서대로)
 ids_object.SetSort('C8 A')
else
 // 출력순서를 'y'좌표우선 'x'좌표차선으로 출력(위쪽 왼쪽 순서대로)
 ids_object.setSort('C11 A, C8 A')
end if
ids_object.Sort()

for i = 1 to ids_object.rowcount()
 is_detail[i]  = ids_object.getitemstring(i, 'C1')
 is_objtype[i] = ids_object.getitemstring(i, 'C4')
 is_label[i]   = ids_object.getitemstring(i, 'C5')
 is_coltype[i] = ids_object.getitemstring(i, 'C6') 
 il_objx[i]    = long(ids_object.getitemstring(i, 'C8'))
next

return 1
end function

public function integer of_saveasascii ();///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_saveasascii
//
// DESCRIPTION : idw_source, ids_source에 대하여
//               SaveAsAscii함수를 사용하여 저장화되 Grid와 Crosstab은
//               Excel에서 Column Type에 따라 문자열을 지정해 줌.
//               (숫자형 문자열의 Excel전환시 숫자화 되는 것 방지)
//
// RETURN  : Integer
//               성공 : 1
//               실패 : -1
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
//   None
//
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

integer i, li_rc, li_colDatatype[]
string ls_process, ls_mode, ls_coltype[]
string ls_filepath = 'C:\Excel.txt', ls_filename = 'excel'

OleObject MyExcel, MyQuery
/*
li_rc = GetFileSaveName ( "Select File", ls_filepath, ls_filename, "TXT", &
                          "Text Files (*.txt),*.txt") //, "C:\", 32770)
If li_rc <> 1 then Return li_rc //0 파일 저장 취소, -1 Error

IF FileExists(ls_filepath) Then
 li_rc = Messagebox ("저장확인", ls_filepath + "'~r~n 위 파일이 이미 있습니다.~r~n" + &
          "기존 파일을 바꾸시겠습니까?", Question!, YesNo!, 2)
 IF li_rc = 2 Then Return 0 // 파일 저장 취소
End If
*/

if ib_detailonly then //'1','4'
 li_rc = ids_excel.saveasascii(ls_filepath)
 if li_rc <> 1 then &
 MessageBox('1,4', 'SaveAsAscii로 변환중 오류가 발생했습니다.', stopsign!)

else // False or '0', '2'
 choose case ipo_sourcetype
  case datawindow!
   li_rc = idw_source.saveasascii(ls_filepath)
  case datastore!
   li_rc = ids_source.saveasascii(ls_filepath)
  case datawindowchild!
   messagebox('잠깐!', '이 객체는 SaveAsAscii를 지원하지 않습니다.~r~n' &
                     + 'grid형태로 출력을 변경합니다.', exclamation!)
   ib_detailonly = true
   return of_excel(idc_source, ib_detailonly)
  case else
   messagebox('Error', 'of_saveasascii() ~r~n 알수없는 오류가 발생했습니다.', stopsign!)
   return -1
 end choose
end if

if li_rc <> 1 then
 MessageBox('오류!', 'SaveAsAscii로 변환중 오류가 발생했습니다.', stopsign!)
 return -1
end if

MyExcel = Create OleObject
li_rc = MyExcel.ConnectToNewObject("excel.application")
IF li_rc <> 0 THEN
 MessageBox("Information!", "File Conversion Failed!")
 MessageBox('오류!', 'Excel을 구동하면서 오류가 발생했습니다.', stopsign!)
 Destroy MyExcel
 RETURN -1
end if

MyExcel.WorkBooks.Add()
MyExcel.ActiveWorkbook.Sheets.Add.Name = ls_filename
MyQuery = MyExcel.ActiveWorkbook.Sheets(1).QueryTables.Add('TEXT;' + ls_filepath , MyExcel.ActiveWorkbook.Sheets(1).Cells(1,1) )

if ib_detailonly then
 // Column Type을 확인한다.
 for i = 1 to upperbound(is_coltype)
  IF left(upper(is_coltype[i]), 4) = 'CHAR' then
   li_coldatatype[i] = 2
  else
   li_coldatatype[i] = 1
  end if
 next
 MyQuery.TextFileColumnDataTypes = li_coldatatype
end if

MyQuery.refresh()
MyExcel.ActiveWorkbook.sheets(1).Columns.AutoFit
MyExcel.ActiveWorkbook.sheets(1).Cells(1,1).select
MyExcel.Application.Visible = True
MyExcel.DisconnectObject()
if ib_saveobjectinfo then of_saveinformation()

Return 1

end function

public function string of_getitemstring (long al_row, string as_colname);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_getitemstring
//
// DESCRIPTION : idw_source, ids_source, idc_surce, idc_report에 대하여
//               getitemstring함수를 공용으로 사용할 수 있도록 함.
//
// RETURN  : String
//               성공 - 결과문자열
//               실패 - '!'
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
// al_row                row 번호
// as_colname            column 이름
//
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

Choose Case ipo_sourcetype
 Case DataWindow!
  Return idw_source.getitemstring(al_row, as_colname)
 Case DataStore!
  Return ids_source.getitemstring(al_row, as_colname)
 Case DataWindowChild!
  Return idc_source.describe( 'Evaluate(as_colname), al_row)' )
 Case Else
  Return "!"
End Choose  

end function

public function string of_getitemnumber (long al_row, string as_colname);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_getitemnumber
//
// DESCRIPTION : idw_source, ids_source, idc_surce, idc_report에 대하여
//               getitemnumber함수를 공용으로 사용할 수 있도록 함.
//
// RETURN  : String (number가 아님에 주의할 것)
//               성공 - 결과문자열
//               실패 - '!'
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
// al_row                row 번호
// as_colname            column 이름
//
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

Choose Case ipo_sourcetype
 Case DataWindow!
  Return string(idw_source.getitemnumber(al_row, as_colname))
 Case DataStore!
  Return string(ids_source.getitemnumber(al_row, as_colname))
 Case DataWindowChild!
  Return idc_source.describe( 'Evaluate(as_colname), al_row)' )
 Case Else
  Return "!"
End Choose  

end function

public function integer of_saveinformation ();///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_saveinformation
//
// DESCRIPTION : Excel로 전환한 개체의 DWObject들의 정보를 출력함.
//               (개발시의 column자료를 확인하기 위함)
//
// RETURN  : Integer
//               성공 : 1
//               실패 : -1
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
//   None
//
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

integer i, li_rc, li_colDatatype[]
string ls_process, ls_mode, ls_coltype[]
string ls_filepath, ls_filename
OleObject MyExcel
OleObject MyQuery

li_rc = GetFileSaveName ( "오브젝트 정보 저장", ls_filepath, ls_filename, "TXT", &
                          "Text Files (*.txt),*.txt") //, "C:\", 32770)
If li_rc <> 1 then Return li_rc //0 파일 저장 취소, -1 Error

IF FileExists(ls_filepath) Then
 li_rc = Messagebox ("저장확인", ls_filepath + "'~r~n 위 파일이 이미 있습니다.~r~n" + &
          "기존 파일을 바꾸시겠습니까?", Question!, YesNo!, 2)
 IF li_rc = 2 Then Return 0 // 파일 저장 취소
End If

ids_object.setfilter('')
ids_object.filter()
li_rc = ids_object.saveasascii(ls_filepath)

if li_rc <> 1 then
 MessageBox('오류!', 'SaveAsAscii로 변환중 오류가 발생했습니다.', stopsign!)
 return -1
end if

MyExcel = Create OleObject
li_rc = MyExcel.ConnectToNewObject("excel.application")
IF li_rc <> 0 THEN
 MessageBox('오류!', 'Excel을 구동하면서 오류가 발생했습니다.', stopsign!)
 Destroy MyExcel
 RETURN -1
end if

MyExcel.WorkBooks.Open(ls_filepath)
MyExcel.ActiveWorkbook.sheets(1).Cells(1,1).select
MyExcel.Application.Visible = True
MyExcel.DisconnectObject()

Return 1

end function

public function integer of_savecomposite ();///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_savecomposite
//
// DESCRIPTION : idw_source, ids_source에 대하여 composite형태를
//               Report 단위로 처리하여 Excel의 sheet로 변환해 줌.
//               DataWindowChild는 saveasascii방식이 적용안된므로
//               Grid형태로 변형하여 출력함.
//
// RETURN  : Integer
//               성공 : 1
//               실패 : -1
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
//   None
//
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

Integer   i, j, li_rpt, li_rc, li_dwc, li_cnt, li_coldatatype[]
String  ls_copydata, ls_objects, ls_object[], ls_type
string    ls_rc, ls_report[], ls_process, ls_filepath='C:\excel.txt'
OleObject MyExcel, MyQuery

// datawindow의 모든 dwobject를 읽어와 ls_object[]에 저장
ls_objects = of_describe('Datawindow.objects')
of_string2array(ls_objects, '~t', ls_object[])

// report만 ls_report[]에 저장
for i = 1 to upperbound(ls_object[])
 ls_type = of_describe( ls_object[i] + ".type" )
 choose case ls_type
  case 'report'
   li_rpt++
   ls_report[li_rpt] = ls_object[i]
  case else
   // report가 아닌것은 제외
 end choose
next

//-----------------------------------------------------------------------------
// Report개체는 시트를 구분하여 처리한다.
//-----------------------------------------------------------------------------
TRY
 myExcel = CREATE oleobject

 li_rc = myExcel.ConnectToNewObject ( "Excel.Application" )
 IF li_rc <> 0 THEN
  MessageBox ( "Error", String ( li_rc ) )
  Return -1
 END IF
 myExcel.Application.Visible = False
 myExcel.Workbooks.Add()
 
 ib_composite = true // 여기서부터 공용함수를 idc_report로 바꾼다.
 
 if upperbound(ls_report) > 0 then
  messagebox('참고', '선택하신 개체는 Excel로 전환시 ~r~n' &
                   + '부득이하게 형태가 변경됩니다.', Information!)
        
  for i = 1 to upperbound(ls_report)
   li_rc = of_getchild(ls_report[i], idc_report)
    if li_rc <> 1 then
     messagebox('잠깐!', 'getchild 실패', Stopsign!)
     return -1
    end if
   il_rowcount = idc_report.rowcount()
   ls_process = of_describe('Datawindow.Processing')
   
   choose case ls_process
    case '0', '1', '2', '4'
     // 무조건 Grid형태로 진행함.
    case else
     continue
   end choose
   li_rc = of_analyze()
   if li_rc <> 1 then
    messagebox('잠깐!', 'report분석 실패', Stopsign!)
    return -1
   end if

   li_rc = of_createdwo(ids_excel, upperbound(is_detail), False)
   if li_rc <> 1 then
    messagebox('잠깐!', 'report용 datastore작성 실패', Stopsign!)
    return -1
   end if
     
   ls_copydata = of_datacopy()
   if ls_copydata = '!' then
    messagebox('잠깐!', 'report용 datacopy실패:'+ls_copydata, Stopsign!)
    continue
   end if
   for j = 1 to upperbound(is_coltype)
    IF left(upper(is_coltype[j]), 4) = 'CHAR' then
     li_coldatatype[j] = 2
    else
    li_coldatatype[j] = 1
    end if
   next
 
   li_cnt++
   of_writetext(ls_copydata, ls_filepath)
   
   ClipBoard ( ls_copydata ) //복사
   myExcel.ActiveWorkbook.Sheets.add.name = ls_report[i]
   MyQuery = MyExcel.ActiveWorkbook.Sheets(ls_report[i]).QueryTables.Add &
             ('TEXT;' + ls_filepath , MyExcel.ActiveWorkbook.Sheets(ls_report[i]).Cells(1,1) )   
   MyQuery.TextFileColumnDataTypes = li_coldatatype
   MyQuery.refresh
   myExcel.ActiveWorkbook.sheets(ls_report[i]).Cells(1,1).select
   myExcel.ActiveWorkbook.sheets(ls_report[i]).Columns.AutoFit
   if ib_saveobjectinfo then of_saveinformation()
    
  next
  //한개도 성공하지 못한 경우에는 에러를 반환함.
  if li_cnt < 1 then return -1
 else
  messagebox('잠깐!', '작업할 Report가 하나도 없습니다.', Stopsign!)
  return -1
 end if

CATCH ( exception e )
 MessageBox ( "Error", e.GetMessage() )
 
FINALLY
 if isvalid(myExcel) then
  myExcel.Application.Visible = True
  myExcel.DisconnectObject()
  DESTROY myExcel
 end if

END TRY

RETURN 1
return 1
end function

public function integer of_savedetailonly ();///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_savedetailonly
//
// DESCRIPTION : idw_source, ids_source에 대하여
//               SaveAsAscii를 적용하지않고 Detail만 Grid형태로 출력함.
//               문자열에 대햐여 숫자로 전환된지 않도록 방지하고,
//               SaveAsAscii에서 잘못되는 group소계 부분을 삭제함.
//               (Excel에서 부분합 같은 기능으로 간단히 할 수 있으며
//                Excel로 전환후 Data의 재사용성을 제고함.)
//
// RETURN  : Integer
//               성공 : 1
//               실패 : -1
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
//   None
//
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

integer li_rc
string  ls_rc
if is_processing = '4' then
 // Crosstab은 StaticMode를 설정함.
 ls_rc = of_modify('DataWindow.crosstab.StaticMode = "yes"')
 if ls_rc = '!' or ls_rc = '?' then
  messagebox ('오류', 'of_modify() ~r~n Crosstab의 StaticMode를 설정하지 못했습니다.', Stopsign!)
  return -1
 end if
end if
   
li_rc = of_analyze() // objects를 분석.
if li_rc <> 1 then
 messagebox ('오류', 'of_analyze() ~r~n Datawindow를 분석하는 중에 오류가 발생했습니다.', Stopsign!)
 return -1
end if

li_rc = of_createdwo(ids_excel, upperbound(is_detail), False) // 복사용 DataStore 준비.
if li_rc <> 1 then
 messagebox ('오류', 'of_createdwo ~r~n 복사용 DataStore를 만들지 못했습니다.', Stopsign!)
 return -1
end if

ls_rc = of_datacopy() // 자료를 ids_excel로 복사.
if ls_rc = '!' then
 messagebox ('오류', 'of_displaycopy() ~r~n Data를 복사하지 못했습니다.', Stopsign!)
 return -1
end if

return of_saveasascii() // Excel로 읽기
end function

public function string of_datacopy ();///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_datacopy
//
// DESCRIPTION : Datawindow를 Display된 내용으로 임시 DataStore로 Copy한다.
//               Detail Band와 그 Title만 전환함. 서식적용없는 내용Copy임.
//
// RETURN  : String
//               성공 - Tab으로 분리된 문자열
//               실피 - '!'
//
// ARGUMENTS         DESCRIPTION
// ------------------------------------------------------------------------
//   None
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////
string         ls_exp, ls_data, ls_editstyle, ls_copydata
Long    i, j, ll_rowcount
Integer        li_colcount

//-----------------------------------------------------------------------------
// row , column의 개수를 가져온다.
// row의 갯수는 Excel의 한계인 65536에서 Title열을 뺀 65535로 제한한다.
//-----------------------------------------------------------------------------
li_colcount = upperbound(is_detail)
ll_rowcount = il_rowcount
IF ll_rowcount < 1 then return '!' //처리할 행이 없음.
IF li_colcount < 1 then return '!' //처리할 열이 없음.
IF li_colcount > ii_excelcol then li_colcount = ii_excelcol
IF ll_rowcount > ii_excelrow then ll_rowcount = ii_excelrow

//-----------------------------------------------------------------------------
// Data복사용 DataStore를 설정한다.
//-----------------------------------------------------------------------------
ids_excel.reset()

FOR i = 1 TO ll_rowcount    // row의 수만큼 DataStore에 추가한다.
   ids_excel.InsertRow(0)
NEXT

//-----------------------------------------------------------------------------
// 자료를 copy한다.
// data에 탭, 개행문자 등이 있을 경우에는 copy & paste에 문제가 되므로 공백대체.
// 계산필드에 혹시 따옴표가 있을 경우에는 Evaluate의 따옴표 종류를 다르게 할 것.
//-----------------------------------------------------------------------------

FOR j = 1 to li_colcount

 ls_data = ''
 ls_editstyle = of_describe(is_detail[j] + ".edit.style")

 // 원Data의 coltype을 보고 char(##), number에 따라 처리
 choose case ls_editstyle
  case 'checkbox'
   if left(is_coltype[j],4) = 'CHAR' then  //문자열인 경우
    for i = 1 to ll_rowcount
     ls_data = of_getitemstring(i, is_detail[j])
     // 0으로 시작하는 숫자형 문자열의 변형 방지 예) 0001 -> 1 대안 '0001
     if asc(ls_data) = 48 then ls_data = "'" + ls_data
     ids_excel.SetItem(i , j , ls_data)
    next
   else //숫자형인 경우
    for i = 1 to ll_rowcount
     ls_data = of_getitemnumber(I,is_detail[j])
     ids_excel.SetItem(i , j , ls_data)
    next
   end if
  case else //checkbox 이외의 edit style
   IF is_objtype[j] = 'COLUMN' then
    FOR i = 1 TO ll_rowcount
     ls_data = of_Describe("Evaluate('LookupDisplay(" + &
                   is_detail[j] + ")' , " + String(i) + ")")
     if isnull(ls_data) then ls_data = ''
     // 탭과 개행문자를 공백으로 대치
     of_replaceall(ls_data, char(9) , ' ') //Tab
     of_replaceall(ls_data, char(10), ' ') //LF
     of_replaceall(ls_data, char(13), ' ') //CR
     of_replaceall(ls_data, char(34), char(39)) //쌍따옴표
     // 0으로 시작하는 숫자형 문자열의 변형 방지 예) 0001 -> 1 대안 '0001
     //if upper(adw_source.describe( ls_detail[j] + ".coltype" )) = 'CHAR' then
     //  if asc(ls_data) = 48 then ls_data = "'" + ls_data
     //end if
     
     ids_excel.SetItem(i , j , ls_data)
    NEXT
      
   //계산필드 내용 확인
   elseif is_objtype[j] = 'COMPUTE' then
    ls_exp = of_describe(is_detail[j] + ".expression")
    FOR i = 1 TO ll_rowcount
     ls_data = of_Describe("Evaluate('" + ls_exp + "'," + string(i) + ")")
     if isnull(ls_data) then ls_data = ''
     // 탭과 개행문자를 공백으로 대치
     of_replaceall(ls_data, char(9) , ' ') //Tab
     of_replaceall(ls_data, char(10), ' ') //LF
     of_replaceall(ls_data, char(13), ' ') //CR
     of_replaceall(ls_data, char(34), char(39)) //쌍따옴표
     // 0으로 시작하는 숫자형 문자열의 변형 방지 예) 0001 -> 1 대안 '0001
     //if upper(adw_source.describe( ls_detail[j] + ".coltype" )) = 'CHAR' then
     //  if asc(ls_data) = 48 then ls_data = "'" + ls_data
     //end if
     ids_excel.SetItem(i , j , ls_data)
    NEXT
   end if
   
 end choose //edit style에 따른 처리 종료
NEXT

//-----------------------------------------------------------------------------
// Header title 삽입
//-----------------------------------------------------------------------------
ids_excel.InsertRow(1)
for i = 1 to upperbound(is_label)
 ids_excel.SetItem(1 , i , is_label[i])
next

ls_copydata = ids_excel.object.datawindow.data

RETURN ls_copydata

end function

public function integer of_getchild (string as_report, ref datawindowchild adc_source);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_getchild
//
// DESCRIPTION : idw_source, ids_source에 대하여
//               getchild함수를 공용으로 사용할 수 있도록 함.
//
// RETURN  : String
//               성공 :  1
//               실패 : -1
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
// as_report             getchild에 사용할 report명
// adc_source            getchild로 할당될 DataWindowChild 참조개체
//
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

Choose Case ipo_sourcetype
 Case DataWindow!
  Return idw_source.getchild(as_report, adc_source)
 Case DataStore!
  Return ids_source.getchild(as_report, adc_source)
 Case DataWindowChild!
  Return -1 // idc_source.getchild(as_report, adc_source)
 Case Else
  Return -1
End Choose  

end function

public function long of_writetext (string as_string, string as_filepath);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_writetext
//
// DESCRIPTION : 주어진 문자열을 Text파일로 출력함.
//
// RETURN  : Long (출력된 문자열 길이)
//
// ARGUMENTS         DESCRIPTION
// ------------------------------------------------------------------------
// as_string       파일로 쓸 문자열
// as_filepath     저장할 파일명을 포함한 Path
//
///////////////////////////////////////////////////////////////////////////////
//                 mojirhi @ gmail . com
///////////////////////////////////////////////////////////////////////////////

long i, ll_len, ll_loop, ll_FileNo, ll_pos
string ls_temp

ll_len  = len(as_string)
ll_loop = integer(ll_len/32765) + 1

ll_FileNo = FileOpen(as_filepath, StreamMode!, Write!, LockWrite!, Replace!)

ll_pos = 1
For i = 1 To ll_loop
   ls_temp = Mid(as_string, ll_pos, 32765)
   ll_pos += 32765
   If FileWrite(ll_FileNo, ls_temp) = -1 Then
      Return -1
   End if
Next
FileClose(ll_FileNo)

return ll_len
end function

public function integer of_createdwo (ref datastore ads_source, integer ai_col, boolean ab_header);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_createdwo
//
// DESCRIPTION : 임시로 사용할 datastore의 dwobject를 만든다.
//
// RETURN  : Integer
//
// ARGUMENTS         DESCRIPTION
// ------------------------------------------------------------------------
// ads_source       source datastore
// ai_col                        dwobject의 열수를 지정.
// ab_header                     Header름 만드는지의 옵션
//                               True 만듦 - DwObject용
//                               False 만들지 않음 - DataCopy용
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

string ls_syntax
integer  i

if not isvalid(ads_source) or isnull(ads_source) then return -1

if ai_col > 255 then ai_col = 255

ls_syntax = ls_syntax + 'release 9;'
ls_syntax = ls_syntax +  '~r~n' + 'datawindow(units=0 timer_interval=0 color=16777215 processing=1 HTMLDW=no print.printername="" print.documentname="" print.orientation = 0 print.margin.left = 110 print.margin.right = 110 print.margin.top = 96 print.margin.bottom = 96 print.paper.source = 0 print.paper.size = 0 print.canusedefaultprinter=yes print.prompt=no print.buttons=no print.preview.buttons=no print.cliptext=no print.overrideprintjob=no print.collate=yes hidegrayline=no grid.lines=0 )'
ls_syntax = ls_syntax +  '~r~n' + 'header(height=80 color="536870912" )'
ls_syntax = ls_syntax +  '~r~n' + 'summary(height=0 color="536870912" )'
ls_syntax = ls_syntax +  '~r~n' + 'footer(height=0 color="536870912" )'
ls_syntax = ls_syntax +  '~r~n' + 'detail(height=92 color="536870912" )'
ls_syntax = ls_syntax +  '~r~n' + 'table('
 for i = 1 to ai_col
  ls_syntax = ls_syntax +  '~r~n' + 'column=(type=char('+ string(ii_celllen) + ') updatewhereclause=yes name=C' + string(i) + ' dbname="C' + string(i) +'" )'
 next
ls_syntax = ls_syntax +  '~r~n' + ' )'
if ab_header then
 for i = 1 to ai_col
  ls_syntax = ls_syntax +  '~r~n' + 'text(band=header alignment="2" text="C' + string(i) + '" border="0" color="0" x="' + string(i*100 + 9) + '" y="8" height="64" width="91" html.valueishtml="0"  name=C' + string(i) + '_t visible="1"  font.face="Arial" font.height="-10" font.weight="400"  font.family="2" font.pitch="2" font.charset="0" background.mode="1" background.color="536870912" )'
 next
end if
for i = 1 to ai_col
 ls_syntax = ls_syntax +  '~r~n' + 'column(band=detail id='+ string(i) +' alignment="0" tabsequence=' + string(i*10) + ' border="0" color="0" x="'+ string(i*100 + 9) +' " y="8" height="76" width="91" format="[general]" html.valueishtml="0"  name=C' +string(i) + ' visible="1" edit.limit=0 edit.case=any edit.focusrectangle=no edit.autoselect=yes edit.autohscroll=yes edit.imemode=0  font.face="Arial" font.height="-10" font.weight="400"  font.family="2" font.pitch="2" font.charset="0" background.mode="1" background.color="536870912" )'
next
ls_syntax = ls_syntax +  '~r~n' + 'htmltable(border="1" )'
ls_syntax = ls_syntax +  '~r~n' + 'htmlgen(clientevents="1" clientvalidation="1" clientcomputedfields="1" clientformatting="0" clientscriptable="0" generatejavascript="1" encodeselflinkargs="1" netscapelayers="0" )'
ls_syntax = ls_syntax +  '~r~n' + 'export.xml(headgroups="1" includewhitespace="0" metadatatype=0 savemetadata=0 )'
ls_syntax = ls_syntax +  '~r~n' + 'import.xml()'
ls_syntax = ls_syntax +  '~r~n' + 'export.pdf(method=0 distill.custompostscript="0" xslfop.print="0" )'

return ads_source.create(ls_syntax)

end function

public function integer of_excel (powerobject apo_source, boolean ab_detailonly);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_excel
//
// DESCRIPTION : Datawindow와 DataStrore를 Excel로 전환함.
//
// RETURN  : Integer
//               1 = 성공, -1 = 실패
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
// apo_source           Excel로 전환할 Object
// ab_detailonly        Detail만 grid로 전환할 옵션
//                      Grid 및 Crosstab에서만 유효하며
//                      Composite는 무조건 True임
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

integer li_rc
string ls_rc, ls_mode
powerobject lpo_source

if isnull(ib_detailonly) then return -1
ib_detailonly = ab_detailonly

lpo_source = apo_source
if not(isnull(lpo_source)) and isvalid(lpo_source) then
 ipo_sourcetype = lpo_source.typeof()
 choose case ipo_sourcetype
  case datawindow!
   idw_source = lpo_source
   il_rowcount = idw_source.rowcount()
  case datastore!
   ids_source = lpo_source
   il_rowcount = ids_source.rowcount()
  case datawindowchild!
   idc_source = lpo_source
   il_rowcount = idc_source.rowcount()
  case else
   return -1
 end choose

 is_processing = of_describe('Datawindow.Processing')
 ls_rc = of_describe('Datawindow.data')
 if trim(ls_rc) = '' and is_processing <> '5' then
  messagebox('잠깐!', 'Data가 없습니다.', stopsign!)
  return -1
 end if
else
 messagebox('잠깐!', '작업할 수 없는 상태입니다.', stopsign!)
 return -1
end if

choose case is_processing
 case '0', '2' // Form/Tabular/N-Up, Label은 무조건 saveasascii를 적용함.
  ib_detailonly = False
  li_rc = of_saveasascii()
 case '1', '4' // Grid, Crosstab은 ib_detailonly에 따름.
  if ib_detailonly then
   li_rc = of_savedetailonly()
  else
   li_rc = of_saveasascii()
  end if
 case '5'  // Composite는 SaveAsAscii가 안됨
  ib_detailonly = True
  li_rc = of_savecomposite()
 case else
  messagebox('잠깐!', '지원하지 않은 형식의 Data입니다.', Stopsign!)
end choose
if li_rc <> 1 then
 messagebox('잠깐!', 'Excel로 전환되지 못했습니다.', Stopsign!)
end if

return 1
end function

public function integer of_excel (powerobject apo_source, boolean ab_detailonly, boolean ab_saveobjectinfo);///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION  : of_excel(개발용)
//
// DESCRIPTION : Datawindow와 DataStrore를 Excel로 전환함.
//               추가로 전환된 후에 DWObject정보를 Excel로 출력함.
//               (Composite는 맨 마지막 Report만 나옴.)
//
// RETURN  : Integer
//               1 = 성공, -1 = 실패
//
// ARGUMENTS             DESCRIPTION
// ------------------------------------------------------------------------
// apo_source           Excel로 전환할 Object
// ab_detailonly        Detail만 grid로 전환할 옵션
//                      Grid 및 Crosstab에서만 유효하며
//                      Composite는 무조건 True임
// ab_saveobjectinfo    개발용으로 DWObject를 출력할 것인지 옵션
//
///////////////////////////////////////////////////////////////////////////////
//                      mojirhi (mojirhi @ gmail . com)
///////////////////////////////////////////////////////////////////////////////

integer li_rc
if isnull( ab_saveobjectinfo ) then return -1

li_rc = messagebox('DWObject정보저장', &
                  'DWObject정보를 저장하시겠습니까?', &
       Question!, YesNo!, 1)
if li_rc = 1 then
 ib_saveobjectinfo = ab_saveobjectinfo
end if

return of_excel(apo_source, ab_detailonly)

end function

event constructor;ids_object = create datastore
ids_excel  = create datastore
of_createdwo(ids_object, 30, True)

end event

on my_n_excel.create
call super::create
TriggerEvent( this, "constructor" )
end on

on my_n_excel.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on

event destructor;if isvalid(ids_excel)  then destroy ids_excel
if isvalid(ids_object) then destroy ids_object


end event

Posted by 민서정
l