# 기초 개발자 교육 (appendix)

목차

1. 제품 파일 구성
2. 기본 시트 생성 방법
3. 함수와 이벤트
4. 시트 구조 이해 (Header, Head, Body, Foot, Solid)
5. Def 와 `ibsheet-common.js`
6. 렌더링과 데이터 로드
7. 데이터 추출과 저장
8. Formula 기능 사용
9. Solid (appendix), Menu (appendix), 달력 기능
10. 커스텀 다이얼로그 기능 사용
11. 파일 export/import 기능 사용
12. FAQ

## 1. 제품 파일 구성

IBSheet8 기본 파일 구성에 대해 설명하고(참고), `plugins 파일` 3개의 역할을 설명합니다.

## 2. 기본 시트 생성 방법

간단하게 javascript를 이용하여 시트 객체를 생성하는 방법을 설명합니다.(참고)

    var OPT = {
    	Cfg:{
    		Alternate:2, HeaderMerge:3
    	},
    	LeftCols:[
    		{ Header: "No", Name: "SEQ", Type: "Text", Width:40, Align:"Center"},
    	],
    	Cols:[
    		{ Header: "이름", Name: "sa_nm", Type: "Text", Width:80},
    		{ Header: "성별", Name: "sa_gender", Type: "Enum", Enum:"|남|여",EnumKeys:"|M|F", MinWidth:50},
    		{ Header: "사원번호", Name: "sa_id", Type: "Text", Align: "center", Width:70,Size:6,EditMask:"^\\d*$"},
    		{ Header: "부서", Name: "sa_dept", Type: "Enum", Enum: "|경영지원|총무|인사|설계|시공1|시공2", EnumKeys: "|01|02|03|04|05|06",Width:80 },
    		{ Header: "직급", Name: "sa_position", MinWidth:60, MaxWidth:60, Type: "Enum", Enum: "|대표|상무|이사|부장|차장|과장|대리|사원", EnumKeys: "|A1|A2|A3|B0|B1|C4|C5|C6"},
    		{ Header: "입사일",	Name: "sa_enterdate", Type: "Date", Width:100, Format: "yyyy/MM/dd", DataForamt:"yyyyMMdd", EditFormat:"yyyy-MM-dd"},
    		{ Header: "급여", Name: "sa_salary", Type: "Int", Width:80},
    		{ Header: "퇴직여부", Name: "sa_retire", Type: "Radio", Enum:"|퇴직|재직", EnumKeys:"|Y|N",Align:"center",MinWidth:125},
    		{ Header: "비고", Name: "sa_desc", Type: "Lines", RelWidth:1 }
    	]
    };

    IBSheet.create({
    	id:"mySheet",   //생성하는 시트 이름
    	el:"sheet_DIV", //시트가 생성될 div 객체 id
    	options:OPT     //ibsheet 기본 설정
    });

## 3. 함수와 이벤트

ibsheet 함수 와 이벤트에 대한 기본적인 사용법을 설명합니다.

#### 1) 기본적인 함수 사용 방법

- 자주 사용되는 함수

함수명 | 기능설명
--- | ---
getValue | 셀의 값을 얻음
setValue | 셀의 값을 수정
getString | 포멧이 적용된 셀의 값을 얻음
setString | 포멧을 포함한 문자열로 셀값을 수정
setAllCheck | bool타입 컬럼에서 전체 체크
getAttribute | 행,열,셀의 속성을 얻음
setAttribute | 행,열,셀의 속성을 수정
addRow | 행 추가
deleteRow | 행 삭제
removeAll | 전체 데이터 제거
dispose | 시트객체 초기화
focus | 특정 위치로 포커스 이동
doSort | 특정 컬럼 소팅
doFilter | 특정 컬럼 필터링
makeSubTotal | 소계 삽입 기능
version | 제품의 버젼확인

#### 2) 이벤트 사용 방법

- 자주 사용되는 이벤트

