25.Grid 응용

Edit

25.1Grid에서 엑셀로 복사/붙여넣기

컴퓨터를 사용할 때 시스템 클립보드를 통한 복사(Ctrl+c) / 붙여넣기(Ctrl+v) 기능은 사용의 편의성으로 인해 자주 사용됩니다. 마찬가지로 넥사크로플랫폼에서도 기능을 구현하면 복사/붙여넣기를 사용할 수 있습니다.

본 장에서는 Grid의 데이터를 시스템에 있는 엑셀, 메모장을 비롯한 애플리케이션으로 복사/붙여넣기 하는 기능을 구현하고 그 방법을 설명합니다.

25.1.1예제

다음은 Grid의 데이터를 엑셀로 복사/붙여넣기 하는 예제입니다.

Grid의 Row를 마우스 드래그나 키보드를 사용해 선택한 후 Ctrl + c를 누르면 복사됩니다. 그런 후 시스템에 있는 엑셀에서 Ctrl + v를 눌러 붙여넣기 합니다.

Grid의 selecttype 속성이 multirow로 설정되어 있기 때문에 Row 단위로만 선택할 수 있습니다.

그림 25-1sample_excelexportimport_08_01

sample_grid_30.xfdl

25.1.2예제에서 사용한 핵심 기능

navigatorname

브라우저의 이름 정보를 갖는 읽기 전용 속성입니다.

넥사크로플랫폼 런타임

nexacro

인터넷 익스플로러

IE

크롬

Chrome

파이어폭스

Gecko

setEventHandler

Grid의 이벤트 함수를 변경하는 메소드입니다.

selectstartrow

Grid에서 선택된 영역의 시작 셀의 Row 인덱스를 갖는 읽기전용 속성입니다.

selectendrow

Grid 에서 선택된 영역의 마지막 셀의 Row 인덱스를 갖는 읽기전용 속성입니다.

selectstartcol

Grid 에서 선택된 영역의 시작 셀의 Column 인덱스를 갖는 읽기전용 속성입니다.

selectendcol

Grid 에서 선택된 영역의 마지막 셀의 Column 인덱스를 갖는 읽기전용 속성입니다.

getFormatColCount

Grid 에 표시되고 있는 포맷에 정의된 Column 의 갯수를 반환하는 메소드입니다

getCellText

인수로 전달된 위치의 셀에 표시되는 텍스트 값을 반환하는 메소드입니다.

setClipboard

시스템의 클립보드에 지정된 형식으로 데이터를 저장하는 메소드입니다.

clearClipboard

시스템의 클립보드에 저장된 내용을 삭제하는 메소드입니다.

keycode

키보드로 입력된 키에 해당하는 코드값을 갖는 속성입니다

ctrlkey

이벤트 발생시 Ctrl 키가 눌렸는지 여부를 확인하는 속성입니다.

shiftkey

이벤트 발생시 Shift 키가 눌렸는지 여부를 확인하는 속성입니다.

altkey

이벤트 발생시 Alt 키가 눌렸는지 여부를 확인하는 속성입니다.

25.1.3예제 구현 방법

1

컴포넌트 생성하기

툴바에서 그리드 를 선택한 후, Form 위에 적당한 크기로 드래그하여 생성합니다. 그냥 폼에 대고 클릭하면 기본 크기로 생성됩니다.

2

Dataset 생성과 데이터 입력하기

Grid에 출력할 데이터 아이템 목록을 가진 Dataset을 생성합니다.

  1. 툴바에서 Dataset 을 선택한 후, 폼 위 적당한 공간에 클릭하여 Dataset을 생성합니다.

  1. 생성한 Dataset에 데이터 아이템 목록을 입력합니다. Invisible Objects 영역에 있는 Dataset을 더블 클릭하면 Dataset Editor가 뜨는데 Columns와 Rows에 아래 그림과 같이 입력합니다.

그림 25-2sample_grid_25_02

3

Dataset 바인딩

Dataset을 Grid 컴포넌트에 바인딩합니다.

Invisible Objects 영역에 있는 Dataset을 Form에 생성한 Grid 컴포넌트로 드래그 앤 드롭하면 바인딩이 완료됩니다.

4

Grid 속성 설정하기

Grid를 다중 선택이 가능하도록 selecttype 속성을 'multirow'로 설정합니다.

5

Form 이벤트 함수 작성하기

Form을 선택한 후 onload 이벤트 함수를 다음과 같이 작성합니다.

this.Form_onload = function(obj:nexacro.Form,e:nexacro.LoadEventInfo)
{
    this.copyPaste.addGrid(this.Grid00);    
};

6

키 입력과 복사/붙여넣기 처리를 위한 copyPaste 오브젝트 작성하기

키 입력을 처리하고 Grid의 데이터를 브라우저에 따라 시스템의 클립보드 혹은 Textarea 요소로 복사하는 기능을 스크립트로 구현합니다.

기능 구현을 위해 copyPaste 오브젝트를 작성합니다. copyPaste 오브젝트는 키 입력 처리를 위한 addGrid, 선택된 Grid 데이터를 추출하기 위한 makeData, Grid 데이터를 복사하기 위한 copyGridCellData1, copyGridCellData2의 총 4개 메소드로 구성됩니다.

각 메소드에 대한 자세한 설명은 아래 코드의 주석을 참조하시기 바랍니다.

this.copyPaste = {    
    
    //브라우저를 체크하여 브라우저에 맞는 onkeydown 이벤트 함수를 설정합니다.
    //브라우저에 따라 클립보드를 이용할지(copyGridCellData1) Textarea를 이용할지(copyGridCellData2) 결정합니다.
    addGrid: function(grid)
    {
        //브라우저가 넥사크로플랫폼 Runtime 혹은 IE인 경우
        if (system.navigatorname == "nexacro" || system.navigatorname == "IE" ) 
        {
            //grid에 onkeydown 이벤트 함수 등록
            grid.setEventHandler("onkeydown", this.copyGridCellData1(this), this);
        }
        //그 이외의 브라우저인 경우
        else
        {
            //HTML DOM의 Textarea 요소를 생성하고 body 요소에 추가합니다.
            var objTA = document.createElement("textarea");
            document.body.appendChild(objTA);
            
            //grid에 onkeydown 이벤트 함수 등록
            grid.setEventHandler("onkeydown", this.copyGridCellData2(this, objTA), this);
        }

    },
    
    //Grid에서 선택된 영역의 데이터를 변수에 저장합니다.
    makeData: function(obj)
    {    
        var sBody = "";
        var sSpr = "    ";    //Tab 값 입력
        var nStartrow = obj.selectstartrow;
        var nEndrow = obj.selectendrow;
        var nStartCol = obj.selectstartcol;
        var nEndCol = obj.selectendcol;
                        
        //selecttype이 row나 multirow인 경우
        //selectstartcol, selectendcol 값은 -1이 된다.
        //따라서 컬럼의 갯수를 계산하여 nStartCol과 nEndCol을 설정한다.
        var nLoop = nStartrow.length;
        
        if(nStartCol == -1 && nEndCol == -1)
        {
            nStartCol = 0;
            nEndCol = obj.getFormatColCount()-1;
        }
                    
        //copy cell data from selected cell
        for(var k=0; k < nLoop; k++)
        {
        
            for (var i = nStartrow[k]; i <= nEndrow[k]; i++) 
            {            
                for (var j = nStartCol; j <= nEndCol; j++) 
                {
                    if (j < nEndCol) 
                    {
                        sBody += obj.getCellText(i, j) + sSpr;
                    } 
                    else 
                    {
                        sBody += obj.getCellText(i, j) + "\r\n";
                    }
                }
            }        
            
        }

        return sBody;
    },
    
    //IE 혹은 Runtime인 경우
    //Ctrl + c가 입력되면 클립보드로 Grid의 선택된 데이터를 복사합니다.
    //키 값은 ctrl=17, shift=16, alt=18, c=67 입니다.
    copyGridCellData1: function(pThis)
    {    
        return function(obj, e) 
        {
            //Ctrl 키가 눌린 경우
            if (e.ctrlkey && !e.shiftkey && !e.altkey)
            {
                //c 키가 눌린 경우
                if (e.keycode == 67)    //'c'
                {                    
                    var rtnStr = pThis.makeData(obj);
                    
                    system.clearClipboard();                        
                    system.setClipboard("CF_TEXT", rtnStr);
                } 
            }
        }
        
    },


    //IE 혹은 Runtime 이외의 브라우저인 경우
    //Ctrl + c가 입력되면 Textarea로 Grid의 선택된 데이터를 복사합니다.
    //키 값은 ctrl=17, shift=16, alt=18, c=67 입니다.
    copyGridCellData2: function(pThis, objTA)
    {
        return function(obj, e) 
        {
            //Ctrl 키가 눌린 경우
            if (e.ctrlkey && !e.shiftkey && !e.altkey)
            {
                //c 키가 눌린 경우
                if (e.keycode == 67)    
                {
                    var rtnStr = pThis.makeData(obj);

                    objTA.value = rtnStr;
                    objTA.select();
                } 
            }
            
        }

    }//end of copyGridCellData2: function(pThis, objTA)    

}//end of this.copyPaste

7

QuickView로 확인하기

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다.

Grid를 마우스와 키보드를 사용하여 선택한 후 Ctrl +c로 복사하고 시스템의 엑셀에 Ctrl + v로 붙여넣습니다. 선택한 항목들이 모두 엑셀에 정상적으로 복사됐는지 확인합니다.

25.2합계/소계 구하기

Grid에서는 데이터를 표 형태로 표현하는 기능뿐 아니라 필요한 경우 데이터를 자동으로 연산하는 기능을 사용할 수 있습니다. 기본적으로 지원하는 연산으로는 합계, 평균, 개수, 최대/최소값 등이 있습니다. 이 중 가장 빈번하게 사용하는 연산이 합계입니다. 합계는 컬럼의 총 합을 뜻하며 같은 값을 갖는 컬럼을 그룹별로 묶어 합을 구하는 것을 소계라 합니다.

이번 장에서는 컬럼의 합계(total)와 소계(subtotal)를 구하는 방법에 대해 설명합니다.

25.2.1예제

다음 Grid는 Salary 컬럼의 합계를 구하고 Company 컬럼으로 그룹을 지어 그룹별 소계를 계산한 예제입니다.

합계는 Grid의 가장 하단에 표시되고 소계는 각 그룹의 아래에 새로운 Row가 생성되어 표시됩니다.

그림 25-3sample_grid_31_01

sample_grid_31.xfdl

25.2.2예제에서 사용한 핵심 기능

expr

Grid에서 Cell의 text 속성 값에 적용할 수식을 설정하는 속성입니다.

getSum

Dataset에서 지정한 범위의 컬럼 값 혹은 계산식의 합계를 구하는 메소드입니다.

suppress

Grid에서 Cell에 suppress 기능을 설정하는 속성입니다. suppress 기능은 한 컬럼에 같은 값을 가진 셀이 여러 개 반복적으로 나열되어 있을 경우 하나의 Cell로 합쳐 보여줍니다.

keystring

Dataset에 로드된 데이터를 그룹/정렬할 기준이 되는 조건식을 설정하는 속성입니다. 그룹 타입을 생략하면 G 옵션이 적용됩니다.

this.Dataset00.set_keystring( "column0" );
this.Dataset00.set_keystring( "G:column0" );
this.Dataset00.set_keystring( "G:+column0-column1" );
this.Dataset00.set_keystring( "G:+column0,S:-column1" );
prop

Dataset의 keystring 속성에 의해 그룹핑된 논리적 레코드에 표시되는 값의 유형을 설정하는 속성입니다.

연산

설명

NONE

(default) 아무 값도 표시하지 않습니다.

AVG

그룹의 평균값을 계산합니다.

COUNT

그룹의 개수를 계산합니다.

KEY

그룹의 키 값을 표시합니다.

MAX

그룹의 최대 값을 표시합니다.

MIN

그룹의 최소 값을 표시합니다.

SUM

그룹의 합계를 계산합니다.

TEXT

sumtext 속성값을 표시합니다.

sumtext 속성은 Grid의 Summary 영역에 표시할 문자를 설정하는 속성입니다.

displaytype

Grid의 Cell에서 데이터가 표시되는 형식을 설정하는 속성입니다.

25.2.3예제 구현 방법

1

컴포넌트 생성하기

툴바에서 그리드 를 선택한 후, Form 위에 적당한 크기로 드래그하여 생성합니다. 그냥 폼에 대고 클릭하면 기본 크기로 생성됩니다.

2

Dataset 생성과 데이터 입력하기

Grid에 출력할 데이터 아이템 목록을 가진 Dataset을 생성합니다.

  1. 툴바에서 Dataset 을 선택한 후, 폼 위 적당한 공간에 클릭하여 Dataset을 생성합니다.

  1. 생성한 Dataset에 데이터 아이템 목록을 입력합니다. Invisible Objects 영역에 있는 Dataset을 더블 클릭하면 Dataset Editor가 뜨는데 Columns와 Rows에 아래 그림과 같이 입력합니다.

그림 25-4sample_grid_31_02

3

Dataset 바인딩

Dataset을 Grid 컴포넌트에 바인딩합니다.

Invisible Objects 영역에 있는 Dataset을 Form에 생성한 Grid 컴포넌트로 드래그 앤 드롭하면 바인딩이 완료됩니다.

4

Grid 설정하기

Salary 컬럼의 표시 형식을 화폐로 설정합니다. 다음과 같이 Grid Contents Editor를 열어 Salary 컬럼의 displaytype 속성을 'currency'로 설정합니다.

그림 25-5sample_grid_31_04

5

합계 구하기

합계를 계산해 표시하려면 우선 Grid의 어느 부분에 표시할지 정한 후 expr이나 스크립트를 사용해 합계를 계산후 해당 위치에 결과를 표시합니다. 이 샘플에서는 서머리 밴드에 합계를 표시합니다.

  1. 서머리 밴드에 새로운 로우를 추가합니다. Grid를 더블클릭하여 Grid Contents Editor를 열고 마우스 오른쪽 버튼을 눌러 컨텍스트 메뉴에서 [Add Summary Row]를 선택합니다.

그림 25-6sample_grid_31_05

  1. Grid상에 TOTAL로 표시하기 위해 새로 추가한 로우의 col0~col3까지를 하나의 Cell로 합칩니다. 다음 그림과 같이 col0~col3까지 Cell을 선택한 후 마우스 오른쪽 버튼을 눌러 컨텍스트 메뉴에서 [Merge Cells] 메뉴를 선택합니다. Cell이 하나로 합쳐지면 합쳐진 Cell의 text 속성을 'TOTAL'로 설정합니다.

그림 25-7sample_grid_31_06

  1. 합계를 표시할 col4 Cell을 선택한 후 displaytype, expr 속성을 다음 그림과 같이 설정합니다. expr에 기술한 스크립트는 Salary 컬럼의 값을 모두 합친 결과를 반환하라는 의미입니다.

그림 25-8sample_grid_31_07

6

소계 구하기

소계를 계산해 표시하려면 우선 소계를 구할 기준 컬럼을 정하고 그룹지어야 합니다. 그런 후 Dataset의 prop 속성을 사용해 어떤 연산을 할지 정합니다. 이 샘플에서는 소계를 구해야 하므로 SUM으로 설정합니다.

  1. 샘플과 같이 Company 컬럼을 기준으로 그룹을 만들기 위해 Dataset00의 keystring 속성을 'G:+Company'로 설정합니다. 여기서 'G'는 그룹을 의미하고 '+'는 오름차순으로의 정렬을 의미합니다.

  1. 그룹별 소계를 계산하려면 다음 그림과 같이 Dataset Editor를 열어 Salary 컬럼의 type 속성은 'INT', prop 속성은 'SUM'으로 설정합니다. prop 속성은 별도로 값을 설정하지 않으면 SUM으로 동작합니다.

그림 25-9sample_grid_31_03

7

QuickView로 확인하기

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다.

Grid의 데이터가 Company 컬럼을 기준으로 그룹이 지어졌는지, 각 그룹별로 소계가 표시되는지, Grid 하단에 합계가 표시되는지 확인합니다.

25.3소계 이름과 배경색 설정하기

앞의 합계/소계 구하기에서 합계와 소계를 구하는 방법에 대해 알아봤습니다. 합계의 경우 기본 테마에서 Summary 밴드 영역에 대해 정의된 스타일이 있어 한눈에 알아볼 수 있게 되어 있습니다. 그러나 소계의 경우에는 행 사이에 있고 소계라는 어떤 표시도 없기 때문에 사용자가 한눈에 알아볼 수 없습니다. 이는 기본 테마에서 소계에 대해 정의된 스타일이 없기 때문입니다. 소계는 Dataset 연산으로 생성된 논리적인 결과물이라 어느 위치에 어떤 형태로 출력될지 예측할 수 없기 때문에 무조건 일괄 적용되는 테마의 스타일로는 정의하기 힘듭니다. 따라서 개발자가 Dataset 의 내용을 분석하여 화면을 디자인하는 시점에 스타일을 설정해야 합니다.

이번 장에서는 소계에 이름과 배경을 설정하는 방법에 관해 설명합니다. 사용할 예제는 앞 장에서 작성한 예제를 그대로 사용합니다. 예제 샘플이 없다면 앞 장을 참조하여 합계/소계가 적용된 Grid 예제를 먼저 작성하십시오.

25.3.1예제

다음은 Salary Column의 합계를 구하고 Company Column으로 그룹을 지어 그룹별 소계를 계산한 Gird 예제입니다. 합계는 Grid의 가장 하단에 표시되고 소계는 각 그룹의 아래에 새로운 Row로 생성되어 표시됩니다.

그림 25-10sample_grid_31_style_01

sample_grid_31_style.xfdl

소계의 이름은 Cell의 expr 속성을 사용하여 설정합니다. expr 스크립트로 해당 Row가 그룹화되지 않은 일반 Row인지 그룹화되어 생성된 소계 Row인지 판단하여 그에 맞는 결과를 출력합니다. 소계 Row인지는 Row의 레벨 값으로 확인할 수 있습니다. 일반 Row는 0 값을 그룹화된 Row는 1 이상의 값을 갖습니다.

소계의 배경색은 Cell의 cssclass 속성과 스타일을 정의한 XCSS 파일을 사용해 설정합니다. expr 스크립트로 해당 Row가 일반 Row인지 소계 Row인지 판단하여 소계 Row일 경우 XCSS에 정의된 클래스 선택자를 cssclass 속성에 설정합니다.

XCSS(넥사크로 스타일 시트)는 넥사크로플랫폼에서 사용할 수 있는 스타일 시트입니다. 자세한 설명은 스타일 활용 (XCSS) 장을 참조하십시오.

25.3.2예제에서 사용한 핵심 기능

getRowLevel

Dataset을 그룹화했을 경우 지정한 Row의 레벨 값을 반환하는 메소드입니다. 일반 Row의 레벨 값은 0이며, 그룹화한 Row는 그룹화 정도에 따라 1 이상의 값을 갖습니다.

cssclass

XCSS 파일에 정의한 클래스 선택자의 스타일을 Cell에 적용하는 속성입니다. 설정값으로는 클래스 선택자 명을 입력합니다.

