Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
MTSD/design.json에서 DataSource 속성에 DataSource 이름을 지정하면, 보고서 로드 시 자동으로 SQL 실행 후 데이터가 바인딩됩니다.
방식 2: SetDataSet (직접 데이터 주입)
// 서버 스크립트 호출 후 받은 DataSet 주입Matrix.RunScriptEx([], "GetData", params, function(p) {
if (p.Success) {
let ds = p.getDataSet("GRD_MAIN") asDataSet;
grd.SetDataSet(ds);
}
});
방식 3: RefreshData (데이터 갱신)
// DataSource가 설정된 그리드의 데이터를 서버에서 다시 가져옴
grd.RefreshData();
// 현재 선택된 행let currentRow = grd.GetCurrentRow();
// 인덱스로 행 가져오기 (필터링 후 보이는 행 기준)let row = grd.GetRow(0);
// 인덱스로 행 가져오기 (전체 데이터 기준, 필터 무관)let rowInTotal = grd.GetRowInTotalRows(0);
// 행 수 조회let visibleCount = grd.GetRowCount();
let totalCount = grd.GetTotalRowCount();
// 선택된 행들let selectedRows = grd.GetSelectedRows();
3.3 셀 값 읽기/쓰기
// Row 객체에서 직접 접근 (권장)let value = row.GetValue("FIELD_NAME");
row.SetValue("FIELD_NAME", "new value");
// Cell 객체를 통한 접근let cell = row.GetCell("FIELD_NAME");
let cellValue = cell.Value; // 원본 값let displayText = cell.Text; // 표시 텍스트 (readonly)let displayValue = cell.DisplayValue; // 서식 적용된 표시값 (readonly)// Grid 메서드로 접근let val = grd.getRowValue(0, "FIELD_NAME"); // 인덱스 + 필드명
grd.setRowValue(0, "FIELD_NAME", "new value"); // 인덱스 + 필드명
3.4 행 상태(RowState) 관리
CRUD에서 행의 변경 상태를 추적합니다:
상태
값
설명
None
0
변경 없음 (서버에 전송 안 됨)
Added
1
새로 추가된 행 (INSERT)
Updated
2
수정된 행 (UPDATE)
Deleted
4
삭제된 행 (DELETE)
// 행 상태 조회let status = grd.GetRowStatus(0); // "None", "Insert", "Update", "Delete"// 행 상태 수동 변경
grd.ChangeRowStateAt(0, "Update");
// 수정 여부 확인let modified = grd.IsModified(); // 변경된 행이 있으면 true
4. 컬럼(Column) 설정
4.1 컬럼 속성
import { DataGridColumn } from"@AUD_CLIENT/control/grids/DataGridColumn";
let col = grd.GetField("EMP_NAME") asDataGridColumn;
// 기본 속성
col.Caption = "사원명"; // 헤더 표시명
col.Width = 150; // 너비(px)
col.Visible = true; // 표시 여부
col.Editable = true; // 편집 가능 여부
col.Sortable = true; // 정렬 가능 여부
col.Filterable = true; // 필터 가능 여부
col.Resizable = true; // 리사이즈 가능 여부
col.Mergeable = true; // 병합 가능 여부// 정렬
col.TextPosition = "center"; // "start" | "center" | "end"
col.HeaderPosition = "center"; // 헤더 정렬
col.VerticalAlign = enPropFontAlignV.Middle; // 세로 정렬// 데이터 타입
col.DataType = enDataType.String; // String, Int, Float, Double, DateTime 등
col.Format = "#,##0"; // 숫자 서식
col.Format = "yyyy-MM-dd"; // 날짜 서식
col.InitValue = ""; // 새 행 추가 시 기본값
4.2 컬럼 타입(ColumnType)
컬럼의 UI 표현 방식을 결정합니다:
ColumnType
설명
주요 속성
Text
일반 텍스트 (기본)
Format
ComboBox
드롭다운 선택
DefinedItems, DataSource, ValuePath, LabelPath
CheckBox
체크박스
CheckedValue, UnCheckedValue
RadioButton
라디오 버튼
DefinedItems
Button
버튼
Caption
Image
이미지
-
DateTime/Calendar
날짜 선택
Format
MultiLine
여러 줄 텍스트
-
Password
비밀번호
-
ComboBox 컬럼 설정
// 방법 1: DefinedItems (고정 목록)
col.ColumnType = enDataColumnType.ComboBox;
col.DefinedItems = "Y:사용,N:미사용"; // value:label 형식// 방법 2: DataSource 연동 (동적 목록)// MTSD에서 컬럼의 ComboBox DataSource를 설정// ValuePath: 코드 필드, LabelPath: 표시 필드
CheckBox 컬럼 설정
col.ColumnType = enDataColumnType.CheckBox;
col.CheckedValue = "Y";
col.UnCheckedValue = "N";
// IsCheckBoxAllSelected: 헤더 체크박스 전체 선택 상태
4.3 컬럼 스타일
// BoxStyle 적용 (공통 스타일)
col.SetBoxStyle("STYLE_CODE"); // 데이터 영역
col.SetHeaderBoxStyle("HEADER_STYLE"); // 헤더 영역
col.ClearBoxStyle(); // 스타일 제거// 너비 설정
col.SetWidth(200);
let actualWidth = col.GetActualWidth();
4.4 컬럼 동적 추가/삭제
// 컬럼 추가
grd.AddColumn("NEW_COL", false); // false=문자, true=숫자// 컬럼 삭제
grd.DeleteColumn("NEW_COL");
// 컬럼 이동
grd.MoveField("COL_NAME", 3); // 3번째 위치로 이동// 필드 정보 조회let fields = grd.GetFields(); // 모든 컬럼 배열let fieldNames = grd.GetFieldNames(); // 필드명 배열let colCount = grd.GetColumnCount(); // 컬럼 수let fieldIdx = grd.GetFieldIndex("COL_NAME"); // 필드 인덱스
4.5 CRUD용 컬럼 키 속성
서버로 데이터를 전송하여 자동 DML 생성할 때 사용됩니다:
속성
값
설명
KeyType
Primary
WHERE 절에 사용 (PK 컬럼)
KeyType
None
일반 데이터 컬럼
DataType
String/Numeric/DateTime/DateTimeNow/UserCode/UUID
서버 DML 생성 시 타입 처리
SaveMode
All
INSERT/UPDATE 모두 포함
SaveMode
InsertOnly
INSERT에만 포함
SaveMode
UpdateOnly
UPDATE에만 포함
SaveMode
None
DML에서 제외
5. 이벤트
5.1 셀/행 이벤트
// 셀 클릭
grd.OnCellClick = function(sender, args) {
// args: { Id, Row: DataGridRow, Cell: DataGridCell, X, Y }let value = args.Row.GetValue("FIELD_NAME");
let cellText = args.Cell.Text;
};
// 셀 더블클릭
grd.OnCellDoubleClick = function(sender, args) {
// args: { Id, Row, Cell, X, Y }
};
// 현재 셀 변경
grd.OnCurrentCellChanged = function(sender, args) {
// args: { Id }
};
// 현재 행 변경
grd.OnCurrentRowChanged = function(sender, args) {
// args: { Id }
};
// 셀 렌더링 전 (조건부 서식)
grd.OnCellLoaded = function(sender, args) {
// args: { Id, Row, Cell }// 셀이 화면에 그려지기 직전에 호출 — 셀 색상/폰트를 동적으로 변경if (args.Cell.Column.Name === "STATUS" && args.Cell.Value === "FAIL") {
args.Cell.BackColor = "#FFCCCC";
args.Cell.FontColor = "#FF0000";
args.Cell.FontBold = true;
}
};
5.2 편집 이벤트
// 편집 시작 전
grd.OnCellBeginEdit = function(sender, args) {
// args: { Id, Cell, Cancel, MergeColumn, LOVList }// Cancel = true로 설정하면 편집 취소if (args.Cell.Column.Name === "READONLY_COL") {
args.Cancel = true; // 특정 컬럼 편집 방지
}
};
// 편집 완료 후
grd.OnCellEndEdit = function(sender, args) {
// args: { Id, getCells(), Cancel }let cells = args.getCells(); // 편집된 셀 목록// Cancel = true로 설정하면 편집 내용 취소
};
// 새 행 생성 시
grd.OnRowAppended = function(sender, args) {
// args: { Id, Row }
args.Row.SetValue("CREATE_DATE", newDate().toISOString().slice(0, 10));
};
5.3 데이터 이벤트
// 데이터 바인딩 완료
grd.OnDataBindEnd = function(sender, args) {
// args: { Id, RecordCount }// 데이터 로딩 후 초기 처리
};
// 데이터 변경 (ApplyDataSource, SetDataSet, Calculate 후)
grd.OnDataChanged = function(sender, args) {
// args: { Id, RecordCount, Source }// Source: "ApplyDataSource" | "SetDataSet" | "Calculate"
};
// 차원 필터 (Dimension) — 특정 값 포함/제외
grd.setDimensionFilterIn("DEPT_CODE", ["D001", "D002"]); // 포함
grd.setDimensionFilterNotIn("STATUS", ["CLOSED"]); // 제외
grd.setDimensionFilterBetween("DATE", "2024-01-01", "2024-12-31"); // 범위// 측정값 필터 (Measure) — 숫자 조건
grd.setMeasureFilter("AMOUNT", ">=", 10000);
// 컬럼 단위 필터let col = grd.GetField("STATUS") asDataGridColumn;
col.AddFilter(0, "In", ["ACTIVE", "PENDING"], true); // type:0=Dimension, isAnd:true// 필터 해제
col.ClearFilter();
grd.ClearFilter(); // 모든 필터 해제
grd.ClearFilters(["DEPT_CODE", "STATUS"]); // 특정 필드만 해제
6.2 정렬
// 정렬 추가
grd.AddSort("DEPT_CODE", "ASC");
grd.AddSort("EMP_NAME", "DESC", true); // 세 번째 인수 true: 화면 갱신 안 함// 정렬 표현식으로 실행
grd.ExecuteSort("DEPT_CODE ASC, AMOUNT DESC");
// 정렬 해제
grd.ClearSort();
7. 셀 선택(Selection) / 고정 컬럼(Freeze) / 병합(Merge)
7.1 선택
// 선택 규칙 (MTSD/design.json에서 설정)// SelectRule: SingleRow, MultiRow, SingleRange, SingleCell// 특정 셀 선택
grd.SelectCell(0, "EMP_NAME");
// 특정 행 선택
grd.SelectRow(0);
grd.SelectRowRange(0, 5); // 범위 선택// 선택 해제
grd.ClearSelect();
// 현재 선택 정보let currentCell = grd.GetCurrentCell();
let selectedCells = grd.GetSelectedCells();
let selectedRows = grd.GetSelectedRows();
7.2 고정 컬럼 (Freeze)
import { FreezeColumnSetting } from"@AUD_CLIENT/control/grids/FreezeColumnSetting";
// FreezeColumn 설정 (MTSD/design.json에서 주로 설정)// FreezeColumn: { Left: 2, Right: 0, Type: 0 }// → 왼쪽 2개 컬럼 고정
7.3 셀 병합 (Merge)
// MergeRule 설정 (MTSD/design.json에서 주로 설정)// MergeRule: 0=None, 1=Vertical, 2=VerticalHierarchy// Vertical: 같은 컬럼에서 연속된 동일 값 셀을 병합// VerticalHierarchy: 부모 그룹 범위 내에서만 병합// 개별 컬럼의 병합 가능 여부let col = grd.GetField("DEPT_CODE") asDataGridColumn;
col.Mergeable = true; // 이 컬럼 병합 허용
col.FieldForMerge = "DEPT_CODE"; // 병합 기준 필드 (다른 필드의 값으로 병합 판단)
// 사용 예
grd.Calculate(); // 행 추가/삭제 후
grd.Update(); // 셀 스타일 변경 후
grd.RefreshData(); // 서버에서 데이터 다시 가져오기
grd.SetAutoFit(null, true); // 모든 컬럼 자동 맞춤 (헤더 포함)
10. 셀 스타일 (조건부 서식)
Canvas 기반이므로 CSS가 아닌 셀 프로퍼티로 스타일을 지정합니다. OnCellLoaded 이벤트에서 동적으로 적용합니다.
cell.BackColor — 배경색 ("#RRGGBB" 또는 "rgba(r,g,b,a)")
cell.FontColor — 글자색
cell.FontBold — 굵게 (boolean)
cell.FontItalic — 기울임 (boolean)
11. DataGrid 전용: 페이징
// 페이징 활성화 (MTSD/design.json에서 설정 또는 스크립트에서 설정)
grd.UsePaging = true;
grd.PageSize = 20;
// 페이지 이동
grd.MoveNextPage();
grd.MovePrevPage();
grd.MovePage(3); // 특정 페이지로 이동// 현재 페이지 정보let pageIdx = grd.PageIndex; // 현재 페이지 (0-based)let lastPage = grd.GetLastPageIndex();
let totalRows = grd.GetTotalPageRowCount();
12. GroupGrid 전용: 그룹핑 + 소계
GroupGrid는 DataGrid를 상속하며, 특정 필드 기준으로 데이터를 그룹핑하고 소계/합계 행을 자동 생성합니다.
import { DataGrid } from"@AUD_CLIENT/control/DataGrid";
let grd = Matrix.getObject("GRD_GROUP") asDataGrid; // GroupGrid는 DataGrid 타입 사용// 그룹핑 실행 (필드명 배열)
grd.GroupGrid(["DEPT_CODE"]); // 1단계 그룹
grd.GroupGrid(["DEPT_CODE", "TEAM"]); // 2단계 그룹 (부서 > 팀)// 그룹핑 후 데이터가 재배열되고 SubTotal/GrandTotal 행이 자동 삽입됨
소계 집계 함수 설정
컬럼별로 소계 행에 표시할 집계 함수를 지정합니다 (MTSD/design.json에서 설정):
CalcSubTotalType
설명
Sum
합계
Average
평균
Count
건수
Min
최소값
Max
최대값
None
표시 안 함
GroupGrid 이벤트
// 그룹 데이터 바인딩 완료
grd.OnGroupDataBindEnd = function(sender, args) {
// 그룹핑 처리 완료 후 호출
};
import { TreeGrid } from"@AUD_CLIENT/control/TreeGrid";
import { TreeGridNode } from"@AUD_CLIENT/control/grids/TreeGridNode";
let tree = Matrix.getObject("TRG_ORG") asTreeGrid;
13.1 트리 설정 (TreeSetting)
MTSD/design.json에서 TreeInfo를 설정합니다:
{"TreeInfo":{"ParentField":"PARENT_CODE",// 부모 키 필드"ChildField":"CODE",// 자식 키 필드"CheckField":"",// 체크박스 필드 (선택)"ImageField":""// 아이콘 필드 (선택)}}
데이터 예시:
CODE
PARENT_CODE
NAME
ROOT
최상위
D001
ROOT
개발부
D002
ROOT
영업부
T001
D001
웹팀
T002
D001
앱팀
13.2 트리 조작
// 펼치기/접기
tree.ExpandAll();
tree.CollapseAll();
tree.ExpandToLevel(2); // 2단계까지만 펼치기// 체크 관련 (TreeInfo.CheckField가 설정된 경우)let checkedRows = tree.GetCheckedRows(); // 체크된 노드 배열
tree.ClearCheckedRows(); // 전체 체크 해제// 노드 접근let node = tree.GetRow(0) asTreeGridNode;
let parentNode = node.ParentNode;
let children = node.GetChildNodeList();
let childCount = node.GetChildNodeCount();
let level = node.Level; // 깊이 (0부터)let isExpanded = node.IsExpand;
// 노드 값 접근let nodeValue = node.GetValue("CODE");
node.SetValue("NAME", "변경된 이름");
13.3 트리 이벤트
// 트리 셀 클릭 (Area로 클릭 위치 구분)
tree.OnTreeCellClick = function(sender, args) {
// args: { Id, Row: TreeGridNode, Cell, Area }// Area: 확장/축소 버튼, 트리 아이콘, 셀 영역 구분
};
// 일반 셀 클릭도 동일하게 사용 가능
tree.OnCellClick = function(sender, args) {
let node = args.RowasTreeGridNode;
let level = node.Level;
};
14. CRUD: 서버로 데이터 전송
14.1 자동 CRUD (DMLType 설정)
그리드에 CRUD 관련 속성을 설정하면, 서버에서 자동으로 INSERT/UPDATE/DELETE SQL을 생성합니다.
필수 설정:
CRUDTableName: 대상 테이블명 (MTSD에서 설정)
컬럼 KeyType: Primary 키 컬럼 지정
컬럼 DataType: 서버 DML 생성 시 타입 매핑
컬럼 SaveMode: DML에 포함할 범위
14.2 데이터 전송 흐름
[클라이언트] [서버]
1. 사용자가 그리드에서 데이터 수정
2. 행 추가(AppendRow), 수정(SetValue),
삭제(DeleteRow) → RowState 자동 추적
3. Matrix.RunScriptEx(["GRD"], "Save", 4. Packet.parsePacket()
params, callback) → DataTable으로 역직렬화
→ 내부적으로 GetCRUDJSON() 호출
→ MafPacket 형식으로 전송 5. QueryGenerator.getDMLCommand()
→ RowState별 INSERT/UPDATE/DELETE 자동 생성
6. SQL 실행
14.3 GetCRUDJSON 데이터 구조
GetCRUDJSON()은 그리드의 변경된 데이터를 서버 전송용 JSON으로 직렬화합니다:
DataType.DateTimeNow → 서버 날짜 함수 (Oracle: SYSDATE, MSSQL: GETDATE())
DataType.UserCode → 로그인 사용자 코드 자동 삽입
DataType.UUID → 고유 키 자동 생성
UPDATE (RowState = 2, Updated)
UPDATE TB_EMP
SET EMP_NAME ='수정됨', AMOUNT =70000, UPDATE_DATE = GETDATE()
WHERE EMP_CODE ='E004'
SaveMode.InsertOnly 컬럼은 제외
KeyType.Primary 컬럼이 WHERE 조건 (원래 값 사용)
DELETE (RowState = 4, Deleted)
DELETEFROM TB_EMP WHERE EMP_CODE ='E006'
KeyType.Primary 컬럼만 WHERE 조건에 사용
MERGE (Oracle/MSSQL 지원)
-- OracleMERGEINTO TB_EMP T
USING DUAL ON (T.EMP_CODE ='E001')
WHEN MATCHED THENUPDATESET EMP_NAME ='홍길동'WHENNOT MATCHED THENINSERT (EMP_CODE, EMP_NAME) VALUES ('E001', '홍길동')
-- MSSQLMERGE TB_EMP AS TT
USING (SELECT'E001'AS EMP_CODE) AS ST ON TT.EMP_CODE = ST.EMP_CODE
WHEN MATCHED THENUPDATESET EMP_NAME ='홍길동'WHENNOT MATCHED BY TARGET THENINSERT (EMP_CODE, EMP_NAME) VALUES ('E001', '홍길동');
let col = grd.GetField("INTERNAL_CODE") asDataGridColumn;
col.UseExport = false; // 내보내기에서 제외
17. 유효성 검증 (Validation)
// 전체 유효성 검사let isValid = grd.ValidateEx(); // 기본 검증let isValid2 = grd.ValidateEx(false); // 모든 행 검증 (삭제행 포함)let isValid3 = grd.ValidateEx(false, true); // InputSetting 검증 포함// 유효성 검증 이벤트
grd.OnCellValidatorMessage = function(sender, args) {
// args: { Id, Cell, Validator, Type, Title, Message, Cancel }// Cancel = true로 설정하면 기본 알림 표시 안 함// 커스텀 메시지 표시 가능
};
18. 실전 예제
18.1 기본 CRUD 화면
import { Matrix } from"@AUD_CLIENT/control/Matrix";
import { Button } from"@AUD_CLIENT/control/Button";
import { DataGrid } from"@AUD_CLIENT/control/DataGrid";
import { DataGridRow } from"@AUD_CLIENT/control/grids/DataGridRow";
import { DataGridCell } from"@AUD_CLIENT/control/grids/DataGridCell";
letMatrix: Matrix;
let grd = Matrix.getObject("GRD_MAIN") asDataGrid;
let btnSearch = Matrix.getObject("btnSearch") asButton;
let btnAdd = Matrix.getObject("btnAdd") asButton;
let btnDelete = Matrix.getObject("btnDelete") asButton;
let btnSave = Matrix.getObject("btnSave") asButton;
// 조회
btnSearch.OnClick = function(sender, args) {
grd.RefreshData();
};
// 행 추가
btnAdd.OnClick = function(sender, args) {
let newRow = grd.AppendRow();
newRow.SetValue("STATUS", "NEW");
grd.Calculate();
};
// 행 삭제
btnDelete.OnClick = function(sender, args) {
let currentRow = grd.GetCurrentRow();
if (currentRow == null) {
Matrix.Alert("삭제할 행을 선택하세요.");
return;
}
let rowIdx = currentRow.RowIndex;
grd.DeleteRow(rowIdx);
grd.Calculate();
};
// 저장
btnSave.OnClick = function(sender, args) {
if (!grd.IsModified()) {
Matrix.Alert("변경된 데이터가 없습니다.");
return;
}
if (!grd.ValidateEx()) return;
Matrix.RunScriptEx(["GRD_MAIN"], "SaveData", {}, function(p) {
if (p.Success) {
Matrix.Alert("저장 완료");
grd.RefreshData();
}
});
};
// 조건부 서식
grd.OnCellLoaded = function(sender, args) {
if (args.Cell.Column.Name === "AMOUNT") {
let val = Number(args.Cell.Value);
if (val < 0) {
args.Cell.FontColor = "#FF0000";
}
}
};
// 데이터 바인딩 완료 후 처리
grd.OnDataBindEnd = function(sender, args) {
// 총 건수 표시 등
};
18.2 마스터-디테일 (그리드 2개 연동)
let grdMaster = Matrix.getObject("GRD_MASTER") asDataGrid;
let grdDetail = Matrix.getObject("GRD_DETAIL") asDataGrid;
// 마스터 행 선택 시 디테일 데이터 로드
grdMaster.OnCurrentRowChanged = function(sender, args) {
let currentRow = grdMaster.GetCurrentRow();
if (currentRow == null) return;
let masterCode = currentRow.GetValue("MASTER_CODE");
// 방법 1: 파라미터로 디테일 DataSource 실행Matrix.SetVariableValue("VS_MASTER_CODE", masterCode);
grdDetail.RefreshData();
// 방법 2: 서버 스크립트 호출// Matrix.RunScriptEx(["GRD_DETAIL"], "GetDetail",// { VS_MASTER_CODE: masterCode }, function(p) { ... });
};
18.3 TreeGrid 조직도
let tree = Matrix.getObject("TRG_ORG") asTreeGrid;
// 데이터 로드 후 2단계까지 펼치기
tree.OnDataBindEnd = function(sender, args) {
tree.ExpandToLevel(2);
};
// 체크된 노드 가져오기const getCheckedNodes = function() {
let checkedRows = tree.GetCheckedRows();
letcodes: string[] = [];
for (let i = 0; i < checkedRows.length; i++) {
codes.push(checkedRows[i].GetValue("CODE") asstring);
}
return codes;
};
// 트리 노드 클릭
tree.OnCellClick = function(sender, args) {
let node = args.RowasTreeGridNode;
let level = node.Level;
let hasChildren = node.GetChildNodeCount() > 0;
};
19. 샘플 보고서 위치
실제 구현 예제는 아래 폴더에서 확인할 수 있습니다:
카테고리
경로
DataGrid 샘플
src/reports/samples/기능별 샘플/DataGrid/
TreeGrid 샘플
src/reports/samples/기능별 샘플/TreeGrid/
판매관리 CRUD 예제
src/reports/samples/판매관리 시스템/
20. 서버 데이터 전송 상세 (MafPacket)
클라이언트 → 서버 패킷 구조
Matrix.RunScriptEx(["GRD_MAIN"], "ServiceName", params, callback) 호출 시 내부적으로 Document.GetDataSetMafPacket()이 호출되어 아래 JSON 구조가 생성됩니다:
let newRow = grd.AppendRow();
grd.Calculate();
grd.SelectCell(newRow.RowIndex, "EMP_NAME");
// 자동으로 편집 모드 진입됨
Q: 그리드 데이터를 DataTable로 접근하려면?
let dt = grd.GetDataTable(0) asDataTable; // 0: 기본 데이터let rowCount = dt.Rows.length;
for (let i = 0; i < rowCount; i++) {
let val = dt.Rows[i].GetValue("FIELD");
}
Q: 그리드 높이를 데이터 건수에 맞추려면?
해당 기능은 그리드 자체에서 지원하지 않습니다. 그리드의 Position.Height를 직접 계산하여 설정합니다.
Q: 여러 그리드의 CRUD를 한 번에 저장하려면?
// RunScriptEx 첫 번째 인수에 여러 그리드 이름 전달Matrix.RunScriptEx(
["GRD_MASTER", "GRD_DETAIL"], // 두 그리드의 CRUD 데이터 모두 전송"SaveAll",
{},
function(p) { ... }
);
Q: ComboBox 컬럼의 표시값이 코드로 나올 때?
ComboBox 컬럼의 ValuePath(코드)와 LabelPath(표시명)가 올바르게 설정되었는지 확인합니다. DefinedItems를 사용할 경우 "코드:표시명" 형식이 맞는지 확인합니다.