이벤트명 | 기능설명
--- | ---
onAfterClick | 클릭시 발생 이벤트
onDblClick | 더블클릭시 발생 이벤트
onBeforeChange | 셀 값이 수정되기 전 발생 이벤트
onAfterChange | 셀의 값이 수정된 후 발생 이벤트
onFocus | 시트 내에 포커스가 이동될때 발생 이벤트
onRenderFirstFinish | 시트 객체가 최초 생성되었을 때 발생 이벤트

#### 3) JSON 이벤트 (Properties/Event)

- 특정 행이나 열 혹은 셀에 이벤트 정의(참고)

## 4. 시트 구조 이해

아이비시트 각 구조 (헤더, 헤드, 바디, 풋)에 대해 이해하고, 행/열 객체에 대해 설명합니다.

#### 1) 헤더행 2줄, 배경색, 글자색, 내용 변경하기

> 시트에 여러개의 헤더행을 생성할 수 있습니다.
> 헤더행은 생성 후에도 타이틀을 변경하거나, 속성(글자색,배경색 등)을 변경할 수 있습니다.

    //시트 생성부
    options.Cols = [
    	{ Header : ["개인정보","이름"], Type : "Text", Name : "userName" },  //헤더행 두줄
    	{ Header : ["개인정보",{Value:"전화번호",Color:"#DDD",TextColor:"#FF4433"}], Type : "Text" ...} //헤더행 글자, 배경색 설정하기
    ];

    //생성 후 해더 내용/속성 변경하기
    	//헤더가 한줄일때는 "Header" 라는 ID을 갖고 2번째 헤더행부터는 HR1,HR2… 식으로 ID를 갖습니다.
    	sheet.setValue(sheet.getRowById("Header"), "sa_nm" , "성명", 1 );//첫번째 헤더행 내용 변경
    	sheet.setAttribute({row:sheet.getRowById("HR1"),attr:"Color",val:"#FFED37"}); //두번째 해더행의 배경색 변경

#### 2) 행 객체에 대한 접근 및 값 확인(참고)

> ***시트 내에 모든 행은 `id`를 갖고 있고, 이 `id`를 통해 접근할 수 있습니다.***
> 첫번째 헤더행의 `id`는 `Header`이고 두번째 이후부터는 HR1, HR2… 식으로 자동 부여됩니다.
> 데이터 행의 `id`는 생성 순서대로 AR1, AR2, AR3… 식으로 자동 부여됩니다.
> 이외에 필터행은 `Filter`, 합계행은 `FormulaRow`등의 이름을 갖고 있습니다.
> Head,Foot,Solid등의 행을 만들때는 직접 `id`를 지정하실 수 있습니다.

    /**  행 객체 얻기 **/
    //첫번째 데이터 행
    var headerRow = sheet.getFirstRow();
    //포커스 행
    var focusRow = sheet.getFocusedRow();
    //포커스된 행의 아래 행
    var nrow = sheet.getNextRow(  sheet.getFocusedRow() );
    //포커스된 행의 위 행
    var nrow = sheet.getPrevRow(  sheet.getFocusedRow() );
    //10번째 데이터 행
    var row = sheet.getRowByIndex( 10 );
    //합계행
    var sumRow = sheet.getRowById("FormulaRow");

    //전체 데이터 행 얻기
    var dataRows = sheet.getDataRows();
    //현재 보여지는 행 얻기
    var dataRows = sheet.getShownRows();

    /** 행 객체 내에 값 확인 및 수정**/
    var edit = sheet.getRowById("AR2").CanEdit;
    var edit = sheet.getAttribute(sheet.getFocusedRow() , null , "CanEdit" );

    sheet.setAttribute(sheet.getFocusedRow(), null, "Color" , "#FF0000",0);

#### 3) 열 속성 변경(참고)

> 시트 생성 시 Cols 속성을 통해 설정되는 컬럼에는 반드시 Name과 Type을 지정해 주셔야 합니다.
> 시트가 생성된 이후에는 각 컬럼에 부여한 Name을 기준으로 컬럼의 속성을 확인하거나 변경할 수 있습니다.

다음과 같은 Name은 예약어로 사용에 주의가 필요합니다. (대/소문자 유의)