expr

수식을 입력하여 그 결과 값을 Cell의 text 속성에 적용하는 속성입니다.

25.3.3예제 구현 방법

1

Grid 생성, 합계/소계 하기

합계/소계 구하기를 참조하여 합계/소계를 포함한 Grid를 생성합니다.

2

소계 이름 설정하기

Company Column을 기준으로 그룹화 했으므로 Company 열에 해당하는 소계 Row에 소계 이름을 출력합니다.

  1. 디자인 화면의 Grid를 더블 클릭하여 Grid Contents Editor를 오픈합니다.

  1. Company Column에서 데이터가 출력되는 Body 밴드 영역의 row1 Cell을 선택 후 expr 속성을 설정합니다.

그림 25-11sample_grid_31_style_02

속성

expr

dataset.getRowLevel(currow)==1?'SUBTOTAL':Company

expr 수식은 현재 Grid에 바인딩 된 데이터셋에서 현재 Row의 레벨 값이 1인 경우에는 현재 Row에 "SUBTOTAL"이라고 문자열을 출력하고 아닌 경우에는 원래 출력해야 하는 Company Column의 Row값을 출력하라는 의미입니다.

현재 Row가 소계 Row인지는 Row의 레벨 값으로 알 수 있습니다. 레벨 값은 일반 Row이면 0 값을, 그룹화된 Row이면 1 이상의 값을 갖습니다. 본 예제의 데이터셋은 Company Column으로 한 번만 그룹화했기에 1 값을 갖게 됩니다. 현재 Row의 인덱스는 currow 변수로, Row의 레벨 값은 getRowLevel 메소드로 구할 수 있습니다.

수식에서 사용된 currow 변수는 expr 수식에서만 사용할 수 있는 특수한 변수입니다. expr에서 사용할 수 있는 변수 및 함수에 대한 내용은 레퍼런스가이드의 GridCellControl 객체를 참조하십시오.

1

XCSS 파일 생성, class 선택자 정의하기

  1. Menu에서 [File > New > Nexacro Style Sheet(.xcss)]를 선택하여 새로운 XCSS 파일을 생성합니다.

그림 25-12new_xcss

New Style Sheet 창에서 XCSS 이름과 경로, 적용 대상을 다음과 같이 설정합니다.

그림 25-13sample_grid_31_style_03

Finish 버튼을 클릭하면 다음과 같이 Project Explorer에 생성된 XCSS 파일이 나타나고 자동으로 Xcss Editor로 오픈됩니다.

그림 25-14sample_grid_31_style_04

  1. Xcss Editor에서 Add Selector 버튼을 클릭하여 새로운 선택자를 추가합니다.

그림 25-15sample_grid_31_style_05

  1. Add Selector 창에서 스타일을 정의할 Grid 컴포넌트를 선택하고 Add 버튼을 클릭합니다. 그러면 아무 내용도 없는 Grid 선택자가 새로 생성됩니다.

스타일을 적용할 대상은 Grid의 자식인 Cell이므로 Cell에 적용되는 선택자 형식은 .Grid .body .row .cell 입니다. Xcss Editor에서 .Grid 선택자 뒤로 한 칸을 띈 후 . 을 입력하면 자동으로 입력 가능한 자식 선택자가 콘텍스트 메뉴로 출력됩니다. body, row, cell을 차례로 선택해줍니다.

그림 25-16sample_grid_31_style_08

  1. .Grid .body .row .cell 뒤에 subtotal이라는 이름으로 클래스 선택자를 추가합니다. 여기서 정한 클래스 선택자 이름이 폼 디자인 화면에서 컴포넌트의 cssclass 속성에 설정할 때 사용됩니다.

.Grid .body .row .cell.subtotal

클래스 선택자는 앞에 선언한 .Grid 선택자와 그 자식 선택자의 선언과 달리 한 칸을 띄우지 않고 붙여서 사용합니다.

  1. Xcss Editor를 사용하여 소계에 적용할 Cell의 스타일을 설정합니다.

다음과 같이 background 속성과 font 속성을 설정한 후 XCSS 파일을 저장합니다. Xcss Editor를 사용하지 않고 사용자가 직접 입력할 수도 있습니다.

그림 25-17sample_grid_31_style_09

2

소계 Row 배경색 설정하기

소계 Row에 배경색을 설정하려면 cssclass 속성을 사용합니다. cssclass에 값이 설정되면 XCSS 파일에서 설정된 값에 해당하는 클래스 선택자를 찾아 정의된 스타일을 컴포넌트에 적용합니다.

  1. Grid를 더블 클릭하여 Grid Contents Editor를 오픈한 후 Body 밴드의 Cell을 모두 선택합니다. 하나 이상의 Cell을 다중 선택 후 특정 속성을 설정하면 선택된 모든 Cell의 속성을 동일한 값으로 한번에 설정할 수 있습니다.

그림 25-18sample_grid_31_style_11

  1. cssclass 속성을 다음과 같이 설정합니다.

그림 25-19sample_grid_31_style_10

속성

cssclass

expr:dataset.getRowLevel(currow)==1?'subtotal':''

설정한 expr 수식은 현재 Grid에 바인딩 된 데이터셋에서 현재 Row의 레벨 값이 1인 경우에는 cssclass 속성에 "subtotal"을 설정하고 아닌 경우에는 설정하지 않는다는 의미입니다. cssclass 속성에 설정되는 "subtotal" 값은 grid_subtotal.xcss에 정의된 클래스 선택자 이름입니다.

3

QuickView로 확인하기

QuickView(Ctrl + F6)를 실행하여 소계 Row에 이름과 배경색이 설정되었는지 확인합니다. cssclass가 설정되는 즉시 디자인 화면에서도 확인할 수 있습니다.

25.4트리 형태로 표현하기

트리는 영어 Tree의 국어 표현으로 나무를 뜻 합니다. 나무는 하나의 가지에서 여러 가지가 뻗어 나오는 모양을 띄는데 데이터간의 연관성을 표현할 때 이 나무와 같은 형태로 표현하는 방법을 트리라 합니다.

Grid는 많은 양의 데이터를 표 형태로 정리하여 보여주는 기능을 합니다. 그러나 어떤 데이터들은 표 형태로 표현하는 것보다 트리 형태로 표현하는 것이 좋은 경우가 있습니다. 예를 들면, 조직 구조 같은 경우가 그렇습니다. 그룹이 있고 그룹 아래 여러 팀이 있고 다시 그 팀 아래 여러 팀원이 존재할 수 있습니다. 이런 경우에는 그룹, 팀, 팀원을 표 형태로 표현하는 것보다 트리 형태로 표현하는 것이 그 관계를 더욱 효과적으로 보여줄 수 있습니다.

다음은 트리의 쓰임새를 잘 보여주고 있는 윈도우 탐색기의 탐색창입니다. 여기서는 디렉토리의 구조를 보여주기 위한 방법으로 트리를 활용하고 있습니다.

그림 25-20sample_grid_32_04

이처럼 트리는 데이터 연관성이 한눈에 들어와 효과적이지만 서로 연관성이 없는 데이터의 경우는 트리 형태가 적합하지 않습니다. 데이터간에 서로 연관성이 있고 부모, 자식 관계로 정리할 수 있는 경우가 트리 구조로 사용하기 좋습니다.

이번 장에서는 Grid를 트리 형태로 표현하는 방법에 대해 설명합니다.

25.4.1예제

다음은 Grid를 트리로 설정한 예제입니다. 윈도우 탐색기의 탐색창처럼 (확장)버튼, (축소)버튼을 사용해 트리를 동작시킬 수 있습니다.

Level 값은 트리의 depth를 설정하기 위한 값으로 depth가 낮을수록 상위 노드가 됩니다. 이 예제에서는 0~2까지의 레벨값을 갖는데 0은 회사, 1은 팀, 2는 팀원을 의미합니다.

그림 25-21sample_grid_32_03

sample_grid_32.xfdl

25.4.2예제에서 사용한 핵심 기능

displaytype

Grid의 Cell에서 데이터가 표시되는 형식을 설정하는 속성입니다. 아무 값도 설정하지 않으면 normal이 기본값으로 설정됩니다.

edittype

Grid의 Cell에서 편집 창의 형식을 설정하는 속성입니다. 아무 값도 설정하지 않으면 none이 기본값으로 설정됩니다.

treelevel

Cell이 트리 형식일 때 트리의 레벨값으로 사용할 컬럼을 설정하는 속성입니다.

textAlign

Cell에 표시되는 데이터의 가로 정렬 방식을 설정하는 속성입니다.

treeusecheckbox

Cell이 트리 형식일 때 체크박스를 보여줄지 설정하는 속성입니다. 체크박스를 사용하려면 Cell의 treecheck 속성도 같이 설정해야 합니다.

25.4.3예제 구현 방법

1

컴포넌트 생성하기

툴바에서 그리드 를 선택한 후, Form 위에 적당한 크기로 드래그하여 생성합니다. 그냥 폼에 대고 클릭하면 기본 크기로 생성됩니다.

2

Dataset 생성과 데이터 입력하기

Grid에 출력할 데이터 아이템 목록을 가진 Dataset을 생성합니다.

  1. 툴바에서 Dataset 을 선택한 후, 폼 위 적당한 공간에 클릭하여 Dataset을 생성합니다.

  1. 생성한 Dataset에 데이터 아이템 목록을 입력합니다. Invisible Objects 영역에 있는 Dataset을 더블 클릭하면 Dataset Editor가 뜨는데 Columns와 Rows에 아래 그림과 같이 입력합니다.

그림 25-22sample_grid_32_02

3

Dataset 바인딩

Dataset을 Grid 컴포넌트에 바인딩합니다.

Invisible Objects 영역에 있는 Dataset을 Form에 생성한 Grid 컴포넌트로 드래그 앤 드롭하면 바인딩이 완료됩니다.

4

Grid 속성 설정하기

체크박스를 사용하지 않도록 Grid의 treeusecheckbox 속성을 다음과 같이 설정합니다. 아무 설정도 하지 않으면 'true'로 적용되어 체크박스가 보여집니다.

속성

treeusecheckbox

false

treeusecheckbox 속성은 트리에 체크박스가 보여질지 여부만 설정하며 체크박스가 실제 동작하기 위해서는 셀의 treecheck 속성을 같이 설정해야 합니다.

5

Cell 속성 설정하기

Grid Contents Editor를 열어서 Label 컬럼의 Cell 속성을 다음과 같이 설정합니다.

속성

displaytype

treeitemcontrol

edittype

tree

treelevel

bind:Level

textAlign

left

6

QuickView로 확인하기

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다.

Level 값(0~2)에 따라 트리가 알맞게 보여지는지 확인합니다. 값이 작을수록 트리의 상위에 위치합니다.
확장/축소 버튼을 눌러 트리의 동작을 확인합니다.

25.5트리에서 편집하기

Grid를 트리 형태로 만들었을 경우에는 edittype 속성을 tree로 설정했기 때문에 편집할 수 없는 상태가 됩니다. 트리 형태의 Grid Cell을 편집하려면 Cell의 이벤트를 사용하여 해당 컬럼을 편집 가능하도록 해줘야 합니다.

이번 장에서는 Grid를 트리 형태로 만들었을 경우에 Grid Cell을 편집하는 방법에 대해 설명합니다.

25.5.1예제

다음은 트리 형태로 설정한 Grid 예제입니다. 그러나 보통 트리와는 다르게 편집이 가능하다록 되어 있어 Cell을 더블클릭하면 내용을 수정할 수 있습니다.

그림 25-23sample_grid_33_01

sample_grid_33.xfdl

25.5.2예제에서 사용한 핵심 기능

edittype

Grid의 Cell에서 편집 창의 형식을 설정하는 속성입니다. 아무 값도 설정하지 않으면 none이 기본값으로 설정됩니다.

setCellProperty

Cell의 특정 속성값을 설정하는 메소드입니다.

editautoselect

Cell의 편집 영역을 활성화했을 때 텍스트를 자동으로 전체 선택할지 설정하는 속성입니다.

autoenter

edittype 속성이 설정된 경우 해당 Cell 선택 시 자동으로 편집 모드로 변경하도록 설정하는 속성입니다.

setCellPos

특정 Cell에 포커스를 이동하는 메소드입니다. 예제에서는 Cell 더블 클릭 시 바로 편집할 수 있도록 포커스를 다시 지정해주는 역할을 합니다.

25.5.3예제 구현 방법

1

컴포넌트 생성하기

툴바에서 그리드 를 선택한 후, Form 위에 적당한 크기로 드래그하여 생성합니다. 그냥 폼에 대고 클릭하면 기본 크기로 생성됩니다.

2

Dataset 생성과 데이터 입력하기

Grid에 출력할 데이터 아이템 목록을 가진 Dataset을 생성합니다.

  1. 툴바에서 Dataset 을 선택한 후, 폼 위 적당한 공간에 클릭하여 Dataset을 생성합니다.

  1. 생성한 Dataset에 데이터 아이템 목록을 입력합니다. Invisible Objects 영역에 있는 Dataset을 더블 클릭하면 Dataset Editor가 뜨는데 Columns와 Rows에 아래 그림과 같이 입력합니다.

그림 25-24sample_grid_32_02

3

Dataset 바인딩

Dataset을 Grid 컴포넌트에 바인딩합니다.

Invisible Objects 영역에 있는 Dataset을 Form에 생성한 Grid 컴포넌트로 드래그 앤 드롭하면 바인딩이 완료됩니다.

4

Grid 속성 설정하기

체크박스를 사용하지 않도록 Grid의 treeusecheckbox 속성을 다음과 같이 설정합니다. 아무 설정도 하지 않으면 'true'로 적용되어 체크박스가 보여집니다. 그리고 해당 Cell에 포커스가 갔을 때 바로 편집 모드로 변경되도록 autoenter 속성을 지정합니다.

속성

treeusecheckbox

false

autoenter

select

treeusecheckbox 속성은 트리에 체크박스가 보여질지 여부만 설정하며 체크박스가 실제 동작하기 위해서는 셀의 treecheck 속성을 같이 설정해야 합니다.

5

Cell 속성 설정하기

Grid Contents Editor를 열어서 Label 컬럼의 Cell 속성을 다음과 같이 설정합니다.

속성

displaytype

treeitemcontrol

edittype

tree

treelevel

bind:Level

textAlign

left

editautoselect

true

6

Cell 편집 모드 전환 이벤트 함수 작성하기

Cell을 더블 클릭했을 경우 편집 모드로 전환되도록 처리하는 이벤트 함수를 작성합니다.

this.Grid00_oncelldblclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    //if tree cell column
    if(e.col == 0)
    {
        var nCellIdx = this.Grid00.currentcell;
        this.Grid00.setCellProperty("body", nCellIdx, "edittype", "normal");
        this.Grid00.setCellPos(nCellIdx);
    }
    
};

Cell의 내용을 변경한 후 선택 영역을 변경하면 다시 트리 형태로 보이도록 처리하는 이벤트 함수를 작성합니다.

this.Grid00_onselectchanged = function(obj:nexacro.Grid,e:nexacro.GridSelectEventInfo)
{
    var nCellIdx = this.Grid00.currentcell;
    this.Grid00.setCellProperty("body", nCellIdx, "edittype", "tree");
    
};

7

QuickView로 확인하기

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다.

트리 Cell을 더블 클릭하여 편집 모드로 변경되는지 확인합니다. 편집 후 다른 셀을 클릭하거나 Enter 키를 입력하면 변경된 내용이 반영되고 다시 트리 형태로 변경되는지 확인합니다.

25.6헤더 이벤트를 이용한 정렬하기

정렬은 데이터를 조건에 따라 일정한 순서가 되도록 배열하는 작업을 의미합니다. 특히 많은 양의 데이터를 그리드로 보여줄 때 사용자가 원하는 데이터를 쉽게 찾을 수 있도록 하려면 정렬은 필수입니다.

그리드에서 정렬 기능은 데이터셋의 keystring 메소드를 사용해 구현합니다. 자세한 사용법은 관련 요소를 참조하시기 바랍니다.

25.6.1예제

다음은 keystring 메소드를 사용해 정렬을 수행하는 Grid 예제입니다.

각 헤더 Cell을 클릭하면 헤더 Cell에 오름차순(▲), 내림차순(▼)이 표시되며 해당 컬럼이 정렬됩니다.

그림 25-25sample_grid_34_01

sample_grid_34.xfdl

25.6.2예제에서 사용한 핵심 기능

keystring

Dataset에 로드된 데이터를 그룹/정렬할 기준이 되는 조건식을 설정하는 속성입니다. 인수를 설정할 때 그룹 타입을 명시해야 하는데 'S'는 정렬, 'G'는 그룹을 의미합니다. 그룹 타입을 생략하면 'G'를 기본 값으로 적용합니다.

this.Dataset00.set_keystring( "S:column0" );
this.Dataset00.set_keystring( "S:column0+column0" );
this.Dataset00.set_keystring( "G:+column0,S:-column1" );
objects

폼에 등록된 모든 오브젝트(컴포넌트) 목록을 갖는 속성입니다. 배열 타입으로 다음과 같이 각 오브젝트에 접근할 수 있습니다.

var object1 = this.objects[2];
var object2 = this.objects["Grid00"];
getCellCount

Grid에서 특정 밴드에 정의된 Cell의 개수를 반환하는 메소드입니다.

var nCount = this.Grid00.getCellCount( "head" );
getCellText

지정된 위치의 Cell Text 속성값을 반환하는 메소드입니다.

/* Body 밴드의 첫번재 Row에서 두번째 Cell의 Text 값을 반환 */
var strText = this.Grid00.getCellText(0, 1);
getCellProperty

지정한 Cell의 특정 속성값을 반환하는 메소드입니다.

setCellProperty

지정한 Cell의 특정 속성값을 설정하는 메소드입니다.

split

문자열을 여러 개의 부분 문자열로 분할하여 배열로 반환하는 메소드입니다.

substr

문자열에서 지정한 위치부터 지정한 길이만큼의 문자열로 잘라 반환하는 메소드입니다.

25.6.3예제 구현 방법

1

화면 구성하기

툴바에서 Grid 컴포넌트를 예제의 그림과 같이 적절히 배치합니다.

2

Dataset 생성과 데이터 입력하기

Grid에 출력할 데이터 아이템 목록을 가진 Dataset을 생성합니다.

  1. 툴바에서 Dataset 을 선택한 후, 폼 위 적당한 공간에 클릭하여 Dataset을 생성합니다.

  1. 생성한 Dataset에 데이터 아이템 목록을 입력합니다. Invisible Objects 영역에 있는 Dataset을 더블 클릭하면 Dataset Editor가 뜨는데 Columns와 Rows에 아래 그림과 같이 입력합니다.

그림 25-26sample_grid_25_02

3

Dataset 바인딩

Dataset을 Grid 컴포넌트에 바인딩합니다.

Invisible Objects 영역에 있는 Dataset을 Form에 생성한 Grid 컴포넌트로 드래그 앤 드롭하면 바인딩이 완료됩니다.

4

정렬 기능 구현

Form에 있는 Grid를 선택한 후 onheadclick 이벤트 함수를 다음과 같이 추가합니다.

