* Powerbuilder 10.5


지난 31강에서 조건에 따라 명단을 조회하는 두 가지 방법을 소개했습니다.

1. DB 쿼리에 조건을 주는 방법
2. Filter 함수를 이용해서 조건에 맞는 명단을 걸러내는 방법


1번은 직급과 부서를 조건으로 구현했구요. 이제 2번을 할 차례입니다.

2번은 부서위치를 조건으로 구현해 보겠습니다.


목록을 담는 ddlb 를 만드는 건 동일합니다.

select loc
from dept


위 쿼리로 d_loc_list 라는 이름의 grid 타입 dw 를 만듭니다.

dw_loc_list 라는 이름의 dw 컨트롤을 만들어서 연결시킵니다.

그리고 ddlb_loc 라는 이름의 ddlb 를 만듭니다. 그럼 다음과 같은 화면이 나오겠네요.


그리고 dw_loc_list 를 조회해서 ddlb_loc 에 넣어줍니다.

w_list.open 이벤트

dw_emp.SetTransObject(sqlca)
dw_job_list.SetTransObject(sqlca)
dw_dept_list.SetTransObject(sqlca)
dw_loc_list.SetTransObject(sqlca)

int li_cnt, i

// 직급 목록
li_cnt = dw_job_list.Retrieve()

ddlb_job.AddItem('전체' + space(30) + '%')

For i = 1 to li_cnt
 
    ddlb_job.AddItem(dw_job_list.getItemString(i, 'job'))
 
Next

ddlb_job.SelectItem(1)
//--

// 부서 목록
li_cnt = dw_dept_list.Retrieve()

ddlb_dept.AddItem('전체' + space(30) + '1')

For i = 1 to li_cnt
 
    ddlb_dept.AddItem( dw_dept_list.getItemString(i, 'dname') + space(30) + string(dw_dept_list.getItemNumber(i, 'deptno')) )
 
Next

ddlb_dept.SelectItem(1)
//--

// 부서위치 목록
li_cnt = dw_loc_list.Retrieve()

ddlb_loc.AddItem('전체')    // % 는 붙이지 않았습니다.

For i = 1 to li_cnt
 
    ddlb_loc.AddItem(dw_loc_list.getItemString(i, 'loc'))
 
Next

ddlb_loc.SelectItem(1)
//--

wf_retrieve('%', 1)


굵게 표현한 부분이 추가한 스크립트입니다. copy & paste 의 향기가...ㅎㅎ


d_emp 의 DataSource

select a.empno,
         a.ename,
         a.job,
         a.deptno,
         b.deptno as dname,
         b.deptno as loc,
         
b.loc as loc_filter    -- 이 부분을 추가합니다. 부서위치 칼럼
from emp a, dept b
where a.deptno = b.deptno
and a.job like :as_job
and (a.deptno = :ai_deptno or :ai_deptno = 1)
order by a.ename


d_emp 레이아웃으로 돌아옵니다.


 




그럼 dept_loc_filter 칼럼이 추가되죠.




dept_loc_filter 를 선택한 다음 Del 키를 눌러서 삭제합니다.

이 때, 레이아웃에서는 삭제 되지만 dw 자체적으로는 소유하고 있습니다.

Column Specification 을 보면 dept_loc_filter 가 있는게 보입니다.

그렇다면 레이아웃에서 삭제된 칼럼을 불러오려면?

일단, dept_loc_filter 를 삭제한 뒤에

 





컨트롤 모음창을 열어서 Place a column 을 선택합니다.






그리고 detail 밴드에 있는 dept_loc 칼럼 오른편을 클릭합니다. 

 


그럼 DataSource 쿼리에서 가져온 칼럼 목록이 나옵니다. Column specification 의 목록과 동일하고 순서만 다릅니다.

dept_loc_filter 를 선택하고 OK 버튼 클릭~

그럼 dept_loc_filter 칼럼이 레이아웃에 생성됩니다.






dept_loc_filter 칼럼은 화면에 보여줄 필요가 없으므로 레이아웃에서는 삭제합니다.


ddlb_loc.selectionchanged 이벤트




일단 요대로 작성하세요.


 

SetFilter method (DataWindows)

설명
  dw에서 필터 기준을 설정

문법
  integer dwcontrol.SetFilter ( string format )

  format 은 string 타입의 boolean 표현식(조건식)
  필터 기준을 제거하려면 '' 또는 "" 을 입력


Filter method (DataWindows)

설명
  현재 필터 기준(SetFilter에 의해 설정된 기준)을 통과하는 dw 로우만 보여줌.
  필터 기준에 맞지 않는 로우는 Filter buffer 로 옴겨짐.

문법
  integer dwcontrol.Filter ( ) 



dw 에서 SetFilter 함수로 필터 기준을 세우고 Filter 함수로 기준을 적용시킵니다.

이제 스크립트를 살펴보겠습니다.

if ls_loc = '전체' then
    dw_emp.setfilter("")
else
    dw_emp.setfilter("dept_loc_filter = '" + ls_loc + "'")
end if


ls_loc 가 '전체' 라는 값을 가지면 dw_emp.setFilter("") 을 호출했습니다.

즉, 필터 기준을 제거한 것이 되어 모든 로우를 보여줍니다.

dw_emp.setfilter("dept_loc_filter = '" + ls_loc + "'")

이 부분이 좀 어렵습니다.

ls_loc 대신에 리터럴값을 직접 입력하면

dw_emp.setfilter("dept_loc_filter = 'CHICAGO'"

dept_loc_filter = 'CHICAGO' 는 일반적인 조건식입니다.

그런데 fortmat 자체는 string 타입이므로 더블쿼트(")로 감쌌습니다.

이 때 싱글쿼트(')를 'CHICAGO' 에서 이미 사용중이므로 다시 싱글쿼트(')로 감싸면 인용구의 구분이 불확실해져서 에러가 발생하게 됩니다. 그래서 반드시 더블쿼트로 감싸야 합니다.

그래서 "dept_loc_filter = 'CHICAGO'" 이렇게 되는건데요.
'CHICAGO' 부분을 변수로 치환하려니 좀 복잡해지는 겁니다.

바로 치환해 보죠.

dw_emp.setfilter("dept_loc_filter = ls_loc"

이럴 경우 더블쿼트로 감쌌기 때문에 ls_loc 가 변수로 취급되지 않고 리터럴로 취급됩니다.


해결방법은 다음과 같습니다.

먼저, 다음과 같이 "CHICAGO" 를 분리 시킵니다.

"dept_loc_filter = 'CHICAGO'"   ->   "dept_loc_filter = '" + "CHICAGO" + "'"

("ABC" = "A" + "B" + "C")

그리고 "CHICAGO"  를 변수로 치환합니다.

그러면

dw_emp.setfilter("dept_loc_filter = '" + ls_loc + "'")     요렇게 되는 거죠.


처음 보면 어려운데 자꾸 보면 적응됩니다. ㅎㅎ


실행해 보세요.


1. dw 의 Retrieve 함수는 DBMS 로 쿼리를 전달하고 그 결과(Result Set)를 dw 컨트롤에 보여줍니다.
2. dw 의 Filter 함수는 dw 에서 이미 조회한 결과 중에 조건에 맞는 결과만 보여줍니다.

1번은 매번 DBMS 와 통신하지만 2번은 한번 만 통신한다는 차이점이 있습니다.

경우에 따라 적합한 방법을 사용하는 것이 중요합니다.


수고하셨습니다.

 

Posted by A4M
,