예약어 | 용도
--- | ---
SEQ | Type과 무관하게 자동으로 증가하는 숫자형식으로 동작 (모든 시트에는 SEQ가 존재)
id | 모든 행은 고유한 id가 있으므로 id를 별도로 컬럼이름으로 사용 불가 (조회데이터에 "`id`"가 포함된 경우 `"___id"`로 조회됨.)
STATUS | getSaveJson(), doSave() 등 저장함수 호출시 자동으로 서버로 전송되는 상태값으로 사용

    //모든 컬럼명 얻기
    var cols = sheet.getCols();

    //컬럼 속성 확인
    var color = sheet.getAttribute(null, "saID", "Color");

    //컬럼 속성 변경
    sheet.setAttribute({col:"AMT_12",attr:"CanEdit",val:0});

#### 4) 헤드,풋 추가해 보기

헤더와 데이터 영역 사이나 데이터행 하단에 고정된 행을 설정할 수 있습니다.

    var OPT = {
    	//상단 고정행
    	Head : [
    		{
    			id:"HEAD1",Kind:"Head",CanEdit:0,
    			sa_salary:"",sa_salaryType:"Text",sa_retire:"퇴직자만 보기",sa_retireType:"Text",sa_descType:"Bool",sa_descAlign:"left",sa_descCanEdit:1,
    			sa_descOnChange:function(evt){
    				if(evt.row[evt.col]){
    					evt.sheet.setFilter({name:"myFilter",filter:"sa_retire=='Y'?1:0",render:1});
    				}else{
    					evt.sheet.clearFilter();
    				}
    			}
    		}
    	],
    	//하단 고정행
    	Foot : [
    		{id:"FOOT1",Kind:"Foot",sa_desc:"2019년 자료",CanEdit:0,Color:"#FFDDEE"}
    	]
    }

## 5. 공통 기능 정의 (Def 와 ibsheet-common.js)

#### 1) Def 의 역할

시트 내에 모든 행이나 열에 공통 기능을 설정 할 수 있습니다.
options.Def.Col을 통해 특정 속성을 모든 열에 설정해도, options.Cols를 통해 개별 열에 동일한 속성이 설정된 경우 개별 열에 설정된 값이 우선됩니다.

#### 2) CommonOptions 속성과 onBeforeCreate 함수 사용

시스템 내에 모든 시트에 공통 기능을 설정 할 수 있습니다.
CommonOptions를 통해 설정된 값보다 개별 시트에서 설정한 값이 우선되고, 이보다 onBeforeCreate 함수를 통해 설정된 값이 가장 우선됩니다.
IBSheet.CommonOptions 는 ibsheet-common.js 에 정의되어 있습니다.

#### 3) IB_Preset 과 Extend

열에 설정되는 여러가지 속성을 변수에 담아두었다가, Extend 속성을 동일한 기능을 하는 열을 손쉽게 생성할 수 있습니다.
IB_Preset 변수는 ibsheet-common.js 파일에 정의 되어 있습니다.

## 6. 렌더링 과 데이터 로드

#### 1) 시트 내 값 변경과 렌더링

시트 내에 값을 변경하거나 색상을 변경하는 등 화면에 변화를 일으키는 경우 렌더링 타이밍에 주의하여야 합니다.

    //여러번 렌더링이 일어나는 로직
    var drows = sheet.getDataRows();
    for(var i=0;i<drows.length;i++){
    	sheet.setValue(drows[i], "DWT" , "사용불가");
    	sheet.setAttribute( {row:drows[i],attr:"Color","#FF0000"});
    }

    //단 한번만 렌더링이 일어나는 로직
    var drows = sheet.getDataRows();
    for(var i=0;i<drows.length;i++){
    	//setValue나 setAttribute에 render인자값을 0으로 설정(값의 수정이 있어도 화면에 반영되지 않음)
    	sheet.setValue(drows[i], "DWT" , 0 , 0 );
    	sheet.setAttribute( {"row":drows[i],attr:"Color","#FF0000","render":0});
    }
    //최종 변경된 내용이 화면에 표시됨.
    sheet.rerender();