this.Grid00_onheadclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    var objDs = this.objects[obj.binddataset];
                                         
    for (var i = 0; i < obj.getCellCount("head"); i++)
    {        
        var sHeadText = obj.getCellText(-1, i);
        var nLen      = sHeadText.length - 1;
        
        /* In case of the clicked head cell */
        if (i == e.cell)
        {
            var sColId = (obj.getCellProperty("body", e.col,"text")).toString().split(":");
            
            /* If the previous sort in ascending order, it will be sorted in descending order */
            if (sHeadText.substr(nLen) == "▲") 
            {
                obj.setCellProperty( "head", i, "text", sHeadText.substr(0, nLen)+ "▼");
                objDs.set_keystring("S:-" + sColId[1]);
            }
            /* If the previous sort in descending order, it will be sorted in ascending order */
            else if (sHeadText.substr(nLen) == "▼") 
            {
                obj.setCellProperty( "head", i, "text", sHeadText.substr(0, nLen)+ "▲");
                objDs.set_keystring("S:+" + sColId[1]);
            }
            /* If first sort, it will sort in ascending order */
            else 
            {
                obj.setCellProperty( "head", i, "text", sHeadText+"▲");
                objDs.set_keystring("S:+" + sColId[1]);
            }
        }
        /* In case of it's not the clicked head cell */
        else
        {

            /* Remove the arrow indication is displayed in the head cell which are arranged previously */
            if (sHeadText.substr(nLen) == "▲" || sHeadText.substr(nLen) == "▼") 
            {
                obj.setCellProperty( "head", i, "text", sHeadText.substr(0, nLen));
            }

        }
    }        
};

5

QuickView로 확인하기

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다.

위치를 변경하려는 Column의 헤더를 마우스로 드래그하여 원하는 위치에 드롭합니다.

25.7전체 선택/해제 하기

Grid 사용시 필요한 데이터만을 선택하여 처리해야 하는 경우가 있습니다. 이럴 때 Grid의 체크박스 기능을 사용하면 편리하게 데이터를 선택할 수 있습니다.

Grid에서 데이터 선택은 체크박스의 기본 기능이므로 별다른 처리가 필요 없지만 데이터의 전체 선택/해제의 경우에는 스크립트로 기능을 구현해야 합니다.

이번 장에서는 Grid 체크박스의 전체 선택/해제 하는 방법에 대해 설명합니다.

25.7.1예제

다음은 체크박스로 설정한 Grid 예제입니다.

헤드 컬럼의 체크박스를 클릭하면 전체 선택/해제 할 수 있습니다.

그림 25-27sample_grid_35_01

sample_grid_35.xfdl

25.7.2예제에서 사용한 핵심 기능

displaytype

Grid의 Cell에서 데이터가 표시되는 형식을 설정하는 속성입니다. 아무 값도 설정하지 않으면 'normal'이 기본값으로 설정됩니다.

edittype

Grid의 Cell에서 편집 창의 형식을 설정하는 속성입니다. 아무 값도 설정하지 않으면 'none'이 기본값으로 설정됩니다.

onheadclick

Grid에서 Head 영역의 Cell을 클릭했을 때 발생하는 이벤트입니다.

getRowCount

Dataset에서 Row의 개수를 구하는 메소드입니다.

setColumn

Dataset에서 지정한 Row의 Column에 해당하는 값을 변경하는 메소드입니다.

getCellProperty

Cell의 특정 속성 값을 반환하는 메소드입니다.

setCellProperty

Cell의 특정 속성 값을 설정하는 메소드입니다.

25.7.3예제 구현 방법

1

화면 구성하기

툴바에서 Grid 컴포넌트를 예제의 그림과 같이 적절히 배치합니다.

2

Dataset 생성과 데이터 입력하기

Grid에 출력할 데이터 아이템 목록을 가진 Dataset을 생성합니다.

  1. 툴바에서 Dataset 을 선택한 후, 폼 위 적당한 공간에 클릭하여 Dataset을 생성합니다.

  1. 생성한 Dataset에 데이터 아이템 목록을 입력합니다. Invisible Objects 영역에 있는 Dataset을 더블 클릭하면 Dataset Editor가 뜨는데 Columns와 Rows에 아래 그림과 같이 입력합니다.

그림 25-28sample_grid_35_02

3

Dataset 바인딩

Dataset을 Grid 컴포넌트에 바인딩합니다.

Invisible Objects 영역에 있는 Dataset을 Form에 생성한 Grid 컴포넌트로 드래그 앤 드롭하면 바인딩이 완료됩니다.

4

Grid 설정하기

  1. Grid Contents Editor를 열어 Check 컬럼을 삭제합니다.

  1. Grid의 가장 왼쪽에 체크박스를 표시할 새로운 컬럼을 생성합니다. 컬럼의 생성은 다음과 같이 Add Left Column 메뉴를 사용합니다.

그림 25-29sample_grid_35_03

  1. 새로 생성한 컬럼의 헤드 셀의 속성을 다음과 같이 설정합니다.

속성

displaytype

checkboxcontrol

edittype

checkbox

  1. 새로 생성한 컬럼의 바디 셀의 속성을 다음과 같이 설정합니다.

속성

displaytype

checkboxcontrol

edittype

checkbox

text

bind:Check

CheckBox 컴포넌트는 생성하면 바로 동작시킬 수 있지만 Grid의 체크박스는 반드시 Dataset을 바인딩해줘야 동작시킬 수 있습니다.

1

Grid 이벤트 함수 작성하기

그림 25-30sample_grid_35_04

Grid을 선택한 후 onheadclick 이벤트 함수를 생성하고 다음과 같이 스크립트를 작성합니다.

this.Grid00_onheadclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    //체크박스로 설정한 첫 번째 head 컬럼을 클릭했을 경우에 gf_setCheckAll 함수를 호출
    if(e.cell == 0)
    {
        this.gf_setCheckAll(obj, e);
    }
};

체크박스 전체 선택/해제를 처리하는 함수를 다음과 같이 작성합니다.

this.gv_isCheckAll = 0;
this.gf_setCheckAll = function(obj:Grid, e:GridClickEventInfo)
{
    var strColID = obj.getCellProperty("body", e.cell, "text").replace(/bind:/i, "");
        
    //체크박스가 체크되어 있으면 체크 해제 
    //체크되어 있지 않으면 체크
    this.gv_isCheckAll = (this.gv_isCheckAll ? 0 : 1);
    
    //Dataset의 이벤트를 끔
    //this.Dataset00.enableevent = false;
    
    //check to body column
    for(var i=0; i< this.Dataset00.getRowCount(); i++)
    {
        this.Dataset00.setColumn(i, strColID, this.gv_isCheckAll);
    }
    
    //check to head column
    obj.setCellProperty("Head", 0, "text", this.gv_isCheckAll);

    //Dataset의 이벤트를 켬
    //this.Dataset00.enableevent = true;

}

Dataset은 데이터를 변경할 때 마다 이벤트가 발생는데 잦은 이벤트 발생은 처리 속도 지연이나 화면 깜빡임 등의 증상으로 나타날 수 있습니다. 따라서 데이터가 많은 경우에는 변경 전에 이벤트를 껐다가 변경 후에 다시 이벤트를 키도록 처리하면 그런 증상을 완화할 수 있습니다. Dataset 이벤트의 설정/해제는 enableevent 속성을 사용합니다.

replace 함수 안에 정규식 i 옵션을 추가해 대소문자 상관없이 치환하도록 설정했습니다.

2

QuickView로 확인하기

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다.

체크박스로 설정된 Grid의 헤드 셀을 클릭하여 전체 선택/해제가 동작하는지 확인합니다.

25.8Grid간의 복사/붙여넣기

컴퓨터를 사용할 때 복사(Ctrl+c) / 붙여넣기(Ctrl+v) 기능은 자주 사용됩니다. 마찬가지로 넥사크로플랫폼에서도 기능을 구현하면 복사/붙여넣기를 사용할 수 있습니다.

일반적으로 컴퓨터 사용시의 복사/붙여넣기는 클립보드라는 OS에서 제공하는 임시 메모리 공간을 사용합니다. 그러나 웹 환경에서는 보안상의 문제로 OS에서 제공하는 클립보드를 이용하는데 제한이 있습니다. 따라서 개발자는 어떤 환경인지를 먼저 파악한 후 복사/붙여넣기 기능을 구현해야 합니다. 일례로 넥사크로플랫폼 런타임이나 인터넷익스플로러의 경우에는 클립보드를 사용할 수 있습니다. 그러나 그 외의 브라우저에서는 클립보드로의 접근이 허용되지 않기 때문에 스크립트에서 변수나 컴포넌트같은 별도의 임시 저장 공간을 마련해야 합니다.

본 장에서는 Grid 간의 데이터를 복사/붙여넣기 하는 기능을 구현하고 그 방법에 대해 설명합니다.

25.8.1예제

다음은 Grid에서 Grid로 Row를 복사/붙여넣기 하는 예를 보여줍니다.

그림 25-31sample_grid_37_01

sample_grid_37.xfdl

복사/붙여넣기 동작은 윈도우에서의 동작과 동일합니다. 우선 위 Grid에서 복사하려는 Row를 선택한 후 Ctrl + c를 입력합니다. 그런 후 다른 Grid에서 붙여넣고 싶은 위치를 클릭한 후 Ctrl + v로 붙여넣습니다.

삭제 동작은 먼저 삭제하려는 Row를 선택한 후 Delete 키를 입력합니다.

본 예제에서는 Row 단위로 처리했지만 기능 구현에 따라 Col 단위나 영역으로 동작하도록 할 수도 있습니다.

25.8.2예제에서 사용한 핵심 기능

selectstartrow

Grid에서 선택된 영역의 시작 셀의 Row 인덱스를 갖는 읽기전용 속성입니다.

selectendrow

Grid 에서 선택된 영역의 마지막 셀의 Row 인덱스를 갖는 읽기전용 속성입니다.

selectstartcol

Grid 에서 선택된 영역의 시작 셀의 Column 인덱스를 갖는 읽기전용 속성입니다.

selectendcol

Grid 에서 선택된 영역의 마지막 셀의 Column 인덱스를 갖는 읽기전용 속성입니다.

getCellValue

해당 위치 Cell의 text 속성에 설정된 값을 반환하는 메소드입니다.

getCellCount

Grid에서 특정 밴드에 정의된 Cell의 개수를 반환하는 메소드입니다.

getCellPos

Cell의 인덱스 값을 반환하는 메소드입니다. 각 밴드에 정의된 Cell은 좌상단부터 우하단까지 순차적으로 Cell 인덱스를 갖고 있기 때문에 이를 위치 값으로 활용할 수 있습니다.

getCellProperty

지정한 Cell의 특정 속성값을 반환하는 메소드입니다.

getRowCount

Dataset에서 Row의 개수를 구하는 메소드입니다.

deleteRow

Dataset에서 지정한 Row를 삭제하는 메소드입니다.

rowposition

Dataset에서 현재 선택된 Row의 인덱스 값을 갖는 속성입니다.

setColumn

Dataset에서 지정한 Row의 Column에 해당하는 값을 변경하는 메소드입니다.

keycode

키보드로 입력된 키에 해당하는 코드값을 갖는 속성입니다

ctrlkey

이벤트 발생시 Ctrl 키가 눌렸는지 여부를 확인하는 속성입니다.

split

문자열을 여러 개의 부분 문자열로 분할하여 배열로 반환하는 메소드입니다.

substr

문자열에서 지정한 위치부터 지정한 길이만큼의 문자열로 잘라 반환하는 메소드입니다.

25.8.3예제 구현 방법

1

컴포넌트 생성하기

툴바에서 Grid 컴포넌트 두 개를 예제의 그림과 같이 적절히 배치합니다. Grid 생성 작업을 한번 더 반복하여 두 개의 Grid를 폼에 배치합니다.

2

Dataset 생성과 데이터 입력하기

Grid에 출력할 데이터 아이템 목록을 가진 Dataset을 생성합니다.

  1. 툴바에서 Dataset 을 선택한 후, 폼 위 적당한 공간에 클릭하여 Dataset을 생성합니다. Grid00과 Grid01에 바인딩할 Dataset을 두 개 생성해야 하므로 같은 작업을 한 번 더 반복합니다.

  1. 생성한 Dataset에 데이터 아이템 목록을 입력합니다. Invisible Objects 영역에 있는 Dataset을 더블 클릭하면 Dataset Editor가 뜨는데 Columns와 Rows에 아래 그림과 같이 입력합니다.

  • Dataset00의 아이템 목록 작성

그림 25-32sample_grid_25_02

  • Dataset01의 아이템 목록 작성

Column만 만들고 데이터는 입력하지 않습니다.

그림 25-33sample_grid_37_02

3

Dataset 바인딩

Dataset을 Grid 컴포넌트에 바인딩합니다. Invisible Objects 영역에 있는 Dataset을 Form에 생성한 Grid 컴포넌트로 드래그 앤 드롭하여 바인딩합니다.

Grid00에는 Dataset00을 Grid01에는 Dataset01을 바인딩합니다.

4

Grid 이벤트 함수 작성하기

Grid의 onkeydown 이벤트 함수를 다음과 같이 작성합니다. 두 Grid에서 공통적으로 사용할 것이므로 두 Grid 모두 Grid_onkeydown 이벤트 함수를 연결합니다.

스크립트에 대한 자세한 설명은 주석을 참조하시기 바랍니다.

var Buff = null;

this.Grid_onkeydown = function(obj:nexacro.Grid,e:nexacro.KeyEventInfo)
{
    //Ctrl 키가 입력됐는지 확인
    if (e.ctrlkey)
    {
        //Ctrl 키가 입력된 상태에서 c 키가 입력됐는지 확인
        if (e.keycode == 67)
        {
            //현재 Grid에서 선택되어 있는 column, row 정보를 얻어옴
            var nStartrow = obj.selectstartrow;
            var nEndrow = obj.selectendrow;
            var nStartCol = obj.selectstartcol;
            var nEndCol = obj.selectendcol;
            
            //임시로 데이터를 저장할 변수
            var sClip = "";
            var sSpr  = "    ";
                
            /*
            multirow로 선택하는 경우에 몇 번 반복문을 수행해야 할지 회수를 설정
            selectstartrow, selectendrow에는 선택된 row 정보가 배열 형태로 저장되어 있음
            */
            var nLoopCnt = nStartrow.length;
            
            /*
            row 단위 선택인 경우 column 정보는 -1로 나옴
            따라서 실제 column의 시작, 끝 index 값으로 설정
            */
            if(nStartCol == -1 && nEndCol == -1)
            {
                var objDs    = this.objects[obj.binddataset];    
                
                nStartCol = 0;
                nEndCol = objDs.colcount-1;
            }

            //선택한 Row의 데이터를 추출
            for(var k=0; k < nLoopCnt; k++)
            {
                for (var i = nStartrow[k]; i <= nEndrow[k]; i++) 
                {
                    for (var j = nStartCol; j <= nEndCol; j++) 
                    {                
                        if (j < nEndCol) 
                        {
                            sClip += obj.getCellValue(i, j) + sSpr;
                        } 
                        else 
                        {
                            sClip = sClip + obj.getCellValue(i, j) +  "\n";
                        }
                    }
                }
            
            }

            //추출한 데이터를 Textarea에 복사
            Buff = sClip.substr(0, sClip.length-1);        
        }
        
        //Ctrl 키가 입력된 상태에서 v 키가 입력됐는지 확인
        else if (e.keycode == 86)
        {
            var nIndex = 0;
            var objDs = this.objects[obj.binddataset];
            var nCellCnt = obj.getCellCount("body");
            var nCellPos = obj.getCellPos();
            var nRowPos = objDs.rowposition;

            /*
            Buff 변수에 저장되어 있는 값을 변수로 받아온 후 개행문자를 기준으로
            잘라 배열 형태로 저장
            */
            var sClip = Buff;
            var arrRow = sClip.split("\n");
            var arrCol = new Array();
            
            for (var i = 0; i <arrRow.length; i++) 
            {                
                /*
                Row를 탭문자를 기준으로 잘라 배열 형태로 저장
                */
                arrCol = arrRow[i].split("    "); //tab

                /*
                현재 Row 위치를 기준으로 붙여 넣으려는 Row가 현재 Row보다 큰 경우
                빈 Row를 추가
                */
                if (objDs.getRowCount() <= nRowPos) 
                {
                    objDs.addRow();
                }
                
                /*
                현재 선택한 Row 위치에 Row를 붙여 넣음
                */
                for (var j = 0; j < objDs.getColCount(); j++) 
                {    
                    objDs.setColumn(nRowPos, j, arrCol[nIndex++]);
                }                
                
                /*
                붙여 넣기할 다음 Row로 위치를 이동
                */
                nRowPos++;
                objDs.set_rowposition(nRowPos);
                nIndex = 0;
            }            
        }
    }
    
    //Delete 키가 입력됐는지 확인
    if (e.keycode == 46)
    {
        var objDs = this.objects[obj.binddataset];
    
        //현재 Grid에서 선택되어 있는 row 정보를 얻어옴
        var nStartrow = obj.selectstartrow;
        var nEndrow = obj.selectendrow;

        /*
        multirow로 선택하는 경우에 몇 번 반복문을 수행해야 할지 회수를 설정
        selectstartrow, selectendrow에는 선택된 row 정보가 배열 형태로 저장되어 있음
        */        
        var nLoopCnt = nStartrow.length;

        //선택한 Row를 삭제
        for(var k=nLoopCnt; k >= 0; k--)
        {
            for (var i = nEndrow[k]; i >= nStartrow[k]; i--) 
            {                
                objDs.deleteRow(i);
            }        
        }
    }
    
}

5

QuickView로 확인하기

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다.

Grid를 마우스와 키보드를 사용하여 선택한 후 Ctrl +c로 복사하고 다른 Grid에 Ctrl + v로 붙여넣습니다.

Row를 선택한 후 Delete 키를 눌러 삭제가 되는지 확인합니다.

25.9페이지 기능 구현하기

Grid에서 데이터가 많아 한번에 다 표시할 수 없는 경우에 몇 개 단위로 페이지로 나눠 표시하면 데이터를 한눈에 볼 수 있어 편리합니다.

25.9.1예제

다음은 많은 양의 데이터를 효과적으로 볼 수 있도록 페이지 기능을 추가한 Grid 예제입니다.

상단에 Inquire 버튼을 누르면 Grid에 데이터를 로딩하고 한번에 10개씩 볼 수 있도록 페이지를 나눠 표시합니다. 하단의 페이지 네비게이션 바를 살펴보면 앞 페이지로 이동하는 Prev 버튼, 뒤 페이지로 이동하는 Next 버튼 그리고 페이지로 직접 이동하는 숫자 버튼이 있습니다.

Inquire 버튼은 한번 동작시키면 데이터를 로딩한 후 사라집니다. 이는 데이터 로딩을 반복해서 수행하지 못 하도록 버튼을 안 보이게 처리했기 때문입니다.

그림 25-34sample_grid_38_01

sample_grid_38.xfdl

25.9.2예제에서 사용한 핵심 기능

visible

컴포넌트를 화면에 표시할지 설정하는 속성입니다. false로 설정하면 화면에 표시되지 않습니다.

filter

Dataset에 로드한 데이터를 조건에 맞는 데이터만 볼 수 있게 필터링하는 메소드입니다.

clearData

Dataset의 컬럼 정보를 제외하고 모든 데이터(Row)를 삭제하는 메소드입니다.

copyData

현재 Dataset에 인수로 지정한 Dataset의 데이터(Row)를 복사하는 메소드입니다.

getRowcount

Dataset의 Row 개수를 구하는 메소드입니다.

25.9.3예제 구현 방법

1

컴포넌트 생성하기

그리드 컴포넌트를 하나 생성합니다. 그리고 데이터 조회에 사용할 버튼 을 생성합니다.

2

Page 네비게이션 바 만들기

다음과 같이 페이지 전환에 사용할 네비게이션 바를 만듭니다.

그림 25-35sample_grid_38_02

네비게이션의 바의 베이스로 사용할 Div 컴포넌트를 하나 생성하고 Div 내부에 페이지 선택 버튼으로 사용할 Static 컴포넌트를 12개 생성합니다. 생성한 Static 컴포넌트는 앞에서부터 다음 표와 같이 설정합니다.

ID

속성

stt_prev

text

Prev

visible

false

stt_0

text

1

visible

false

stt_1

text

2

visible

false

stt_2

text

3

visible

false

stt_3

text

4

visible

false

stt_4

text

5

visible

false

stt_5

text

6

visible

false

stt_6

text

7

visible

false

stt_7

text

8

visible

false

stt_8

text

9

visible

false

stt_9

text

10

visible

false

stt_next

text

Next

visible

false

3

Dataset 생성과 데이터 입력하기

Grid에 출력할 데이터 아이템 목록을 가진 Dataset을 2개 생성한 후 ID를 각각 ds_server, ds_client 로 설정합니다. ds_server는 서버로부터 transaction을 통해 내려받은 데이터라 가정하며 ds_client는 Grid에 바인딩해 UI에서 사용합니다. 본 예제는 서버와의 트랜잭션을 가정합니다.

  1. ds_server에 데이터를 입력하는데 입력해야 할 데이터의 양이 많으므로 XML 형태의 데이터를 직접 입력할 수 있는 Dataset Source Editor를 사용합니다. Dataset Source Editor는 Dataset을 더블 클릭하여 Dataset Editor를 띄운 후 하단의 Source 탭을 클릭하면 나옵니다.

그림 25-36sample_grid_38_03

다음 링크의 XML 데이터를 Dataset Source Editor를 사용하여 한번에 복사/붙여넣기 합니다.

  1. ds_client에 데이터를 입력합니다. Dataset을 더블 클릭하여 Dataset Editor를 띄운 후 다음과 같이 데이터는 입력하지 않고 컬럼만 입력합니다.

그림 25-37sample_grid_38_04

4

Dataset 바인딩

ds_client를 Grid 컴포넌트로 드래그 앤 드롭하여 바인딩합니다. 데이터가 없으므로 컬럼명만 표시됩니다.

5

Grid 속성 설정하기

Grid Contents Editor를 열어 헤드 컬럼과 보디 컬럼을 다음과 같이 설정합니다.

컬럼

(head) row0의 text

(body) row1의 text

col0

No

bind:ROWNO

col1

Book Title

bind:BOOK_NM

col2

Publisher

bind:PRESS_NM

col3

Author

bind:EDITOR_NM

6

Inquire 버튼의 클릭 이벤트 함수 작성하기

Inquire 버튼의 onclick 이벤트 함수를 생성하고 다음과 같이 작성합니다.

/*
list inquire
*/
this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    obj.set_visible(false);
    this.div_page.set_visible(true);
    
    /* transaction call */
    
    this.fn_callback("tr1", 0, "success");    
};

예제 코드 중간의 transaction call이라 쓰여진 주석 부분에 트랜잭션 함수를 호출하는 코드를 작성해 넣으면 이 예제를 실제 상황에서도 사용할 수도 있습니다.

7

Page 네비게이션 버튼의 클릭 이벤트 함수 작성하기

Div와 Static 컴포넌트로 만든 네비게이션 바에서 각 컴포넌트의 onclick 이벤트 함수를 작성합니다.

다음 코드를 보면 세 개의 onclick 이벤트 함수가 있습니다. div_page_stt_onclick은 1~10까지의 숫자 버튼을 모두 연결하고 div_page_stt_prev_onclick, div_page_stt_next_onclick은 각각 Prev, Next 버튼과 연결합니다.

/*
click event function for page number(1~10)
*/
this.div_page_stt_onclick = function(obj:Static,  e:nexacro.ClickEventInfo)
{
    var iNo = new Number(obj.text);
    var iFirstNum = (iNo-1) * this.gv_iMaxPageNum + 1;
    var iLastNum = iFirstNum + this.gv_iMaxPageNum;

    this.fn_SetStyle();
    obj.set_color("red");
    
    this.ds_client.filter("");
    this.ds_client.filter("ROWNO >= " + iFirstNum+" && ROWNO < " + iLastNum);
}

/*
click event function for prev
*/
this.div_page_stt_prev_onclick = function(obj:Static,  e:nexacro.ClickEventInfo)
{

    this.gv_iStartPageNo = this.gv_iStartPageNo - 1;
    
    /* transaction function call */
    
    this.fn_callback("tr1", 0, "success");
}

/*
click event function for next
*/
this.div_page_stt_next_onclick = function(obj:Static,  e:nexacro.ClickEventInfo)
{

    this.gv_iStartPageNo = this.gv_iStartPageNo + 1;
    
    /* transaction function call */
    
    this.fn_callback("tr1", 0, "success");
}

8

전역변수 선언하기

스크립트의 가장 상단에 다음과 같이 변수를 선언합니다. 다음 변수들은 초기 설정값으로 사용하며 이 값을 변경시키면 그에 맞게 화면이 재구성됩니다.

this.gv_iStartPageNo    = 0;        /* current page number */
this.gv_iUnitSelRowNo   = 100;    /* number of rows to retrieve when server is called once */
this.gv_iStartSelRowNo  = 1;        /* row number to start when calling server */
this.gv_iMaxPageNum     = 10;    /* maximum page number to display on screen */
this.gv_iServerRowCount = 0;    /* number of rows retrieved from the server */

9

Page 네비게이션 설정 함수 작성하기

다음은 사용자의 조작에 의해 Page 네비게이션의 버튼을 설정하는 함수입니다.

/*
page number setting
*/
this.fn_SetPageNo = function()
{
    var sPage = this.gv_iStartPageNo * this.gv_iMaxPageNum;
    
    /* prev button setting */
    if (this.gv_iStartPageNo < 1)
    {
        this.div_page.form.stt_prev.set_visible(false);
    } 
    else 
    {
        this.div_page.form.stt_prev.set_visible(true);
    }

    /* next button setting */
    if (this.gv_iServerRowCount < this.gv_iUnitSelRowNo)
    {
        this.div_page.form.stt_next.set_visible(false);
    }
    else
    {
        this.div_page.form.stt_next.set_visible(true);
    }

    /* page button setting */
    for (var i = 0; i < this.gv_iMaxPageNum; i++)
    {
        this.div_page.form.components["stt_"+i].set_visible(true);
        
        this.div_page.form.components["stt_"+i].set_text(sPage+i+1);
        
        if (this.gv_iServerRowCount < (i * this.gv_iMaxPageNum))
        {
            this.div_page.form.components["stt_"+i].set_visible(false);
        } 
        else 
        {
            this.div_page.form.components["stt_"+i].set_visible(true);
        }
    }    
}

/*
style settings
*/
this.fn_SetStyle = function()
{
    for (var i = 0; i < this.gv_iMaxPageNum; i++)
    {
        this.div_page.form.components["stt_"+i].set_color("blue");            
    }    
}

10

콜백 함수 작성하기

서버로부터 받은 데이터를 처리하기 위한 콜백 함수를 작성합니다.

트랜잭션이 완료된 후 후처리를 위해 호출되는 콜백 함수지만 예제에서는 실제 트랜잭션을 사용하지 않기 때문에 트랜잭션 함수를 호출할 위치에서 임의로 호출해 사용합니다.

26~28번 줄의 코드는 ds_server의 데이터를 ds_client로 복사하는 코드입니다. 이는 서버의 데이터를 사전에 ds_server에 저장해 놓고 트랜잭션을 수행했음을 가정했기 때문에 필요한 부분으로 실제 트랜잭션 상황에서는 필요없는 코드입니다.

/*
callback function
*/
this.fn_callback = function(sTrId, ErrorCode, ErrorMsg)
{
    if (sTrId == "tr1")    
    {
        if (ErrorCode < 0)
        {
            trace("Error");
        }
        else
        {
            var iLastRow = this.gv_iStartPageNo * this.gv_iUnitSelRowNo;
            this.ds_server.filter("ROWNO >= "+(iLastRow + this.gv_iStartSelRowNo)+" && ROWNO <= "+(iLastRow + this.gv_iUnitSelRowNo));
        
            if (this.ds_server.getRowCount() == 0)
            {
                alert("No more data to view.");
                this.ds_server.filter("");
                return;
            }
            else
            {
                /* if transaction call using, delete the three lines below */
                this.ds_client.clearData();
                this.ds_client.copyData(this.ds_server, true);
                this.ds_client.filter("ROWNO >= "+(iLastRow + this.gv_iStartSelRowNo)+" && ROWNO <= "+(iLastRow + this.gv_iMaxPageNum));
                                
                this.gv_iServerRowCount = this.ds_server.getRowCount();
                this.fn_SetStyle();
                this.fn_SetPageNo();
                
                this.div_page.form.stt_0.set_color("red");
            }
        }
    }
}

11

QuickView로 확인하기

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다.

Page 네비게이션의 Prev, 숫자, Next 버튼을 눌러 페이지 이동에 따라 데이터가 정상적으로 표현되는지 확인합니다.

25.10Grid에서 간단한 설문조사 구현하기

설문조사 항목 중 주관식이나 특정 답변을 선택하는 것 외에 많이 사용하는 것이 항목에 대한 점수를 매기는 방식입니다. 예를 들어 식당을 방문하고 나서 서비스나 가격, 맛이 어떠했는지 1점부터 5점까지 점수 중에서 선택하는 설문을 진행할 수 있습니다.

Grid 컴포넌트에서 이런 방식을 구현하려면 edittype 속성값을 'text"로 지정해서 직접 값을 기입하거나 "combo"로 지정해서 값을 선택하도록 할 수 있습니다. 하지만 직접 값을 입력하는 경우에는 사용자가 어떤 값을 입력해야 하는지 확인하기 어렵고 콤보박스 방식은 combolist를 열어서 항목을 선택하는 불편함이 있습니다. 예제에서는 edittype 속성값을 "checkbox"로 지정해서 해당하는 점수를 체크하는 것만으로 설문조사에 참여할 수 있도록 구현합니다.

설문의 형태에 따라 Grid 컴포넌트를 사용하지 않을 수도 있습니다. 점수를 체크하는 방식에서는 Radio 컴포넌트를 배치해 사용하는 것이 좀 더 쉬운 방법입니다. 하지만 아래 예처럼 정해진 항목이 반복되는 경우에는 Grid 컴포넌트를 사용하는 것이 시각적으로 좀 더 사용자에게 익숙할 수 있습니다.

25.10.1예제

실제 데이터는 Restaurant, Service, Value 3개의 값만을 가지고 있습니다. 식당의 서비스와 가격에 대한 평가는 1~3점까지 점수를 체크할 수 있습니다. 위에 있는 Grid에서 해당하는 점수를 체크하면 Dataset에 반영되고 바인딩된 다른 Grid 컴포넌트에 반영됩니다 (아래쪽에 있는 Grid는 데이터가 변경되는 것을 확인할 수 있도록 배치했습니다).

sample_grid_40.xfdl

25.10.2예제에서 사용한 핵심 기능

setColumn

Dataset 오브젝트에 Row, Column을 지정하고 값을 변경합니다. Row는 인덱스로만 지정하고 Column 항목은 인덱스 또는 컬럼명으로 지정할 수 있습니다. 예제에서는 특정 셀 클릭 시 셀 위치에 따라 변경할 컬럼명을 지정합니다.

currow

GridCellControl 오브젝트의 속성값 지정 시 수식(expr)을 지원하는 경우 사용할 수 있는 변수 중 하나입니다. 현재 Row의 위치를 인덱스값으로 반환합니다. GridCellControl 오브젝트 도움말 항목에서 지원하는 변수 목록을 확인할 수 있습니다.

25.10.3예제 구현 방법

1

메인 화면 구성하기

두 개의 Grid 컴포넌트를 위, 아래로 배치합니다. 그리고 Dataset을 추가합니다. Dataset은 아래 그림과 같은 Column, Row 정보를 가지고 있습니다.

2

Grid 컴포넌트에 Dataset 바인딩하기

두 개의 Grid 컴포넌트에 앞에서 만든 Dataset을 바인딩합니다. 아래쪽 Grid 컴포넌트는 Dataset의 데이터를 확인하기 위한 용도로 사용하기 때문에 바인딩한 상태 그대로 유지합니다. 하지만 위쪽 Grid 컴포넌트는 설문조사 형식을 만들기 위해 해당 그리드를 더블클릭 하거나, 마우스 오른쪽 버튼을 클릭하여 컨텍스트 메뉴에서 [Edit]를 선택해 Grid Contents Editor를 실행합니다.

3

Grid Contents Editor - Add Head Row

Grid Contents Editor에서 Row와 Column을 추가하는 순서는 큰 의미는 없습니다. 편한 방식으로 진행하면 됩니다. 예제에서는 Head Row를 먼저 추가합니다. Service, Value 항목의 각 점수를 컬럼으로 보여주기 때문에 Head Row에 2줄을 표시해야 합니다.

4

Grid Contents Editor - Add Column

4개의 컬럼을 추가합니다. Add Column 메뉴는 마지막 컬럼 뒤에 컬럼을 추가하는 방식인데 특정 위치에 컬럼을 추가하고 싶다면 Insert 메뉴를 사용합니다. 예제에서는 Restaurant 컬럼을 제외하고는 모두 수정할 것이라 어떤 방법을 사용하든 상관없습니다.

5

Grid Contents Editor - Merge Cells

아래 그림처럼 Head Row 항목을 병합합니다. 화면에 보여주는 용도이기 때문에 개별 Child Cell을 유지할 필요는 없습니다. 아래 그림에서 보이는 코드는 병합 후 생성되는 코드입니다.

병합 후 Head row1 항목에는 Service, Value 항목 아래에 1, 2, 3 점수값을 text 속성값으로 입력합니다.

6

Grid Contents Editor - Cell 속성값 지정

각 점수에 해당하는 Cell 속성값을 지정합니다. displaytype 속성값은 "checkboxcontrol", edittype 속성값은 "checkbox"로 지정합니다. 그리고 text 속성값은 Dataset의 컬럼값을 그대로 보여주지 않고 약간의 가공작업을 추가합니다.

Dataset에는 Service, Value 항목 점수값만 들어있기 때문에 어떤 체크박스를 체크된 상태로 표시해야 할지 판단해야 합니다. 같은 점수에 해당하는 Cell의 체크박스만 체크된 상태로 표시하기 위해 수식(expr)을 사용합니다.

7

Grid Contents Editor - 조건식 사용

text 속성값을 직접 입력하거나 [Edit Expression Value] 창을 실행한 후 입력합니다. text 속성값을 직접 입력하는 경우에는 "expr:"이라는 텍스트를 입력해주어야 하며 속성창에서 오른쪽 끝에 있는 버튼(Set Expression) 클릭 후 [Edit Expression Value] 창을 실행한 경우에는 수식만 입력하면 됩니다.

수식은 한 줄에 원하는 식을 담아야 하므로 if 문 대신 3항 연산자를 사용합니다. 3항 연산자는 조건식을 실행하고 해당 조건식이 참인 경우와 거짓인 경우 value값을 반환합니다. 예제에서는 getColumn 메소드를 사용해 현재 Row의 Service 컬럼값이 1인지 확인합니다. 1이 맞다면 1을 아니라면 0을 반환합니다. 그래서 조건이 맞는 경우에는 체크박스가 체크되어 표시되고 맞지 않는다면 체크되지 않는 상태로 표시됩니다.

2점과 3점을 표시하는 Cell에서 마찬가지로 컬럼값이 2 또는 3인지 확인하고 1 또는 0 값을 반환합니다.

expr:dataset.getColumn(currow, "Service")==1?1:0
expr:dataset.getColumn(currow, "Service")==2?1:0
expr:dataset.getColumn(currow, "Service")==3?1:0

Value 컬럼도 마찬가지입니다. 컬럼값만 다르고 나머지는 같은 식을 사용합니다.

expr:dataset.getColumn(currow, "Value")==1?1:0
expr:dataset.getColumn(currow, "Value")==2?1:0
expr:dataset.getColumn(currow, "Value")==3?1:0

이제 Dataset에 있는 점수값을 Grid 컴포넌트에 체크박스 형식으로 표시할 수 있습니다.

8

oncellclick 이벤트 추가하기

화면에 점수를 보여주는 것까지는 처리했는데 체크박스를 클릭하면 아무런 변화가 없습니다. 체크박스와 Dataset 컬럼값이 직접 바인딩된 상태가 아니기 때문입니다. 체크박스가 가지고 있는 값은 1 또는 0인데 Dataset에 들어가야 하는 값은 1점부터 3점까지이기 때문에 맞지도 않습니다.

Grid 컴포넌트에 oncellclick 이벤트를 추가하고 Cell 클릭 시 Column, Row 정보로 Dataset 컬럼값을 업데이트합니다. 예제에서는 Column 정보로 어떤 항목의 점수인지 확인할 수 있기 때문에 아래와 같이 값을 지정했습니다.

this.Grid00_oncellclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    if(e.col>0 && e.col<4)
    {
        this.Dataset00.setColumn(e.row, "Service", e.col);
    }    else
    if(e.col>=4 && e.col<7)
    {
        this.Dataset00.setColumn(e.row, "Value", e.col-3);
    }    
};

9

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 위쪽 Grid 컴포넌트에 점수가 표시되는지, 빈 체크박스 Cell을 클릭했을 때 데이터가 반영되는지 확인합니다.

25.11마우스 휠 동작을 이용한 페이징 처리

데이터가 많은 경우 한번에 모든 데이터를 다 처리하지 않고 화면에 보여지는 데이터만 처리하는 방법 중 하나입니다. 최초 로딩시에는 지정된 만큼 데이터를 보여주고 마우스 휠을 움직이면 보여줄 데이터를 추가해줍니다.

25.11.1예제

버튼을 클릭하면 10개의 데이터를 보여주고 마우스 휠을 움직이면 10개 단위로 데이터를 추가해서 표시합니다.

sample_grid_47.xfdl

25.11.2예제에서 사용한 핵심 기능

filter

Dataset 오브젝트의 데이터 중에서 조건에 만족하는 데이터만 사용하도록 합니다. 데이터 자체를 삭제하거나 조정하는 것은 아닙니다.

onvscroll