다양한 렌더링 함수 참고

- 시트 전체 렌더링 : rerender()
- 데이터 영역만 렌더링 : renderBody()
- 특정 행 하나만 렌더링 : refreshRow()
- 특정 셀 하나만 렌더링 : refreshCell()

#### 2) 조회 / 데이터 로드 함수 이용

시트내에 데이터 로딩은 SearchMode 설정에 따라 달라집니다.

유형 | 함수명 | 기능설명
--- | --- | ---
기본 조회 | doSearch | 지정한 URL을 호출하여 리턴된 json을 시트에 로딩합니다.
페이징 조회 | doSearchPaging | 페이징 조회(cfg:{SearchMode:3 or 4}) 사용시 지속적으로 호출할 서버 URL을 설정합니다.
데이터 로드 | loadSearchData | json 데이터(string혹은 object)를 시트에 로딩합니다.

위 함수는 모두 비동기 형식입니다.

#### 3) 관련 이벤트

조회/데이터 로딩 과정에서 다음과 같은 이벤트가 발생합니다. (중간에 렌더링함수는 제외)

순서 | 이벤트명 | 기능설명
--- | --- | ---
1 | onReceiveData | 데이터 파싱 직전에 발생합니다. 로드 될 데이터를 조작할 수 있습니다.
2 | onBeforeDataLoad | json 데이터 파싱 후 발생합니다. 파싱된 json 데이터를 조작할 수 있습니다.
3 | onDataLoad | 화면에 렌더링 전에 발생합니다.
4 | onSearchFinish | 데이터에 대한 렌더링이 끝나고, 모든 조회 절차가 끝난 후에 발생합니다.

#### 4) 데이터 구조

조회/저장 데이터 구조 참고

    //일반적인 조회 데이터 구조
    {"data":[
    	{"colName1":"1234", "colName2":"abcd","colName3":"가나다라"},
    	{"colName1":"1234", "colName2":"abcd","colName3":"가나다라"},
    	....
    ]}

## 7. 데이터 추출과 저장

#### 1) 데이터 추출 함수

다음과 같은 함수를 통해 시트내에 데이터를 추출할 수 있습니다.

함수명 | 기능설명
--- | ---
doSave | 시트에서 변경된 내용을 추출하여 서버로 전송하고, 서버에서 응답 JSON 내용에 따라 시트에 반영합니다.
getSaveString | 시트 내에 수정된 내용을 행단 위로 querystring형식으로 추출하여 리턴합니다.
getSaveJson | 시트 내에 수정된 내용을 행단 위로 json형식으로 추출하여 리턴합니다.

#### 2) 행,셀안에 데이터 수정 정보 확인

- 수정된 행 객체를 얻음
  getRowsByStatus()함수를 수정,삭제,입력 에 따라 필요한 행 객체를 추출할 수 있습니다.

- 수정된 값이 1개라도 존재하는지 여부 확인
  hasChangedData()함수를 통해 true/false로 판별할 수 있습니다.

- 특정 행의 수정여부를 확인

    var row = getRowByIndex(55);
    if(row["Changed"]){
    	//해당 행은 수정된 내용이 있음.
    }
    if(row["Added"]){
    	//신규로 추가된 행임.
    }
    if(row["Deleted"]){
    	//삭제 예정행임
    }

- 특정 셀의 수정여부 및 수정 전 값을 확인

    var row = sheet.getFocusedRow();
    //Name이 AMT인 컬럼의 수정 여부 확인
    if(row["AMTChanged"]){//수정됨.
    	//수정 전 값 확인
    	var oldValue = row["AMTOrgi"];
    }

- 수정한 내용 시트에 반영
  acceptChangedData(), applySaveResult() : 수정된 데이터를 시트에 반영합니다.
  (Deleted속성을 갖고 있는 행은 삭제하고, Added,Changed 속성은 행에서 제거합니다.)

#### 3) 저장 함수 사용