수직 스크롤바가 움직일때 발생하는 이벤트입니다. ScrollEventInfo 오브젝트의 type 속성값에 따라 스크롤바의 현재 상태를 알 수 있습니다. 예제에서는 type 속성값이 "wheellastover"인 경우에 데이터를 추가합니다.

25.11.3예제 구현 방법

1

화면 구성하기

Grid 컴포넌트와 Button 컴포넌트를 배치합니다. Dataset 오브젝트는 2개를 생성하는데 하나는 데이터를 채우고 하나는 컬럼 정보만 생성합니다. 데이터가 있는 Dataset 오브젝트가 원본이고 컬럼 정보만 가지고 있는 Dataset 오브젝트는 Grid 컴포넌트에 데이터를 보여주기 위한 용도로 사용합니다.

2

Dataset 바인딩

데이터가 없는 Dataset01 오브젝트를 Grid 컴포넌트에 바인딩합니다.

3

Button 컴포넌트 onclick 이벤트 함수 작성하기

fn_retrieve 함수를 호출합니다. fn_retrieve 함수에서는 전체 데이터를 확인하고 얼마만큼의 데이터를 Grid 컴포넌트에 바인딩된 Dataset에 추가할지 판단하고 처리합니다.

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    this.fn_retrieve(false);
};

한 페이지를 10개 데이터 단위로 처리합니다. 버튼 클릭 시에는 10개의 데이터를 Dataset00에서 가져와서 Dataset01에 추가합니다(appendData).

this.fv_nTotCount = 0;
this.fv_nNowPage = 0;
this.fv_nPageSize = 10;
this.fv_bNext = true;
this.fn_retrieve = function(bNext)
{        
    if (bNext == false)
    {
        this.fv_nTotCount  = this.Dataset00.getRowCount();
    }
    
    if (this.Dataset01.rowcount >= this.fv_nTotCount)
    {
        this.fv_bNext = false;
        return;
    }
    
    var nStrat = this.fv_nNowPage * this.fv_nPageSize + 1;
    var nEnd   = this.fv_nNowPage * this.fv_nPageSize + this.fv_nPageSize;
    this.Dataset00.filter("COL0 >= " + nStrat + " && COL0 <= " + nEnd);        
    this.Dataset01.appendData(this.Dataset00);    
    this.Dataset01.set_rowposition(this.Dataset01.rowcount - 1);
    this.fv_nNowPage++;       
}

4

마우스 휠 이벤트 처리하기

onvscroll 이벤트 발생 시 ScrollEventInfo의 type 속성값을 확인하고 "wheellastover"인 경우 데이터를 추가하기 위해 fn_retrieve 함수를 호출합니다.

this.Grid00_onvscroll = function(obj:nexacro.Grid,e:nexacro.ScrollEventInfo)
{
    if (e.type == "wheellastover") 
    {
        if (this.fv_bNext)
        {  
            this.fn_retrieve(true);
        }
    }
};

5

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 버튼을 클릭해 초기값을 설정하고 마우스 휠을 움직여 데이터가 추가되는 것을 확인합니다.

25.121건만 있는 소계 삭제하기

Dataset 오브젝트에서 keystring 속성값을 지정하면 그룹핑 설정을 할 수 있고 소계를 출력할 수 있습니다. 하지만 기본 설정에서는 그룹핑된 항목이 1건이라도 소계를 출력합니다. 불필요하게 소계 항목을 출력하고 있는 것입니다. 이번 예제에서는 그룹핑된 항목이 1건인 경우 삭제하는 방법을 살펴봅니다.

25.12.1예제

그룹핑된 항목이 1건인 소계도 보여주는 상태에서 버튼을 클릭하면 그룹핑된 항목이 1건인 소계 Row를 삭제합니다.

sample_grid_48.xfdl

25.12.2예제에서 사용한 핵심 기능

getRowType

지정된 Row의 타입 정보를 반환합니다. 그룹핑된 정보의 경우에는 Dataset.ROWTYPE_GROUP 정보를 반환합니다. keystring 속성값으로 지정한 항목이 2개 이상인 경우에 각 컬럼 정보를 구분해야 한다면 getRowLevel 메소드를 사용합니다.

getGroupRangeCount

그룹핑된 정보의 경우에 참조하는 Row 정보를 반환합니다. 예제에서는 1건만 있는 소계를 삭제하기 때문에 반환값이 2보다 작은 경우에 조건식을 처리합니다.

25.12.3예제 구현 방법

1

화면 구성하기

Grid 컴포넌트와 Button 컴포넌트를 배치합니다. Dataset 오브젝트를 생성하고 아래와 같이 데이터를 설정합니다.

첫번째 컬럼을 그룹으로 묶을 겁니다. Dataset 오브젝트의 keystring 속성값을 "Column0"으로 지정합니다.

2

suppress 설정하기

Grid 컴포넌트에 Dataset 오브젝트를 바인딩하고 Grid Contents Editor에서 Column0 셀 항목의 suppress 속성값을 1로 지정합니다.

3

onclick 이벤트 함수 작성하기

버튼 클릭 시 그룹핑된 항목이 1건인 데이터를 삭제합니다. 조건에 맞는 Row를 삭제하기 때문에 for 반복문을 0부터 시작하는 것이 아니라 가장 큰 인덱스 값부터 시작해서 작은 인덱스 값으로 반복해 처리합니다.

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    for(var i=this.Dataset00.getRowCount()-1; i>=0 ;i-- )
    {        
        if( this.Dataset00.getRowType(i) == Dataset.ROWTYPE_GROUP 
            &&  this.Dataset00.getGroupRangeCount(i) < 2){
            this.Dataset00.deleteRow(i);
        }
    }
};

4

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 버튼을 클릭해 그룹핑된 항목이 1건인 데이터가 삭제되는지 확인합니다.

25.13특정 위치의 부모 트리만 펼치기

접혀진 상태의 Grid 컴포넌트에서 특정 위치의 항목을 선택하면 해당 항목의 부모 트리만 펼치는 기능입니다.

25.13.1예제

오른쪽에 있는 Grid 컴포넌트에서 원하는 항목을 선택하면 해당 항목이 속한 부모 트리만 펼쳐집니다.

sample_grid_51.xfdl

25.13.2예제에서 사용한 핵심 기능

treeinitstatus

Grid 컴포넌트가 트리 형태로 표시될때 초기 형태를 설정하는 속성입니다. 중간에 해당 속성을 변경하면 지정된 속성값에 따라 초기화된 상태로 표시됩니다. 예제에서는 항목 선택 시 먼저 모든 항목을 접은 상태에서 시작합니다.

setTreeStatus

지정된 Row의 상태를 접거나 펴진 상태로 지정합니다. 예제에서는 반복문을 사용해 선택된 항목 상위의 트리는 모두 펼치도록 했습니다.

25.13.3예제 구현 방법

1

화면 구성하기

Grid 컴포넌트를 2개 배치합니다. Dataset 오브젝트를 생성하고 아래와 같이 데이터를 설정합니다. 그리고 두개의 Grid 컴포넌트에 같은 Dataset 오브젝트를 바인딩합니다.

2

첫번째 Grid 컴포넌트 편집하기

첫번째 Grid 컴포넌트를 트리 형태로 보여주기 위해 Grid Contents Editor를 실행합니다. Grid 컴포넌트를 더블클릭하면 Editor가 실행됩니다. Dataset 오브젝트를 바인딩하면서 생성된 Column1은 삭제해버립니다. Column0의 body 셀 영역을 선택하고 displaytype, edittype 속성값을 아래와 같이 변경합니다.

그리고 treelevel 속성값을 Column1로 지정해줍니다. 속성창 위에 있는 검색창을 사용하면 속성값을 빠르게 찾을 수 있습니다.

3

oncellclick 이벤트 함수 작성하기

전체 데이터 목록에서 특정한 항목을 선택하면 이벤트를 처리하기 위해 oncellclick 이벤트 함수를 작성합니다. 해당 항목의 부모 트리 항목은 findParentArr 함수에서 따로 처리해서 배열 형태로 받아옵니다. 해당 배열 내에 있는 항목은 setTreeStatus 메소드를 사용해 하나식 펼쳐줍니다.

this.Grid01_oncellclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    this.Grid00.set_treeinitstatus("collapse,all");
    
    var path_Arr = this.findParentArr(this.Grid00, e.row);
    for(var i =  path_Arr.length  ; i > 0 ; i--) // Should be expanded in reverse.
    {
        this.Grid00.setTreeStatus(this.Grid00.getTreeRow(path_Arr[i]), true);
    }
    this.Dataset00.set_rowposition(path_Arr[0]);
};

4

findParentArr 함수 작성하기

선택한 Row의 인덱스값을 기준으로 부모 Row를 찾아갑니다. 예를 들어 12번 항목(인덱스는 11)을 선택했다면 부모 항목은 10번(인덱스는 9)이고 10번 항목의 부모 항목은 8번(인덱스는 7)입니다. 배열에는 11,9, 7 값이 담기게 됩니다.

this.findParentArr = function (obj, idx)
{
    var arr = [];
    arr[arr.length] = idx;
    for(;;)
    {    
        var _p = obj.getTreeParentRow(arr[arr.length-1]);
        if(_p < 0){return arr;}
        arr[arr.length] = _p;     
    }
};

for(;;) 문은 계속 반복을 하도록 설정한 반복문입니다. 이런 경우에는 반복문을 멈추는 조건이 없기 때문에 중간에 반복문을 중단하는 문장(return arr)이 없다면 계속 반복문이 동작하게 됩니다. while(true)를 사용하는 것과 같은 방식입니다. getTreeParentRow 메소드는 Root row를 찾았을때 -1을 반환하며 조건에 따라 결과값을 반환하게 됩니다.

5

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 오른쪽 Grid 항목을 선택해 왼쪽 Grid 컴포넌트의 트리 상태가 변하는 것을 확인합니다.

25.14영수증 계산하기

합계나 소계를 구하는 것은 컬럼 속성을 "SUM"으로 지정하거나 getSum 메소드를 사용하는데 단가와 수량이 있는 경우에는 바로 합계를 구할 수 없습니다. 이런 경우에는 어떻게 연산을 할 수 있는지 살펴봅니다.

25.14.1예제

단가와 수량을 계산한 합계값을 표시합니다.

sample_grid_55.xfdl

25.14.2예제에서 사용한 핵심 기능

displaytype

속성값을 "currency"로 지정하면 현재 locale 설정의 통화를 기준으로 표시합니다.

25.14.3예제 구현 방법

1

화면 구성하기

Grid 컴포넌트를 배치합니다. Dataset 오브젝트를 생성하고 아래와 같이 데이터를 설정합니다. 컬럼 type 설정 시 price, amount 항목은 "INT"로 지정합니다. 해당 type을 지정하지 않으면 getSum 메소드가 정상적으로 실행되지 않습니다. 생성된 Dataset 오브젝트를 Grid 컴포넌트에 바인딩합니다.

2

Total 컬럼 추가하기

Grid Contents Editor를 실행하고 컬럼을 추가합니다. 단가와 수량을 계산한 값을 표시하기 위한 컬럼입니다. [Add Column] 버튼을 클릭하면 컬럼이 추가됩니다. head 영역을 선택하고 text 속성값에 "Total"을 입력합니다.

그리고 Total 셀 항목을 선택하고 expr에 아래와 같이 입력합니다. price 컬럼값과 amount 컬럼값을 곱해서 아이템별 합계를 계산하고 화면에 표시합니다.

expr:price * amount

displaytype 속성값은 컬럼별로 아래와 같이 설정합니다.

<Band id="body">
    <Cell text="bind:item"/>
    <Cell col="1" text="bind:price" displaytype="number"/>
    <Cell col="2" text="bind:amount" displaytype="number"/>
    <Cell col="3" expr="expr:price * amount" displaytype="currency"/>
</Band>

expr 속성값 지정 시 직접 계산식을 지정하지 않고 별도 함수를 작성해서 처리할 수 있습니다. 계산식이 복잡할 경우에는 별도 함수를 작성하는 것이 좀 더 직관적입니다. 예를 들어 위와 같은 경우에는 아래와 같이 설정합니다.

...
    <Cell col="3" expr="expr:comp.parent.fn_total(rowidx)" displaytype="currency"/>
...

그리고 fn_sum 이라는 함수를 다음과 같이 생성합니다.

this.fn_total = function(row)
{
    var total= this.Dataset00.getColumn(row,"price") * this.Dataset00.getColumn(row,"amount");
    return total;
};

3

Summary Row 추가하기

[Add Summary Row] 버튼을 클릭해 총합계를 표시할 Row를 추가합니다.

Total 컬럼에 해당하는 summary row 셀의 displaytype 속성값은 "currency"로 지정하고 expr 항목은 아래와 같이 지정합니다. getSum 메소드는 컬럼 ID를 지정하거나 컬럼 ID의 계산식을 파라미터로 지정할 수 있습니다.

expr:dataset.getSum('price*amount')

4

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 아이템별 합계와 전체 합계가 표시되는 것을 확인합니다.

25.15그룹에 레벨 지정해서 subtotal 계산하기

그룹이 두 개 이상인 경우 subtotal 값을 계산해야 하는 경우에는 어떤 그룹을 먼저 묶어야 할지 지정해주어야 합니다. 이번 예제에서는 그룹이 두 개 이상인 경우 처리하는 방식을 살펴봅니다.

25.15.1예제

왼쪽에 표시되는 Grid 컴포넌트는 C1, C2 2개 컬럼을 레벨을 지정했습니다. 오른쪽 Grid는 레벨을 지정하지 않고 그루핑 조건으로만 C1, C2 컬럼을 묶어주었습니다.

sample_grid_56.xfdl

25.15.2예제에서 사용한 핵심 기능

keystring

","를 이용하면 그룹에 레벨을 줄 수 있습니다. 예제에서는 "G:+C1,+C2"으로 지정된 Dataset 오브젝트를 왼쪽 Grid 컴포넌트에 바인딩했는데 C1을 기준으로 소계를 계산하고, C1,C2를 기준으로 소계를 계산한다는 의미입니다. 오른쪽 Grid 컴포넌트에 바인딩된 Dataset 오브젝트의 keystring 속성값은 "G:+C1+C2"입니다. 때문에 C1, C2를 기준으로 소계를 계산해 표시합니다.

25.15.3예제 구현 방법

1

화면 구성하기

Grid 컴포넌트를 2개 배치합니다. Dataset 오브젝트는 2개를 생성하는데 데이터는 똑같이 입력합니다.

Dataset 오브젝트의 keystring 속성값을 아래와 같이 지정합니다. ","가 중간에 들어가는지 아닌지의 차이입니다. 왼쪽 Grid 컴포넌트에는 Dataset00 오브젝트를 바인딩하고, 오른쪽 Grid 컴포넌트에는 Dataset01 오브젝트를 바인딩합니다.

Dataset00: G:+C1,+C2
Dataset01: G:+C1+C2

2

suppress 속성값 설정하기

Grid 컴포넌트를 더블클릭해서 Grid Contents Editor를 실행하고 suppress 속성값을 지정합니다. C1 컬럼은 1, C2 컬럼은 2로 지정합니다.

3

subtotal 텍스트 설정하기

왼쪽 Grid 컴포넌트에는 subtotal 앞에 문구를 표시하도록 합니다. expr 항목을 아래와 같이 지정합니다.

expr:dataset.getRowLevel(rowidx)==2?'sum ' + dataset.getColumn(rowidx-2,'C1'):C2
expr:dataset.getRowLevel(rowidx)==1?'sum ' + dataset.getColumn(rowidx-1,'C2'):C3

4

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 Grid 컴포넌트에 표시되는 항목을 확인합니다.

25.16동적으로 Grid 컴포넌트 생성하고 데이터 바인딩하기

Grid 컴포넌트는 정해놓은 데이터 형식에 따라 데이터를 보여주는 용도로 사용합니다. 하지만 상황에 따라 Grid 컴포넌트를 스크립트에서 동적으로 생성하고 데이터를 설정해주어야 하는 경우도 있습니다. 이번 예제에서는 동적으로 Grid 컴포넌트를 생성하고 포맷을 지정하는 방법을 살펴봅니다.

25.16.1예제

버튼을 클릭하면 하단에 동적으로 생성된 Grid 컴포넌트를 표시합니다.

sample_grid_63.xfdl

25.16.2예제에서 사용한 핵심 기능

appendContentsRow

"head", "body", "summary" Row를 추가하는 메소드입니다. Grid Contents Editor에서 [Add Head Row], [Add Body Row], [Add Summary Row] 항목과 같은 기능을 처리합니다.

appendContentsCol

컬럼을 추가하는 메소드입니다. "left", "body", "right" 밴드 영역을 선택할 수 있습니다. 지정된 밴드 영역이 없으면 "body" 밴드 영역에 추가됩니다. 예제에서는 3개의 컬럼이 필요한데, appendContentsCol 메소드를 두 번 실행했습니다. 첫 번째 컬럼은 appendContentsRow 메소드가 실행되면서 이미 추가된 상태이기 때문에 두 번만 appendContentsCol 메소드를 실행합니다.

25.16.3예제 구현 방법

1

화면 구성하기

화면에는 버튼 하나만 배치합니다. 버튼 클릭 시 Grid 컴포넌트를 생성하고 배치합니다.

2

onclick 이벤트 함수 작성하기

버튼 클릭 시 Grid를 배치하고 생성합니다. 전체 코드를 부분별로 나누어 설명합니다. 가장 먼저 Grid 컴포넌트를 생성하고 form 오브젝트의 자식으로 추가합니다.

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    var objGrid = new Grid();
    objGrid.init("GridNm", 30, 80, 350, 200,null,null);
    this.addChild("Grid00", objGrid);    
    objGrid.show();
...

Dataset 오브젝트를 생성하고 Columns, Rows 정보를 설정합니다.

var objDs = new Dataset();
objDs.set_name("ds_test");
objDs.addColumn("no", "string");
objDs.addColumn("name", "string");
objDs.addColumn("age", "int");
    
for (var i = 0; i < 5; i++) 
{
    var nRow = objDs.addRow();
    
    objDs.setColumn(nRow, "no", i);
    objDs.setColumn(nRow, "name", 'employ_' + i);
    objDs.setColumn(nRow, "age", (10 + i));
}

바인딩 정보를 설정합니다. 바인딩 정보 설정 후 Grid 컴포넌트의 createFormat 메소드를 호출하면 Dataset 오브젝트의 정보를 바탕으로 포맷 정보를 자동으로 설정합니다. 하지만 예제에서는 몇 가지 조정하는 부분이 있어서 createFormat 메소드를 사용하지 않습니다.

objGrid.set_binddataset(objDs);

Row 밴드 정보를 설정하고 컬럼을 추가합니다. appendContentsRow 메소드 실행 시 첫 번째 컬럼은 자동으로 생성되기 때문에 appendContentsCol 메소드는 두 번만 실행합니다.

objGrid.appendContentsRow("head");
objGrid.appendContentsRow("body");
objGrid.appendContentsRow("summ");
    
objGrid.appendContentsCol();
objGrid.appendContentsCol();
    
objGrid.setFormatColProperty(0, "size", 100);
objGrid.setFormatColProperty(1, "size", 100);
objGrid.setFormatColProperty(2, "size", 100);

화면에 표시되는 head 영역의 문자열과 body 영역에 표시될 Cell 속성을 지정합니다.

for (var r = 0; r < objDs.getColCount(); r++) 
{
    var colinfo = objDs.getColumnInfo(r);
    objGrid.setCellProperty("head", r, "text", colinfo.name);
    objGrid.setCellProperty("body", r, "text", "bind:" + colinfo.name);
    if (r == 2) 
    {
        objGrid.setCellProperty("summ", r, "text", "expr:dataset.getSum('"+colinfo.name+"')");
    }
    else if(r == 1)
    {
        objGrid.setCellProperty("summ", r, "text", "total");
    }
}

3

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 버튼 클릭 시 생성되는 Grid 컴포넌트를 확인합니다.

25.17드래그앤드롭으로 Grid 컴포넌트의 문자열 옮기기

드래그 앤 드롭 기능을 활용해 Grid 컴포넌트에 보여지는 데이터를 다른 컴포넌트로 옮기는 예제입니다.

25.17.1예제

Grid 컴포넌트의 특정 Cell을 드래그해서 Edit 컴포넌트로 옮길 수 있습니다. Edit 컴포넌트 중 2, 4번째 컴포넌트는 드래그한 문자열을 옮길 수 없도록 제한해놓았습니다.

sample_grid_65.xfdl

25.17.2예제에서 사용한 핵심 기능

getCellValue

Grid 컴포넌트에 보여지는 문자열을 반환합니다. getCellProperty 메소드를 사용할 경우에는 문자열로 text 속성값을 지정한 경우에는 원하는 결과를 얻을 수 있지만, 바인딩된 컬럼값을 사용하거나 expr 속성을 지정한 경우에는 원하는 문자열을 얻을 수 없습니다.

getCellRect

선택한 Cell 영역의 좌표값을 반환합니다. 예제에서는 드래그 시작 시점에 Static 컴포넌트가 해당 위치에 보여지도록 설정합니다.

25.17.3예제 구현 방법

1

화면 구성하기

Grid 컴포넌트와 Edit 컴포넌트를 배치합니다. Static 컴포넌트 2개를 배치하고 visible 속성값을 false로 지정합니다. Static 컴포넌트는 드래그앤드롭 상태에 따라 visible 속성을 변경합니다. Dataset 오브젝트를 생성하고 Grid 컴포넌트에 바인딩합니다.

2

onload 이벤트 함수 작성하기

예제에서는 Edit 컴포넌트 중 2개는 드래그한 문자열을 옮길 수 있고 나머지 2개는 옮길 수 없도록 지정합니다. 문자열을 옮길 수 있는 컴포넌트와 그렇지 않은 컴포넌트를 onload 이벤트 함수에서 배열로 지정합니다.

var arr1 = [];
var arr2 = [];

this.sample_grid_65_onload = function(obj:nexacro.Form,e:nexacro.LoadEventInfo)
{
    // Drop unavailable
    arr1[0] = this.Edit00;
    arr1[1] = this.Edit02;

    // Drop possible
    arr2[0] = this.Edit01;
    arr2[1] = this.Edit03;
};

3

ondrag 이벤트 함수 작성하기

ondrag 이벤트 함수는 Grid 컴포넌트에서 작성합니다. Grid 영역에서 드래그 동작이 시작되는 시점에 이벤트가 발생합니다. GridDragEventInfo 오브젝트의 row 속성값이 -1 또는 -2인 경우에는 head, summary Row 밴드에서 드래그 동작이 발생한 것이므로 이벤트를 무효화하고 그렇지 않은 경우에는 선택한 Cell 영역의 위치값을 확인하고 Static 컴포넌트를 그 위에 표시합니다.

this.Grid00_ondrag = function(obj:nexacro.Grid, e:nexacro.GridDragEventInfo)
{
    if(e.row == -1 || e.row == -2)
    {
        return false;
    }    
    
    sTextDragData = obj.getCellValue(e.row, e.cell);

    var cell_rect = obj.getCellRect(e.row, e.cell);
    this.Static00.set_left(cell_rect.left);
    this.Static00.set_top(cell_rect.top);
    this.Static00.set_width(cell_rect.width);
    this.Static00.set_height(cell_rect.height);
    this.Static00.set_text(sTextDragData);
    this.Static00.set_visible(true);
    return true;
};

4

ondragmove 이벤트 함수 작성하기

ondragmove 이벤트 함수에서는 마우스 움직임에 따라 Static 컴포넌트를 이동합니다. 문자열을 옮길 Edit 컴포넌트 위로 올라가면 옮길 수 없는 컴포넌트인지 확인하고 Static 컴포넌트의 visible 속성값을 조정합니다.

this.DragTextMove = function(obj, e)
{
    if( this.Static00.visible == true )
    {    
        for(var i = 0; i < arr1.length; i++)
        {
            if(arr1[i].name == e.fromobject.name)
            {
                this.equal_Obj(obj, e);
                break;
            }    else    {
                this.different_Obj(obj, e);
            }
        }
        this.Static00.move(e.clientx+5, e.clienty-15);
    }
};

this.equal_Obj = function(obj, e)
{
    this.Static01.set_visible(true);
    this.Static01.move(e.clientx-10, e.clienty+5);
};

this.different_Obj = function(obj, e)
{
    this.Static01.set_visible(false);
};

5

ondrop 이벤트 함수 작성하기

ondrop 이벤트가 발생하면 Edit 컴포넌트가 문자열을 옮길 수 있는지 없는지 판단하고 옮길 수 있는 컴포넌트라면 value 속성값을 설정해줍니다. 그리고 Static 컴포넌트는 모두 보이지 않게 합니다.

this.sample_grid_65_ondrop = function(obj:nexacro.Form,e:nexacro.DragEventInfo)
{
    for(var i = 0; i < arr1.length; i++ )
    {
        if(e.fromobject != undefined && e.fromobject.name == arr1[i].name)
        {
            this.Static00.set_visible(false);
            this.Static01.set_visible(false);
            return false;
        }
    }

   for(var i = 0; i < arr2.length; i++ )
    {
        if(e.fromobject != undefined && e.fromobject.name == arr2[i].name)
        {
            e.fromobject.set_value(sTextDragData);
            this.Static00.set_visible(false);
        }
    }
    this.Static00.set_visible(false);
};

6

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 Grid 컴포넌트의 문자열을 Edit 컴포넌트로 드래그앤드롭 동작으로 이동합니다.

25.18두 개의 Grid 컴포넌트의 스크롤을 동시에 움직이기

Grid 컴포넌트의 스크롤 이동 시 발생하는 이벤트 함수 내에서 다른 Grid 컴포넌트의 스크롤 위치를 변경할 수 있습니다. 두 개의 Grid 컴포넌트를 하나처럼 보이게 할 수 있습니다.

25.18.1예제

왼쪽에 배치한 Grid 컴포넌트는 스크롤바가 보이지 않도록 설정했습니다. 오른쪽 Grid 컴포넌트의 스크롤바 이동 시 같이 움직입니다.

sample_grid_69.xfdl

25.18.2예제에서 사용한 핵심 기능

scrollTo

가로, 세로 스크롤바의 위치를 지정한 위치로 이동합니다.

25.18.3예제 구현 방법

1

화면 구성하기

Grid 컴포넌트를 예제 화면과 같이 배치합니다. 왼쪽에 배치하는 Grid 컴포넌트는 scrollbartype 속성값을 "none"으로 지정합니다. 가로, 세로 스크롤바가 모두 보이지않도록 하나의 값("none")만 설정합니다.

예제에서는 Dataset 오브젝트를 두 개 생성했지만, 같은 Dataset 오브젝트를 바인딩해서 사용해도 상관없습니다. 각 Dataset 오브젝트의 데이터 갯수만 일치하도록 합니다.

2

onvscroll 이벤트 함수 작성하기

오른쪽 Grid 컴포넌트의 onvscroll 이벤트 함수를 작성합니다. 스크롤이 동작할때마다 이벤트가 발생하며 왼쪽 Grid 컴포넌트의 스크롤 위치를 변경해줍니다.

this.Grid01_onvscroll = function(obj:nexacro.Grid,e:nexacro.ScrollEventInfo)
{
    this.Grid00.scrollTo(0,e.pos);
};

3

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 오른쪽 Grid 컴포넌트의 스크롤바를 이동했을때 왼쪽 Grid 컴포넌트이 스크롤되는지 확인해봅니다.

25.19체크된 Row 숫자 반환하기

CheckBoxControl 오브젝트의 text 속성값을 expr로 처리합니다. 체크된 상태를 별도의 변수로 저장하고 있다가 버튼 클릭 시 결과를 반환합니다.

25.19.1예제

Grid 컴포넌트에서 체크박스를 선택한 결과를 Button 컴포넌트 클릭 시 반환합니다.

sample_grid_72.xfdl

25.19.2예제에서 사용한 핵심 기능

redrawExprCell

Cell 오브젝트에 설정한 expr 값의 갱신 범위를 지정합니다. head, body, summary 중 하나를 설정할 수 있으며, 범위를 지정하지 않으면 전체 밴드 영역의 expr 값을 갱신합니다.

redrawExprCell 메소드는 17.0.0.400 이후 버전부터 사용할 수 있습니다.

25.19.3예제 구현 방법

1

화면 구성하기

Grid 컴포넌트와 Button 컴포넌트를 예제 화면과 같이 배치합니다. Dataset 오브젝트를 아래와 같이 생성하고 바인딩해줍니다.

2

Grid Contents Editor 실행하기

Column0 컬럼 Cell 오브젝트의 속성을 아래와 같이 수정합니다. 체크박스 체크 여부는 ck_func 라는 함수에서 처리합니다.

displaytype: checkboxcontrol
edittype: checkbox
text: expr:comp.parent.ck_func(currow)

3

ck_func 함수 작성하기

ck_func 함수에서는 배열 변수에 해당하는 row를 인덱스값으로 지정해서 0 또는 1의 값을 설정하고 저장한 다음 값을 반환합니다. 실제 배열 변수에 있는 값은 Cell 영역을 클릭 시 값이 토글 형태로 바뀝니다. 값이 바뀌면 redrawExprCell 메소드를 호출해서 expr로 설정된 값을 처리하도록 합니다.

this.ck_arr = [];

this.ck_func = function(nRow)
{    
    return this.ck_arr[nRow] == null ? 0 :  this.ck_arr[nRow];
}

this.Grid00_oncellclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    if(e.cell == 0 )
    {
        this.ck_arr[e.row] = this.ck_arr[e.row] == null ? 1 : this.ck_arr[e.row]^1;
        this.Grid00.redrawExprCell('body');
    }
    
};

^ 기호는 배타적 논리합 연산자입니다. 비트 단위 연산 시 사용합니다. 예제에서는 토글 형태로 값이 0과 1로 변경되는 연산 처리에 사용했습니다.

4

onclick 이벤트 함수 작성하기

Button 컴포넌트 클릭 시 배열 변수에 담긴 값을 확인하고 선택된 값이 몇 개인지 TextArea 컴포넌트에 표시합니다.

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    var cnt = 0;
    for(var i = 0 ; i < this.ck_arr.length ; i++)
    {
        if(this.ck_arr[i])
        {
            cnt = cnt + 1;
        }    
    }
    
    this.TextArea00.set_value("No. of selected rows : " + cnt);
    
    if(cnt == 0){
        this.TextArea00.set_value("There is no selected row " );
    }
    
};

5

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 체크박스의 상태를 바꾼 다음 Button 컴포넌트를 클릭해 TextArea 컴포넌트에 값이 표시되는 것을 확인합니다.

25.20Like 조건으로 검색하기

filter 메소드에 조건식을 사용해 입력된 문자열과 일부만 일치하는 검색 결과를 표시할 수 있습니다.

25.20.1예제

검색어를 입력하고 [%Like%] 버튼을 클릭하면 해당 검색어가 포함된 모든 결과를 표시하고 [Like%] 버튼을 클릭하면 해당 검색어로 시작하는 결과만 표시합니다. [Init] 버튼 클릭 시 검색결과를 초기화합니다.

sample_grid_73.xfdl

25.20.2예제에서 사용한 핵심 기능

filter

파라미터 없이 filter 메소드를 실행하는 경우에는 filterstr 속성값에 지정된 값으로 처리됩니다. filterstr 속성값이 없는 상태에서 파라미터 없이 filter 메소드를 실행하면 undefined 값이 전달되고 false로 처리되어 아무런 값도 표시하지 않습니다.

25.20.3예제 구현 방법

1

화면 구성하기

Grid 컴포넌트와 Button 컴포넌트를 예제 화면과 같이 배치합니다. Dataset 오브젝트를 아래와 같이 생성하고 바인딩해줍니다. 예제에서는 대소문자 구분없이 검색하는 부분을 제외했습니다.

2

onclick 이벤트 함수 작성하기

[%Like%] 버튼 클릭 시 입력된 값이 포함된 모든 결과값을 반환합니다. indexOf 메소드를 사용해 검색어가 포함된 경우 0 이상의 값을 반환하는 모든 데이터를 표시하도록 합니다.

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    this.Dataset00.filter("String(Name).indexOf('"+this.Edit00.value+"')>=0");
};

[Like%] 버튼 클릭 시 입력된 값으로 시작되는 결과값을 반환합니다. indexOf 메소드 실행 시 검색어와 일치하는 인덱스가 0인 데이터만 표시하도록 합니다.

this.Button01_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    this.Dataset00.filter("String(Name).indexOf('"+this.Edit00.value+"')==0");
};

[Init] 버튼 클릭 시 값을 초기화합니다. filterstr 속성값만 지정하더라도 onrowsetchanged 이벤트가 발생하며 초기화가 처리됩니다.

this.Button02_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    this.Dataset00.set_filterstr();
    this.Dataset00.filter();
};

3

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 검색어를 입력하고 검색 결과를 확인합니다.

25.21중복된 항목 제거하기

filter 메소드에 조건식을 사용해 중복된 데이터를 제거합니다. SQL문에서 DISTINCT 키워드와 비슷한 동작을 구현할 수 있습니다.

25.21.1예제

검색어를 입력하고 [Column0] 버튼을 클릭하면 Column0 컬럼의 데이터 중 중복된 항목을 제거하고 남은 결과를 표시하고 [Column1 && Column2] 버튼을 클릭하면 Column0 컬럼의 데이터 중 중복된 항목을 제거하거 남은 결과만 표시합니다. [Init] 버튼 클릭 시 검색결과를 초기화합니다.

sample_grid_74.xfdl

25.21.2예제에서 사용한 핵심 기능

findRowExpr

조건에 해당하는 결과 중 첫번째 Row 인덱스를 반환합니다. 조건은 맞지만 첫번째 Row 인덱스가 아니라면 중복된 결과로 판단하고 필터링합니다.

25.21.3예제 구현 방법

1

화면 구성하기

Grid 컴포넌트와 Button 컴포넌트를 예제 화면과 같이 배치합니다. Dataset 오브젝트를 아래와 같이 생성하고 바인딩해줍니다.

2

onclick 이벤트 함수 작성하기

[Column0] 버튼 클릭 시 Column0 컬럼 내에서 중복된 항목을 제거합니다.

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    var sExpr    = "rowidx==dataset.findRowExpr(\"Column0=='\" + Column0 + \"'\")";        
    this.Dataset00.filter(sExpr);   
};

[Column1 && Column2] 버튼 클릭 시에는 Column1, Column2 컬럼이 모두 중복된 항목을 제거합니다. 예제에서는 다른 컬럼을 설정한 경우에도 처리할 수 있도록 컬럼 정보를 파라미터로 받아서 처리합니다.

this.Button01_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    this.gf_distincDsFilter(this.Dataset00, "Column1,Column2");
};

this.gf_distincDsFilter = function(objDs, sColID)
{
    var arrArgs    = sColID.split(",");
    var sFilterExpr        = "";
    var sFindRowExpr    = "";
    
    for (var i=0; i<arrArgs.length; i++)
    {
        if (objDs.getColumnInfo(arrArgs[i]) == null) continue;
        
        sFindRowExpr    += (sFindRowExpr) ? " && " : "";
        sFindRowExpr    += "" + arrArgs[i] + "=='\" + " + arrArgs[i] + " + \"'";
    }
    
    if (sFindRowExpr) {
        sFilterExpr    = "rowidx==dataset.findRowExpr(\"" + sFindRowExpr + "\")";
    }
    objDs.filter(sFilterExpr);
};

[Init] 버튼 클릭 시 값을 초기화합니다.

this.Button02_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    this.Dataset00.filter("");
};

3

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 버튼을 클릭해 중복된 항목이 제거되는지 확인합니다.

25.22Radio 버튼 표현하기

Cell 오브젝트의 displaytype으로 Radio 컨트롤은 제공하지 않습니다. 하지만 필요에 따라 제시된 목록 중에서 하나만 선택해야 하는 경우 CheckBox 보다는 Radio 컨트롤이 사용자에게 더 익숙할 수 있습니다.

25.22.1예제

첫번째 컬럼에 Radio 컨트롤을 표시합니다. 해당 항목을 선택했을때 기존에 선택된 항목이 있다면 선택을 해제하고 하나의 항목만 선택하도록 합니다.

sample_grid_76.xfdl

25.22.2예제에서 사용한 핵심 기능

displaytype

바인딩된 데이터가 화면에 표시되는 형식을 설정합니다. "imagecontrol"을 속성값으로 지정한 경우에는 text 속성값에 이미지 파일이 있는 경로를 지정하거나 BLOB 값을 설정해주어야 합니다. 예제에서는 Column0 값에 따라 이미지 경로를 다르게 해서 체크된 상태를 보여줄 수 있도록 했습니다.

25.22.3예제 구현 방법

1

화면 구성하기

Grid 컴포넌트를 예제 화면과 같이 배치합니다. Dataset 오브젝트를 아래와 같이 생성하고 바인딩해줍니다.

2

Grid Contents Editor 실행하기

Column0 컬럼은 Radio 컨트롤 이미지만 표시할겁니다. size를 30 정도로 수정하고 head cell의 text 속성은 지웁니다. 그리고 body cell 속성에서 displaytype 속성값은 "imagecontrol", text 속성값은 이미지 경로로 수정합니다.

설정한 text 속성값은 아래와 같습니다.

expr:Column0==1?"theme://images/rdo_WF_Radio_S.png":"theme://images/rdo_WF_Radio_O.png"

3

oncellclick 이벤트 함수 작성하기

Radio 컨트롤이 표시되는 셀 클릭 시 Column0 값을 업데이트합니다. 클릭한 셀에 해당하는 데이터는 1로 나머지는 0으로 설정합니다.

this.Grid00_oncellclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    if (e.cell == 0)
    {
        this.Dataset00.set_enableevent(false);
        for(var i=0; i<this.Dataset00.rowcount; i++)
        {
            if (e.row == i)
            {
                this.Dataset00.setColumn(e.row,"Column0","1");
            }else{
                this.Dataset00.setColumn(i,"Column0","0");
            }    
        }
        this.Dataset00.set_enableevent(true);
    }
};