doSave() : 수정된 내용을 지정한 URL로 전송하고, 리턴된 결과에 따라 내용을 반영합니다.
doSave함수는 getSaveString(데이터 취합), ajax(데이터 전송), acceptChangedData(상태 클리어) 함수가 순차적으로 동작합니다.

doSave함수 사용시 리턴 json 형식(참고)

    {
    	"IO":{
    		"Result":1, "Message":"저장되었습니다."
    	}
    }

#### 4) 저장 관련 이벤트

순서 | 이벤트명 | 기능설명
--- | --- | ---
1 | onSave | doSave함수 호출시 발생합니다.
2 | onBeforeSave | doSave함수를 통해 수정한 데이터가 서버로 전송되기 전에 발생합니다.
3 | onAfterSave | 서버에서 저장에 대한 결과를 받은 후 발생합니다.

## 8. formula 기능

#### 1) 합계 행 생성

컬럼 생성시 FormulaRow를 통해 하단에 합계행을 생성할 수 있습니다.
합계행에는 일반적인 컬럼의 합계 값 외에 평균이나 건수 등의 계산값도 표시 할 수 있습니다.

#### 2) 컬럼 간의 연산

컬럼과 컬럼 간의 계산 결과를 표시하기 위한 Formula기능을 제공합니다.
Formula속성이 설정된 컬럼은 사용자의 편집이 불가하고 자동 계산된 값을 표시합니다.
자세한 내용은 appendix의 Formula를 참고해 주세요.

#### 3) 속성에 대한 변경

컬럼의 속성을 변경하는 Attribute+Formula 기능을 제공합니다.

Formula나 Attribute+Formula 기능을 사용하는 경우에는 반드시 CanFormula, CalcOrder 속성이 Def.Row에 설정되어야 합니다.

## 9. solid,contextmenu 기능

#### 1) solid 행 이해

시트 내에 독립적인 기능을 수행하는 행을 추가할 수 있습니다.
appendix에 solid를 참고해 주세요.

#### 2) menu 기능 활용

마우스 우측 버튼 클릭시 표시되는 컨텍스트 메뉴를 설정할 수 있습니다.
appendix에 menu를 참고해 주세요.

## 10. 커스텀 다이얼로 기능 사용

ibsheet-dialog.js 파일을 통해 몇가지 다이얼로그 기능을 사용하실 수 있습니다.
(아래 기능을 사용하기 위해서는 반드시 ibsheet-dialog.js 파일이 해당화면에 include되어 있어야 합니다.)

다이얼로그 | 함수명 | 역할
--- | --- | ---
찾기 | showFindDialog | 시트 내에 조회된 데이터에서 특정 문자를 찾거나, 표시합니다.
상세보기 | showEditDialog(rowObject,width,height) | 특정 행의 내용을 다이얼로그로 표시합니다.
피벗 | showPivotDialog() | 시트의 각 컬럼의 Type에 따라 피벗 다이얼로그를 생성하여 표시합니다.
다운로드 | showDownloadDialog() | 시트에 조회 된 내용 중 사용자가 원하는 행/열을 지정하여 다운로드 할 수 있습니다.
업로드 | showUploadDialog() | 엑셀의 내용을 시트에 로드하기 전에 미리보기 다이얼로그를 통해 사용자가 컬럼의 순서를 정할수 있습니다.
소트 | showSortDialog() | 다이얼로그를 통해 여러개 컬럼을 동시에 소팅 할 수 있습니다.

## 11. 파일 export/import 기능 사용

파일을 export하거나 import 하는 방법은 크게 서버에서 수행하는 방법과 클라이언트에서 수행하는 방법으로 나누어 집니다.

### 서버에서 export/import 하는 방법

서버에서 파일에 대한 import/export 작업을 위해서는 사전 작업이 필요합니다.
엑셀 업로드/다운로드 설정하기 부분을 참고 하시기 바랍니다.

- 엑셀 다운로드/업로드 기능
  down2Excel(), loadExcel() 함수를 통해 데이터 다운로드,업로드를 하실 수 있습니다.