4

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 Radio 컨트롤이 표시되는 셀을 클릭해봅니다.

25.23세계 시간 표시하기

간단한 스크립트로 세계 시간을 Grid 컴포넌트에 표시하는 방법을 살펴봅니다. 타이머를 사용하고 갱신되는 시점에 시간 정보를 가져오기 때문에 아주 정확한 시간은 아닙니다.

25.23.1예제

화면 로딩 시 타이머 이벤트를 처리하며 1초마다 시간값을 새로고쳐서 표시합니다.

sample_grid_80.xfdl

25.23.2예제에서 사용한 핵심 기능

getTimezoneOffset

Date 오브젝트와 UTC(협정세계시) 사이의 시간차를 반환합니다. 예제에서는 Date 오브젝트에서 현재 시간 정보를 가져와서 UTC 시간으로 맞추기 위한 용도로 getTimezoneOffset 메소드를 사용합니다.

25.23.3예제 구현 방법

1

화면에 Grid 컴포넌트를 배치합니다.

2

Dataset 오브젝트를 Invisible Object 영역으로 배치하고 아래와 같이 데이터를 입력합니다. timezone 컬럼값은 Grid 컴포넌트에 표시하는 항목이고 timevalue 컬럼값은 offset 컬럼값을 가지고 계산한 결과를 보여줄 겁니다.

offset 컬럼값을 원하는 값으로 수정하면 다른 시간대를 확인할 수 있습니다.

3

Grid 컴포넌트에 Dataset 오브젝트를 바인딩합니다.

4

Grid 컴포넌트를 더블 클릭해 Grid Contents Editor를 띄웁니다.

5

offset 컬럼값은 계산을 위해 사용하고 화면에 보여주지 않습니다. 해당 컬럼을 삭제합니다.

6

Form 오브젝트에 onload, ontimer 이벤트 함수를 등록합니다.

onload 이벤트 함수에서는 타이머를 설정하고 ontimer 이벤트 함수에서는 1초마다 시간 정보를 받아서 Grid 컴포넌트의 timevalue 컬럼값에 값을 설정합니다.

this.sample_grid_80_onload = function(obj:nexacro.Form,e:nexacro.LoadEventInfo)
{
    this.setTimer(0, 1000);
};

this.sample_grid_80_ontimer = function(obj:nexacro.Form,e:nexacro.TimerEventInfo)
{
    for(var i=0;i<this.Dataset00.getRowCount();i++)
    {
        this.Dataset00.setColumn(i, 1, 
            this.getWorldTime(this.Dataset00.getColumn(i, 2)));
    }
};

7

시간값을 계산해서 반환할 getWorldTime 함수를 아래와 같이 작성합니다. 현재 시간을 1/1000 초 기준으로 계산(getTime)하고 이 값을 UTC 시간으로 보정한 후(getTimezoneOffset) 각 지역 시간대에 맞게 offSet 값을 더해서 해당 시간대의 시간 정보를 생성합니다.

this.getWorldTime = function(offSet)
{
    var objDate = new Date();
    var nTime = objDate.getTime() + (objDate.getTimezoneOffset() * 60000) + (offSet * 3600000);
    objDate.setTime(nTime);
    
      var s =
    this.fn_getDate(objDate.getFullYear(), 4) + '-' +
    this.fn_getDate(objDate.getMonth() + 1, 2) + '-' +
    this.fn_getDate(objDate.getDate(), 2) + ' ' +

    this.fn_getDate(objDate.getHours(), 2) + ':' +
    this.fn_getDate(objDate.getMinutes(), 2) + ':' +
    this.fn_getDate(objDate.getSeconds(), 2);
    
  return s;
}

fn_getDate 함수는 시간 값이 지정된 자리수보다 작은 경우 앞에 "0"을 채워서 표시합니다.

this.fn_getDate = function(n, digits) 
{
  var zero = '';
  n = n.toString();

  if (n.length < digits) {
    for (i = 0; i < digits - n.length; i++)
      zero += '0';
  }
  return zero + n;
}

8

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다. Grid 컴포넌트에 세계 시간이 표시되는지 확인합니다.

25.24PoupDiv 컴포넌트를 사용해 선택한 셀 테두리선 표현하기

PopupDiv 컴포넌트를 사용해 사용자가 선택한 셀 주변에 원하는 색상의 테두리선을 표현해봅니다.

25.24.1예제

특정 셀을 클릭하면 해당 셀 주변에 빨간 테두리선을 표시합니다. Grid 컴포넌트 외 다른 영역을 클릭하거나 다른 셀을 클릭하면 이전 테두리선은 사라집니다.

sample_grid_81.xfdl

25.24.2예제에서 사용한 핵심 기능

getCellRect

선택한 셀 좌표값을 반환합니다. 해당 좌표값에 따라 PopupDiv 컴포넌트를 띄워줍니다.

25.24.3예제 구현 방법

1

화면에 Grid 컴포넌트를 배치합니다.

2

Dataset 오브젝트를 Invisible Object 영역으로 배치하고 데이터를 입력합니다. 예제에서는 데이터가 큰 의미가 없기 때문에 2개의 컬럼을 만들고 1-5, A-E 까지의 텍스트를 입력했습니다.

3

Grid 컴포넌트에 Dataset 오브젝트를 바인딩합니다.

4

PopupDiv 컴포넌트를 배치합니다. visible 속성값은 false로 설정하고 border 속성은 원하는 스타일로 지정합니다. 예제에서는 아래와 같이 지정했습니다.

1px solid coral

5

Grid 컴포넌트에 oncellclick 이벤트 함수를 등록합니다. 셀 영역 클릭 시 선택한 셀 좌표값을 확인하고 해당 좌표값을 파라미터로 PopupDive 컴포넌트의 trackPopupByComponent 메소드를 실행합니다.

this.Grid00_oncellclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    var aryRect = this.Grid00.getCellRect(e.row, e.cell);
    
    var nX = aryRect.left;    
    var nW = aryRect.width;
    var nH = aryRect.height;
    var nY = nY = aryRect.top + 2;
    
    this.PopupDiv00.trackPopupByComponent(this.Grid00, nX, nY, nW, nH, "", false);
};

6

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다. Grid 컴포넌트의 셀 클릭 시 테두리선이 표시되는지 확인합니다.

25.25트리 구조에서 자식 정보 확인하기

트리 구조로 표현된 Grid 컴포넌트에서 선택한 셀의 자식 정보를 확인합니다.

25.25.1예제

특정 셀을 클릭했을때 하위 트리 정보가 있는 경우 TextArea 컴포넌트에 표시합니다. 해당 정보가 없으면 자식 정보가 없다고 표시합니다.

sample_grid_79.xfdl

25.25.2예제에서 사용한 핵심 기능

getTreeChildCount

특정 Row 아래의 자식 Row 정보를 반환합니다. 트리 구조인 경우에 하위 정보가 있는지 확인하는 용도로 사용합니다.

treeuseline

트리 형태인 경우 연결선을 표시합니다. 예제에서는 연결선을 보이지 않도록 false로 값을 설정했습니다. 연결선이 없더라도 레벨에 따라 들여쓰기된 상태로 표시됩니다.

treeusebutton

자식 Row 정보가 있는 경우에는 접거나 펴는 기능을 처리할 수 있습니다. 예제에서는 트리를 접을 수 없도록 treeusebutton 속성값을 "noclick"으로 지정했습니다. 이렇게 하면 버튼이 보이지도 않고 버튼 영역을 클릭해도 이벤트가 발생하지 않습니다.

25.25.3예제 구현 방법

1

화면에 Grid 컴포넌트와 TextArea 컴포넌트를 배치합니다.

2

Dataset 오브젝트를 추가하고 아래와 같이 데이터를 설정합니다.

3

Dataset 오브젝트를 Grid 컴포넌트로 드래그앤드롭해서 binddataset 속성으로 지정합니다.

4

Grid 컴포넌트를 더블클릭 해 Grid Contents Editor를 실행하고 첫 번째 컬럼 셀 속성값을 아래와 같이 수정합니다.

5

Grid 컴포넌트의 속성 중 CellTreeItem 그룹 아래의 속성 일부를 수정합니다.

트리 구조를 접을 수 없도록 treeusebutton 속성값을 "noclick"으로 지정하고 최초 상태가 모두 펼쳐진 상태로 표시되도록 treeinitstatus 속성값을 "expand,all"으로 지정합니다.

6

Grid 컴포넌트의 oncellclick 이벤트 함수를 아래와 같이 추가합니다.

getTreeChildCount 메소드로 자식 정보가 있는지 확인하고 자식 정보가 있다면 getTreeChildRow 메소드를 사용해 해당 Row의 인덱스 정보를 확인하고 정보를 TextArea 컴포넌트에 표시합니다.

this.Grid00_oncellclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    var numChildcount = this.Grid00.getTreeChildCount(this.Dataset00.rowposition);
    var strChildInfo = "ChildCount = "+numChildcount+"\n";

    for(var i=0; i<numChildcount; i++)
    {
        var numChildRow = this.Grid00.getTreeChildRow(this.Dataset00.rowposition, i, false);
        strChildInfo += "Row = "+numChildRow+", RowText = "+this.Grid00.getCellText(numChildRow, 0)+"\n";
    }
    this.TextArea00.set_value(strChildInfo);
};

7

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다. Grid 컴포넌트의 셀 클릭 시 자식 Row 정보가 표시되는지 확인합니다.

25.26데이터 정렬 시 null 값을 가장 위에 표시하기

keystring 속성을 사용하면 데이터 정렬을 처리할 수 있습니다. 하지만, 경우에 따라 null 값은 정렬 방향과 상관없이 무조건 위 또는 아래에 배치해야 하는 경우가 있습니다. 기본 옵션에서는 제공하지 않는 기능이라 약간의 트릭을 사용해야 합니다.

25.26.1예제

"null check" 버튼 클릭 시 null 값을 가장 위로 올리고 내림차순으로 데이터를 정렬합니다.

17.1.0.100 이후 버전에서는 문자열 정렬 방식이 변경됐습니다. 때문에 첫 번째 Button 컴포넌트 클릭 시 null 값이나 빈 값을 가장 위에 표시합니다. 해당 예제는 17.0 버전을 사용하거나 datatyperule 속성값을 "1.0"으로 지정해 사용하는 경우 참고해주세요.

데이터 정렬 방식 변경

sample_grid_87.xfdl

25.26.2예제에서 사용한 핵심 기능

copyRow

Dataset 오브젝트 간 특정 Row 데이터를 복사합니다. 예제처럼 임시로 값을 옮겨놓고 가공하는 경우에 사용할 수 있습니다.

25.26.3예제 구현 방법

1

화면에 Grid 컴포넌트와 Button 컴포넌트를 배치합니다.

2

Dataset 오브젝트를 추가하고 아래와 같이 데이터를 설정합니다. 임시로 사용할 Dataset 오브젝트는 id 속성값을 "dsTemp"로 지정하고 Columns 만 설정합니다.

null 값을 예외 처리하는 예제이기 때문에 Column0 항목에 null 값을 설정해주어야 합니다. 값을 지정하지 않으면 null 값이 설정되고 컨텍스트 메뉴에서 [Set Null] 항목을 선택해도 null 값을 설정할 수 있습니다.

3

첫 번째 Button 컴포넌트 클릭 시에는 내림차순으로 정렬만 합니다. 이 경우에는 null 값은 마지막에 배치됩니다.

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    this.Dataset00.set_keystring("S:-Column0");
};

4

두 번째 Button 컴포넌트 클릭 시에는 null 값을 체크해서 임시 Dataset 오브젝트로 복사한 후 나중에 다시 값을 가져옵니다.

this.Button01_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    for(var i=0 ; i < this.Dataset00.rowcount; i++){
        if(this.Dataset00.getColumn(i,"Column0") == null){
            var nRow = this.dsTemp.addRow();
            this.dsTemp.copyRow(nRow,this.Dataset00,i);
        }
    }
    
    for(var k=this.Dataset00.rowcount-1 ; k >= 0; k--){
        if(this.Dataset00.getColumn(k,"Column0") == null){
            this.Dataset00.deleteRow(k);
        }
    }

    this.Dataset00.set_keystring( "S:-Column0" );
    
    for(var l=0; l < this.dsTemp.rowcount; l++){
        this.Dataset00.insertRow(l);
        this.Dataset00.copyRow(l,this.dsTemp,l);
    }
};

5

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다. null 값이 어느 부분에 위치하면서 정렬되는지 확인합니다.

25.27데이터 너비에 맞추어 컬럼 너비 조절하기

Grid 컴포넌트의 autosizingtype 속성값을 지정하지 않고 동적으로 데이터 너비에 맞추어 컬럼 너비를 조절하는 방법을 살펴봅니다. Grid 컴포넌트에서 지원하는 기능은 아니고 약간의 트릭을 사용합니다.

25.27.1예제

Grid 컴포넌트 컬럼 헤더 영역을 클릭하면 해당 컬럼 너비가 데이터 너비에 맞추어 조절됩니다.

sample_grid_90.xfdl

25.27.2예제에서 사용한 핵심 기능

getOffsetWidth

동적으로 계산된 컴포넌트의 너비값을 반환합니다.

setFormatColProperty

컬럼 속성값을 설정합니다. 예제에서는 너비값을 재정의합니다.

25.27.3예제 구현 방법

1

화면에 Grid 컴포넌트와 Static 컴포넌트를 배치합니다.

2

Dataset 오브젝트를 추가하고 아래와 같이 데이터를 설정합니다. 데이터는 적당한 길이로 기본 Grid 컴포넌트의 컬럼 너비에서 보이지 않을 정도로만 지정합니다.

3

데이터가 입력되었다면 Grid 컴포넌트와 바인딩해줍니다.

4

Static 컴포넌트의 visible 속성값을 false로 지정하고 fittocontents 속성값은 "width"로 지정합니다. Static 컴포넌트는 너비 조정을 위한 보조 용도로 사용합니다.

5

Grid 컴포넌트의 onheadclick 이벤트 함수를 아래와 같이 작성합니다.

컬럼 헤더 영역을 클릭하게 되면 해당 컬럼 위치의 데이터 중에서 가장 긴 문자열을 확인하고 해당 문자열을 Static 컴포넌트의 text 속성값으로 설정합니다. 그리고 resetScroll 메소드를 실행하게 되면 fittocontents 속성 설정에 따라 Static 컴포넌트의 너비가 조정됩니다. 그러면 해당 너비값을 기준으로 컬럼 너비값을 조정합니다.

this.Grid00_onheadclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    var nMaxVal = 0;
    var nCurrVal = 0;
    var sMaxText = null;
    for(var i=0; i<this.Dataset00.rowcount; i++) {        
        nCurrVal = this.Dataset00.getColumn(i, e.col).length;
        if(nCurrVal > nMaxVal) {
            nMaxVal = nCurrVal;
            sMaxText = this.Dataset00.getColumn(i, e.col);
        }
    }
    this.staTemp.set_text(sMaxText);
    this.resetScroll();
    this.Grid00.setFormatColProperty(e.col, "size", this.staTemp.getOffsetWidth()+10);
};

6

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다. 컬럼 헤더 영역을 클릭하면 컬럼 너비가 조절되는지 확인합니다.

25.28특정 Grid 컴포넌트만 합계 Row 추가하기

Grid 컴포넌트에 사용자 속성을 추가하고 사용자 속성값에 따라 특정 기능을 추가하는 방법을 살펴봅니다.

25.28.1예제

버튼 클릭 시 첫 번째, 두 번째 Grid 컴포넌트 마지막 Row에 합계값을 보여줍니다.

sample_grid_93.xfdl

25.28.2예제에서 사용한 핵심 기능

getSum

Dataset 오브젝트에서 필터링되지 않은 Row 영역의 합계값을 반환합니다.

getCellCount

Grid 컴포넌트의 특정 밴드(예제에서는 body 밴드)의 Cell 개수를 반환합니다. 예제에서는 body 밴드에 하나의 Row만 있기 때문에 Cell 개수가 컬럼 개수와 같습니다. getCellCount 대신 바인딩된 Dataset 오브젝트의 getColCount 메소드를 사용해도 같은 결과를 반환합니다.

25.28.3예제 구현 방법

1

화면에 Grid 컴포넌트와 Button 컴포넌트를 배치합니다.

2

Dataset 오브젝트를 추가하고 아래와 같이 데이터를 설정합니다. 합계값을 계산해야 하기 때문에 type 항목은 "INT"로 지정합니다. 3개의 Grid 컴포넌트에 각각 다른 Dataset 오브젝트를 만들어서 바인딩합니다.

3

데이터가 입력되었다면 Grid 컴포넌트와 바인딩해줍니다.

4

첫 번째와 두 번째 Grid 컴포넌트를 선택하고 속성창에서 오른쪽 마우스 클릭 후 [Add User Property] 항목을 선택해 "summ"이라는 이름의 속성을 추가하고 값은 "Y"로 설정합니다.

5

Button 컴포넌트의 onclick 이벤트 함수를 아래와 같이 작성합니다.

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
    this.fn_setSumm(this);
};

합계값을 처리하는 것은 fn_setSumm 함수에서 처리합니다. Form에 속한 자식 중에서 Grid 컴포넌트를 찾아내고 Grid 컴포넌트의 사용자 속성 summ의 속성값이 "Y"인 항목을 찾습니다.

Grid 컴포넌트에 바인딩된 Dataset 오브젝트를 찾은 다음 Row를 추가하고 합계값을 설정합니다.

this.fn_setSumm = function(obj)
{
    var colNm;
    var objGrd;
    var objDs;
    for(var i=0; i<obj.all.length; i++){
        if( obj.all[i].toString() == "[object Grid]" ){
            objGrd = obj.all[i];
            if( objGrd.summ == "Y"){
                objDs = obj.all[objGrd.binddataset];    
                var idx = objDs.addRow();
                for(var j=0; j<objGrd.getCellCount("body"); j++){
                    colNm = objGrd.getCellProperty("body", j, "text").split(":");
                    objDs.setColumn(idx, colNm[1], objDs.getSum(colNm[1], 0, objDs.rowcount-1));
                }
            }    
        }
    }
}

세 번째 Grid 컴포넌트는 summ이라는 속성이 없기 때문에 objGrd.summ 값이 null로 처리되고 해당 조건문에서 false로 처리됩니다.

6

QuickView(Ctrl + F6)를 실행하여 결과를 확인합니다. 버튼 클릭 시 첫 번째와 두 번째 Grid 컴포넌트에 Row가 추가되고 합계값이 표시되는지 확인합니다.

25.29선택한 영역의 합계 보여주기

Grid 컴포넌트의 selecttype 속성값을 "area"로 지정한 경우 선택한 영역의 합계를 보여줍니다.

25.29.1예제

SHIFT 키를 같이 사용해 특정 영역의 셀을 선택하면 선택한 셀의 합계값을 보여줍니다.

sample_grid_98.xfdl

25.29.2예제에서 사용한 핵심 기능

getSum

getSum 메소드의 첫 번째 파라미터는 컬럼 ID를 지정할 수도 있지만, 계산식을 설정할 수 있습니다. 예제에서는 선택한 컬럼이 2개인 경우 2개 컬럼의 값을 더하는 식을 첫 번째 파라미터로 지정합니다.

25.29.3예제 구현 방법

1

화면에 Grid 컴포넌트와 PopupDiv 컴포넌트를 배치합니다.

PopupDiv 컴포넌트 안에는 Static 컴포넌트를 배치합니다. Static 컴포넌트에서 합계값을 표시합니다.

2

Dataset 오브젝트를 추가하고 아래와 같이 데이터를 설정합니다. 합계값을 계산해야 하기 때문에 type 항목은 "INT"로 지정합니다.

3

데이터가 입력되었다면 Grid 컴포넌트와 바인딩해줍니다.

4

Grid 컴포넌트의 selecttype 속성값을 "area"로 설정합니다.

5

Grid 컴포넌트의 onkeydown 이벤트 함수를 아래와 같이 작성합니다.

Grid 컴포넌트에서 SHIFT 키를 눌러 여러 영역을 선택하는 경우 특정한 변수값을 설정합니다.

this.nShift = 0;
this.Grid00_onkeydown = function(obj:nexacro.Grid,e:nexacro.KeyEventInfo)
{
    if(e.keycode == 16) {
        this.nShift = 1;
    } else {
        this.nShift = 0;
    }
};

6

Grid 컴포넌트의 onlbuttonup 이벤트 함수를 아래와 같이 작성합니다.

Grid 컴포넌트의 특정 셀에서 SHIFT 키를 누른 상태에서 마우스 버튼을 놓았을 때 합계값을 처리합니다.

this.Grid00_onlbuttonup = function(obj:nexacro.Grid,e:nexacro.GridMouseEventInfo)
{
    if(this.nShift == 1) {
        var strColExpr;
        if(obj.selectstartcol==0) {
            if(obj.selectendcol==1) {
                strColExpr = "Column0+Column1";
            } else {
                strColExpr = "Column0";
            }
        } else {
            strColExpr = "Column1";
        }
        
        var nTot = this.Dataset00.getSum(strColExpr, obj.selectstartrow, Number(obj.selectendrow)+1);
        
        this.PopupDiv00.form.Static00.set_text("SUM : "+nTot);
        this.PopupDiv00.form.Static00.set_fittocontents('width');
        this.PopupDiv00.form.resetScroll();
        this.PopupDiv00.trackPopupByComponent(obj,e.canvasx,e.canvasy);
        this.nShift = 0;
    }
};

7

PopupDiv 컴포넌트의 oncloseup 이벤트 함수를 아래와 같이 작성합니다.

this.PopupDiv00_oncloseup = function(obj:nexacro.PopupDiv,e:nexacro.EventInfo)
{
    obj.form.Static00.set_text("");
};

8

QuickView(Ctrl + F6)를 실행하여 특정 영역 선택 시 해당하는 값의 합계가 표시되는지 확인합니다.

25.30클릭한 셀 표시하기

Grid 컴포넌트의 selecttype 속성값을 "row"로 지정한 경우 선택한 Row는 표시되는데 클릭한 셀은 따로 표시하지 않습니다. 클릭한 셀을 다른 형식으로 표시하는 예제입니다.

25.30.1예제

클릭한 셀은 다른 배경색으로 표시합니다.

sample_grid_99.xfdl

25.30.2예제에서 사용한 핵심 기능

getBindCellIndex

Dataset 오브젝트의 특정 컬럼과 바인드된 첫 번째 Cell 인덱스를 반환합니다. Grid 컴포넌트에서 클릭한 셀의 인덱스를 확인하기 위한 용도로 사용했습니다.

getCellPos

선택한 셀의 인덱스값을 반환합니다. 예제에서는 getBindCellIndex 메소드에서 반환한 값과 getCellPos 메소드에서 반환한 값을 비교합니다.

25.30.3예제 구현 방법

1

화면에 Grid 컴포넌트를 배치합니다.

2

Dataset 오브젝트를 추가하고 아래와 같이 데이터를 설정합니다. Row는 값은 지정하지 않고 5개 정도만 추가합니다.

3

데이터가 입력되었다면 Grid 컴포넌트와 바인딩해줍니다.

4

Grid 컴포넌트를 더블 클릭하고 Grid Contents Editor를 실행합니다.

5

body 밴드의 각 셀을 선택하고 cssclass 속성값을 아래와 같이 지정합니다.

getBindCellIndex 메소드의 컬럼 아이디 문자열은 각 컬럼에 맞게 지정합니다.

expr:comp.getBindCellIndex("body","Column0")==comp.getCellPos()?'sample_grid_99_cellclick':''

6

Grid 컴포넌트의 oncellclick 이벤트 함수를 아래와 같이 작성합니다.

this.Grid00_oncellclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    obj.redrawExprCell("body");
};

7

xcss 파일을 열어서 아래 코드를 추가합니다.

Advanced 탭에서 선택자를 추가하거나 Text 탭에서 직접 코드값을 입력할 수 있습니다.

.Grid .body .row .cell.sample_grid_99_cellclick[userstatus=selected]
{
    -nexa-background-odd : lawngreen;
    background : lawngreen; 
}

8

QuickView(Ctrl + F6)를 실행하여 셀 클릭 시 해당 Row가 선택되고 클릭한 셀의 배경색이 변경되는 것을 확인합니다.

25.31트리를 펼치거나 접을 때 하위 레벨 데이터 보이게 하기

트리 형태일 때 데이터가 적으면 별 문제가 없지만 Grid 컴포넌트 영역보다 데이터가 많은 경우에는 트리를 펼쳤을때 하위 레벨 데이터가 바로 보이지 않는 문제가 있습니다. 예제에서는 선택한 하위 레벨 데이터가 좀 더 잘 보일 수 있는 방법을 살펴봅니다.

25.31.1예제

"3" 항목을 펼쳤을때 오른쪽 Grid는 스크롤 위치 조정을 하지 않아서 하위 레벨 데이터가 보이지 않습니다. 왼쪽 Grid에서는 선택한 항목을 위에 보이도록 위치를 조정합니다.

sample_grid_100.xfdl

25.31.2예제에서 사용한 핵심 기능

getRealRowSize

특정 Row의 높이를 반환합니다. Grid 컴포넌트 설정 시 지정한 Row의 높이값은 다른 속성 설정이나 데이터에 따라 실제 보여지는 높이가 달라질 수 있어서 getRealRowSize 메소드를 사용해 실제 높이값을 확인합니다.

getTreeRow

트리 구조에서 Row 위치를 반환합니다. 예제에서 "2" 항목을 클릭하는 경우 선택한 Row의 index는 6이지만, 펼쳐지지 않은 트리 아이템을 제외하고 보여지는 Row의 index는 2가 됩니다. getTreeRow 메소드는 펼쳐지지 않은 트리 아이템을 제외하고 화면에 보여지는 Row index를 반환합니다.

25.31.3예제 구현 방법

1

화면에 Grid 컴포넌트를 배치합니다.

2

Dataset 오브젝트를 추가하고 아래와 같이 데이터를 설정합니다.

<ColumnInfo>
  <Column id="Column0" type="STRING" size="256"/>
  <Column id="Column1" type="STRING" size="256"/>
</ColumnInfo>
<Rows>
  <Row>
    <Col id="Column0">0</Col>
    <Col id="Column1">ROOT</Col>
  </Row>
  <Row>
    <Col id="Column0">1</Col>
    <Col id="Column1">1</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">1-2</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">1-3</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">1-4</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">1-5</Col>
  </Row>
  <Row>
    <Col id="Column0">1</Col>
    <Col id="Column1">2</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">2-1</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">2-2</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">2-3</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">2-4</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">2-5</Col>
  </Row>
  <Row>
    <Col id="Column0">1</Col>
    <Col id="Column1">3</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">3-1</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">3-2</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">3-3</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">3-4</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">3-5</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">3-6</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">3-7</Col>
  </Row>
  <Row>
    <Col id="Column0">1</Col>
    <Col id="Column1">4</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">4-1</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">4-2</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">4-3</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">4-4</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">4-5</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">4-6</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">4-7</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">4-8</Col>
  </Row>
  <Row>
    <Col id="Column0">2</Col>
    <Col id="Column1">4-9</Col>
  </Row>
</Rows>

3

데이터가 입력되었다면 Grid 컴포넌트와 바인딩해줍니다.

4

Grid 컴포넌트를 더블 클릭하고 Grid Contents Editor를 실행합니다.

5

body 밴드의 셀을 선택하고 아래와 같이 속성값을 설정합니다.

displaytype: treeitemcontrol
edittype: tree
treelevel: bind:Column0

6

Grid 컴포넌트와 Dataset 오브젝트를 복사해서 새로운 Grid 컴포넌트와 Dataset 오브젝트를 만듭니다.

7

복사해서 만든 Grid 컴포넌트의 binddataset 속성값을 복사해서 만든 Dataset 오브젝트로 변경합니다.

8

원래 있던 Grid 컴포넌트의 oncellclick 이벤트 함수를 아래와 같이 작성합니다.

this.Grid00_oncellclick = function(obj:nexacro.Grid,e:nexacro.GridClickEventInfo)
{
    if(obj.getBindDataset().getColumn(e.row, "Column0" ) == '1')
    {
        var nRowSize = obj.getRealRowSize(0);
        var nPos = obj.getTreeRow(e.row) * nRowSize;
        trace(e.row);
        trace(obj.getTreeRow(e.row));
        obj.vscrollbar.set_pos(nPos);
    }    
};

9

QuickView(Ctrl + F6)를 실행하여 트리 구조의 아이템을 클릭해서 두 개 Grid 컴포넌트의 스크롤 위치를 비교해봅니다.

25.32Grid 컴포넌트로 달력 형태의 일정표 만들기

일정이 있는 날짜를 달력에 표시하고 해당 날짜 선택 시 상세 일정을 확인할 수 있는 일정표를 만드는 예제입니다. Grid 컴포넌트로 달력을 표현하고 ListBox 컴포넌트에 선택한 날짜의 상세 일정을 표시합니다.

예제에서는 2020년 9월과 10월 일정을 Dataset 오브젝트에 직접 추가했습니다.

25.32.1예제

일정이 있는 날짜에는 밑줄이 표시되고 해당 날짜를 클릭하면 상세 일정 목록을 표시합니다.

sample_grid_103.xfdl

25.32.2예제에서 사용한 핵심 기능

getCaseCountNF

조건표현식에 만족하는 Row 전체 갯수를 반환합니다. 예제에서는 해당 날짜에 해당하는 일정이 데이터에 있는지 확인하기 위한 용도로 사용했습니다. ListBox 컴포넌트에 데이터를 보여주기 위해 필터링를 한 상태라 getCaseCount 메소드가 아닌 getCaseCountNF 메소드를 사용했습니다.

25.32.3예제 구현 방법

1

화면에 아래와 같이 컴포넌트를 배치합니다.

2

Dataset 오브젝트를 추가하고 아래와 같이 데이터를 설정합니다.

7개의 컬럼은 일요일부터 토요일까지를 처리합니다. Row는 5개를 추가해 7*5 형태의 Grid 컴포넌트를 표현할 수 있도록 합니다.

3

데이터가 입력되었다면 Grid 컴포넌트와 바인딩해줍니다.

4

Grid 컴포넌트를 더블 클릭하고 Grid Contents Editor를 실행합니다.

5

head 밴드의 셀을 선택하고 요일명으로 text 속성값을 변경합니다.

6

Body 밴드의 셀을 선택하고 displaytype 속성값을 "decoratetext"로 변경합니다.

7

각 요일별 expr 속성값을 아래와 같이 변경합니다.

일요일과 토요일은 빨간색과 파란색으로 표시하고 일정이 있는 날짜는 fn_checkTable 함수에서 체크해서 밑줄을 표시합니다.

Sun: comp.parent.fn_checkTable(cal0)>0?"<fc v='red'><u v='true'>"+cal0+"</u></fc>":cal0?"<fc v='red'>"+cal0+"</fc>":cal0
Mon~Fri: comp.parent.fn_checkTable(cal1)>0?"<u v='true'>"+cal1+"</u>":cal1
Sat: comp.parent.fn_checkTable(cal6)>0?"<fc v='blue'><u v='true'>"+cal6+"</u></fc>":cal6?"<fc v='blue'>"+cal6+"</fc>":cal6
this.fn_checkTable = function(strDay)
{
    return this.Dataset00.getCaseCountNF("date == '"+this.fn_getDateString(strDay)+"'");
}

this.fn_getDateString = function(strDay)
{
    return new nexacro.Date(this.Combo00.value ,this.Combo01.value ,strDay).toString();
}

8

2개의 컬럼을 가지는 Dataset 오브젝트를 2개 추가합니다.

9

Combo 컴포넌트에 2개의 컬럼을 가지는 Dataset 오브젝트를 innerdataset으로 바인딩합니다.

10

date, title 컬럼을 가지는 Dataset 오브젝트를 추가합니다.

데이터는 date 컬럼에 "YYYYMMDD" 형태로 날짜를 입력하고 title 컬럼에는 ListBox 컴포넌트에 표시할 텍스트를 입력합니다.

11

ListBox 컴포넌트에 Dataset 오브젝트를 innerdataset으로 바인딩합니다.

12

Form 오브젝트의 onload 이벤트 함수를 아래와 같이 추가합니다.

예제에서는 2020년 9월과 10월 데이터만 만들어놓아서 2020년 9월 1일로 날짜를 설정했습니다. 그리고 해당 년도와 월을 기준으로 Combo 컴포넌트에 표시될 데이터를 설정하고 Grid 달력에 표시할 날짜를 처리합니다.

this.sample_grid_103_onload = function(obj:nexacro.Form,e:nexacro.LoadEventInfo)
{
    var date = new nexacro.Date(2020,8,1);
    this.fn_setYear(date.getFullYear());
    this.fn_setMonth(date.getMonth());
    this.fn_setCalendar();    
};

13

년도를 표시하는 Dataset 오브젝트의 데이터를 처리하는 fn_setYear 함수를 아래와 같이 추가합니다.

2020년을 기준으로 이전 100년(1920년), 이후 100년(2120년)을 Dataset 오브젝트에 추가하고 Combo 컴포넌트에 보여질 수 있도록 합니다.

this.minYear = -100;
this.maxYear = 100;

this.fn_setYear = function(numCurrentYear)
{
    this.ds_Year.set_enableevent(false);
    for(var i=numCurrentYear+this.minYear ; i<=numCurrentYear+this.maxYear ; i++)
    {
        var nRow = this.ds_Year.addRow();
        this.ds_Year.setColumn(nRow, 0, i);
        this.ds_Year.setColumn(nRow, 1, i);
    }
    this.ds_Year.set_enableevent(true);
    this.Combo00.set_value(numCurrentYear);
}

14

Combo 컴포넌트의 type 속성값은 "search"로 변경합니다.

15

년도를 표시할 Combo 컴포넌트의 displayrowcount 속성값을 5로 설정합니다.

16

월를 표시하는 Dataset 오브젝트의 데이터를 처리하는 fn_setMonth 함수를 아래와 같이 추가합니다.

this.fn_setMonth = function(numCurrentMonth)
{
    this.ds_Month.set_enableevent(false);
    for(var i=0 ; i<12 ; i++)
    {
        var nRow = this.ds_Month.addRow();
        this.ds_Month.setColumn(nRow, 0, i);
        this.ds_Month.setColumn(nRow, 1, i+1);
    }
    this.ds_Month.set_enableevent(true);
    this.Combo01.set_value(numCurrentMonth);
}

17

Combo 컴포넌트의 onitemchanged 이벤트 함수를 아래와 같이 추가합니다.

년도나 월 선택값을 변경하면 Grid 컴포넌트에 표시하는 날짜를 업데이트합니다.

this.Combo_onitemchanged = function(obj:Combo, e:nexacro.ItemChangeEventInfo)
{
    this.fn_setCalendar();
}

18

Grid 컴포넌트에 날짜를 처리하는 fn_setCalendar 함수를 아래와 같이 추가합니다.

선택한 년도와 월에 해당하는 날짜값을 배열로 생성하고 해당 배열값 순서에 따라 Grid 컴포넌트에 바인딩된 Dataset 오브젝트에 데이터를 설정합니다.

this.fn_setCalendar = function()
{
    var y = nexacro.toNumber(this.Combo00.value);    
    var m = nexacro.toNumber(this.Combo01.value);
    
    var arr = this.getCalendarArr(y,m);

    this.ds_calendar.set_enableevent(false);
    this.ds_calendar.clearData();
    for(var i = 0 ; i < arr.length ; i++){
        this.ds_calendar.addRow();
        for(var y = 0 ; y < arr[i].length; y++)
        {
            if(arr[i][y] != null){ this.ds_calendar.setColumn(i,y, arr[i][y]); }
        }
    }
    this.ds_calendar.set_enableevent(true);
    this.Dataset00.filter("date == '00000000'");
    this.Grid00.clearSelect();
}

this.getCalendarArr = function(y,m,d)
{
    var date = new nexacro.Date();
    date.setFullYear(y, m , 1);
    return this.get_DateArr(date, new Array(), m);
}

this.get_DateArr = function(date, arr , month)
{
    if(month != date.getMonth())
        return arr;
        
    var idx = date.getDay();
    if(arr.length == 0 ) {
        arr[0] = new Array();
    } else {
        if(idx == 0) {
            arr[arr.length] = new Array();
        }
    }
    arr[arr.length-1][idx] = date.getDate();
    date.addDate(1);
    return this.get_DateArr(date, arr, month);
}

19

상단에 배치한 Button 컴포넌트에 User Properties를 추가합니다.

User Properties를 추가해 onclick 이벤트 함수를 하나로 처리합니다.

User Properties

1

2

3

4

dataType

year

month

month

year

dataValue

-1

-1

1

1

20

Button 컴포넌트의 onclick 이벤트 함수를 아래와 같이 추가합니다.

버튼 클릭 시 년도와 월을 변경합니다.

this.Button_onclick = function(obj:Button,  e:nexacro.ClickEventInfo)
{
    if(obj.dataType == "month")
    {
        var numMonth = nexacro.toNumber(this.Combo01.value)+nexacro.toNumber(obj.dataValue);
        var value = (numMonth%12)!=0 ? (numMonth%12) : 0;
        trace(value);
        this.Combo01.set_value(value);
    } 
    else if(obj.dataType == "year") 
    {
        var numYear = nexacro.toNumber(this.Combo00.value)+nexacro.toNumber(obj.dataValue);
        this.Combo00.set_value(numYear);
    }
    this.fn_setCalendar();
}

21

Grid 컴포넌트의 oncellclick 이벤트 함수를 아래와 같이 추가합니다.

선택한 날짜에 따라 ListBox 컴포넌트에 바인딩된 Dataset 오브젝트의 데이터를 필터링합니다.

this.Grid00_oncellclick = function(obj:Grid, e:nexacro.GridClickEventInfo)
{
    this.Dataset00.filter("date == '"+this.fn_getDateString(this.ds_calendar.getColumn(e.row,e.cell))+"'");
}

22

QuickView(Ctrl + F6)를 실행하여 2020년 9월 달력이 표시되는지 확인하고 밑줄로 표시된 날짜의 상세 데이터를 확인합니다.