- 텍스트 다운로드/업로드 기능
  down2Text(), loadText() 함수를 통해 데이터 다운로드,업로드를 하실 수 있습니다.

### 클라이언트에서 import/export 하는 방법

javascript를 이용하여 import/export 작업을 위해서는 아래와 같은 작업이 필요합니다.

#### 1) jszip.min.js 파일 추가하기

/plugins/jszip.min.js 파일을 추가 합니다.

#### 2) 다음 함수를 통해 import/export 기능 수행

- 엑셀,text 다운로드 기능
  exportData()
- 엑셀,text 업로드 기능
  importData()

## 12. FAQ

- 시트에 버튼을 추가하거나 혹은 Click이벤트를 통해 layer형태의 팝업을 띄우는 경우, 파업 내에 시트나 input element에서 입력을 해도 계속 파업을 띄운 시트에서 입력이 이루어지는 문제.
  시트를 클릭하여 팝업을 띄우는 경우, 시트는 아직까지 포커스를 자신이 갖고 있다고 판단하기 때문에 발생하는 문제입니다.
  팝업을 띄울때, blur()함수를 호출하여 더 이상 시트가 포커스를 잡지 않게 해야 합니다.

- 조회 직후 시트가 포커스를 가져가지 않게 하는 방법.
  시트는 데이터를 로딩후 첫번째 행,첫번째 열에 포커스를 갖게 됩니다.
  만약 조회 후 포커스를 가져가지 않게 하려면 (cfg)IgnoreFocused 속성을 1로 설정하시면 됩니다.

- 컬럼에 Attribute+Formula 선언하니까 다른 Formula까지 동작하지 않는 문제
  Formula만 사용할때 계산 순서를 결정하는 CalcOrder를 설정하지 않으면 컬럼명의 알파벳 순으로 자동 계산을 합니다. 하지만 Attribute+Formula가 사용되면 Attribute+Formula와 일반 Formula에 대한 연산 순서를 모두 CalcOrder에 정의하여야만 정상 작동하게 됩니다.

- 시트 생성후 조회를 했는데 오류가 나거나 조회가 간헐적으로 안되는 문제
  시트 생성 이전에 조회함수를 호출하여 발생하는 경우가 많습니다. 시트 생성이 비동기 형태이기 때문에 IBSheet.create()함수 호출 이후에 조회 함수를 호출하게되면 이러한 문제가 발생할 수 있습니다.
  문제를 해결하기 위해서는 생성 후 발생 이벤트인 onRenderFirstFinish에서 조회 함수를 호출하여야 합니다.

- 시트를 제거하거나 시트를 다시 생성하는 방법
  화면 내에 모든 시트를 제거하려면 IBSheet.disposeAll()함수를 호출하면 됩니다. 단일 시트를 제거할때는 sheet.dispose()함수를 통해 제거할 수 있습니다.
  이렇게 제거된 함수를 다시 생성하는 것은 일반적인 시트를 생성하는 것과 동일하게 IBSheet.create()함수를 사용하시면 됩니다.

### Read More

- 파일 구성 introduction
- Quick Start getting started
- 시트 객체 기본 구조 getting stated
- 시트 객체 구조 getting stated
- SearchMode cfg
- Extend col
- method 사용법 기초 method
- doSearch method
- doSearchPaging method
- down2Excel method
- down2Text method
- getSaveString method
- getSaveJson method
- getChangedData method
- loadSearchData method
- loadExcel method
- loadText method
- rerender method
- renderBody method
- refreshRow method
- refreshCell method
- showDownloadDialog method
- showEditDialog method
- showFindDialog method
- showPivotDialog method
- showUploadDialog method
- event 사용법 기초 event
- onReceiveData event
- onBeforeDataLoad event
- onDataLoad event
- onSearchFinish event
- onSave event
- onBeforeSave event
- onAfterSave event
- static 객체 란 static
- onBeforeCreate static
- CommonOptions static
- Solid appendix
- Menu appendix

### Since

product | version | desc
--- | --- | ---
core | 8.0.0.0 | 기능 추가