일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 중복제거
- declare
- MSSQL
- GIT
- 백준
- pythonanywhere
- Visual Studio
- c#
- anaconda3
- blog
- Delphi
- PyCharm
- pyhcarm
- delphi 10.3
- queryset
- Push
- dbadvgrid
- rank
- github
- 델파이
- COMMIT
- advColumnGrid
- templates
- python 3.7
- HTML
- python3
- Django
- hackerrank
- get_object_or_404
- TMS
- Today
- Total
DevHyun
Delphi에서 FastReport 핸들링 하기! 본문
*작업환경
- Delphi 10.3
- MSSQL
- FastReport 6.0
*사용 컴포넌트
- frxReport
- frxDBDataset
- AdoQuery
- AdoTable
- DataSource
- AdoConnection
: 위 컴포넌트들을 동적으로 생성해도 상관없음!
예시 ) 개발팀 팀원별 2020년 잔여 연차 리스트 뽑아보자!
1. 필요한 데이터 확인
- 잔여 연차 소모 독려를 위하여 개발팀 팀원들의 2020년 잔여 연차리스트가 필요
: 사원별 잔여 연차 리스트 테이블, 사원 정보 테이블(편의상 정규화 X)
- 각 사원들은 고유한 사번이 존재
[사원 정보] - Master
사번 | 직책 | 이름 |
1234 | 팀장 | 김팀장 |
5678 | 과장 | 송과장 |
91011 | 대리 | 박대리 |
[사원별 잔여 연차 리스트] - Detail
사번 | 사용연차 | 잔여 연차 |
1234 | 17 | 0 |
5678 | 12 | 3 |
91011 | 9 | 4 |
2. DB 셋팅
- ADOConnection setting
: ConnectionString 설정 후 LoginPrompt 체크 해제
- AdoQuery, AdoTable Connection Setting
- AdoQuery에 SQL문 입력
: 1이 MASTER, 2가 DETAIL로 사용될 예정
: FIELD EDITOR 에서 ADD ALL FIELD
- DATASOURCE 지정
: DATASOURCE1 = AdoQuery1
: DATASOURCE2 = AdoTable1
- AdoTable1(DETAIL)의 property - mastersource를 DATASOURCE1(MASTER)로 지정
: MASTER FIELDS 선택
: 여기서 매칭할 컬럼(사원번호)를 각각 선택 후 ADD -> OK
- FrxDBDataset1 은 DataSource1(MAIN) , FrxDBDataset2 는 DataSource2(Detail) datasource로 지정
** 중간점검!
- AdoConnection Setting
- AdoQuery1 : Main( SAWON 테이블 조회 쿼리)
- AdoQuery2 : Detail( HOLIDAY 테이블 조회 쿼리)
- AdoTable1 : TABLE NAME = HOLIDAY
: MASTER SOURCE = DATASOURCE1
: MASTERFIELDS = SNUM
: INDEXFIELDNAME = SNUM
- DataSource1 : Dataset = AdoQuery1
- DataSource2 : Dataset = AdoTable2 = HOLIDAY 테이블
- FrxDBDataset1 : Dataset = DataSource1
- FrxDBDataset2 : Dataset = DataSource2
**
- FrxReport 편집화면 진입
: Report -> Data
: FrxDBDataset 1, FrxDBDataset2 둘다 선택
- Data Tree에서 확인
: Data Tree 탭이 안보일 경우 View -> ToolBars -> DataTree 클릭
- Master Data Section과 Detail Data Section 추가
- 사용할 Dataset 선택
- Report 화면 꾸미기
: Header는 한번만 출력
: 표현할 데이터는 DataTree에서 컬럼 별로 끌어와서 report 화면에 추가 가능(Drag & Drop)
: Master Data 는 Master Data 수 만큼 출력
: Detail Data는 Master Data와 연관된 Datail 수 만큼 출력
- 출력
- 끝
* frxReport와 frxDbDataset AdoQuery AdoTable Datasource는 생성만 해 두고
사용은 pas 파일(delphi source file)에서 동적으로 할 수 있게 변경 해볼 예정!
- pas파일에서 코딩해보기!
- adocennection constring setting과 report 꾸미기 작업은 수동으로 진행하였으므로 생략!
procedure TForm3.Button1Click(Sender: TObject);
var
sql :string;
begin
// 쿼리 컴포넌트와 커넥션 연결
adoquery1.Connection := ADOConnection1;
adoquery2.Connection := ADOConnection1;
// 쿼리 컴포넌트 open
sql := ' SELECT * FROM TEST..SAWON ';
adoquery1.SQL.Text := sql;
adoquery1.open;
// adoquery2 컴포넌트는 사실 필요 없어보이지만 추후에
Holiday 테이블과 다른 테이블을 조인하여 SELECT 한 뒤에 임시 테이블로 생성하는 용도로 쓸 예정
임시테이블로 생성한 뒤에 AdoTable 컴포넌트에서 사용할 예정.
sql := ' SELECT * FROM TEST..HOLIDAY ';
adoquery2.SQL.Text := sql;
adoquery2.open;
// datasource 셋팅
datasource1.DataSet := ADOQuery1;
// ado table 셋팅
ADOTable1.Connection := ADOConnection1;
ADOTable1.TableName := 'HOLIDAY';
datasource2.DataSet := ADOTable1;
ADOTable1.MasterSource := DataSource1;
adotable1.MasterFields := 'SNUM';
adotable1.IndexFieldNames := 'SNUM';
// frxDBDataSet 셋팅
frxDBDataset1.DataSet := ADOQuery1;
frxDBDataset2.DataSet := ADOTable1;
// 리포트 출력!
frxReport1.PrintOptions.ShowDialog := False; //출력 시 진행 묻는 부분 없애기
frxReport1.ShowProgress := False; //출력 시 진행 프로그래스바 없애기
frxReport1.PrintOptions.Printer := 'FinePrint';
frxReport1.PrepareReport;
frxReport1.Print;
end;
** 최종 **
- fastreport와 frxdbdataset은 공용모듈 폼에 생성했음.
- fasreport 셋팅은 미리 한 상태.
- FrxReport 편집화면 진입
: Report -> Data
: FrxDBDataset 1, FrxDBDataset2 둘다 선택
- Data Tree에서 확인
: Data Tree 탭이 안보일 경우 View -> ToolBars -> DataTree 클릭
- Master Data Section과 Detail Data Section 추가
- 사용할 Dataset 선택
- Report 화면 꾸미기
: Header는 한번만 출력
: 표현할 데이터는 DataTree에서 컬럼 별로 끌어와서 report 화면에 추가 가능(Drag & Drop)
: Master Data 는 Master Data 수 만큼 출력
: Detail Data는 Master Data와 연관된 Datail 수 만큼 출력
- 아래는 공용모듈에 함수로 생성한 코드
: 조금 다를순 있음..흐름만 참고 하시길 ㅎㅎ
procedure Print(sql, sql2: string;);
var
AdoConnection1 : TAdoconnection;
Query1, Query2 : TAdoQuery;
Table : TAdoTable;
DS1,DS2 : TDataSource;
sql3 : string;
begin
// 커넥션 동적 생성 및 셋팅
AdoConnection1 := TAdoConnection.Create(nil);
AdoConnection1 := '커넥션 정보';
AdoConnection1.LoginPrompt := false;
// 쿼리컴포넌트 동적 생성 및 셋팅
Query1 := TADOQuery.Create(nil);
With Query1 do
begin
CommandTimeout := 0;//10000;
CursorLocation := clUseClient;
CursorType := ctKeySet;
LockType := ltOptimistic;
MarshalOptions := moMarshalAll;
ParamCheck := False;
Prepared := True;
end;
Query1.Connection := AdoConnection1;
Query2 := TADOQuery.Create(nil);
With Query2 do
begin
CommandTimeout := 0;//10000;
CursorLocation := clUseClient;
CursorType := ctKeySet;
LockType := ltOptimistic;
MarshalOptions := moMarshalAll;
ParamCheck := False;
Prepared := True;
end;
Query2.Connection := AdoConnection1;
// table 컴포넌트 생성(임시 테이블 생성 후 데이터 참조 용)
Table := TADOTable.Create(nil);
// 데이터셋 컴포넌트 생성 및 셋팅
DS1 := TDataSource.Create(nil);
DS2 := TDataSource.Create(nil);
// 출력 부분을 공용모듈에서 함수로 만들었기 때문에 masetr sql문은 파라미터로 받아옴
// master 테이블 select
adoquery1.SQL.Text := sql;
adoquery1.open; // Master
// temp 테이블 생성 전 확인
sql3 := ' IF EXISTS(SELECT * FROM TEST SYSOBJECTS WHERE name = ''TEMP'') '
+ ' DROP TABLE TEST..TEMP ';
adoquery2.SQL.Text := sql3;
adoquery2.ExecSQL; // Master
// temp 테이블 생성
sql2 := ' SELECT * INTO TEST..TEMP FROM (SELECT * FROM TEST..HOLIDAY AS A LEFT JOIN TEST..SAWON AS B ON A.SNUM = B.SNUM) AS A ';
adoquery2.SQL.Text := sql2;
adoquery2.ExecSQL;
// temp 테이블 select
sql3 := ' SELECT * FROM TEST..TEMP ';
adoquery2.SQL.Text := sql3;
adoquery2.ExecSQL; // Detail
// 데이터셋 컴포넌트 셋팅 및 table 컴포넌트 셋팅
ds1.DataSet := Query1;
table.Connection := ADOConnection1;
table.TableName := 'TEMP';
ds2.DataSet := table;
// 참조할 키 설정(연결 키)
table.MasterSource := ds1;
table.MasterFields := 'SNUM';
table.IndexFieldNames := 'SNUM';
// 변동 사항 있을 수도 있으니 한번 active 시켜줌
// 컬럼이 변동되었을 경우 active를 해주면 fastrport dbdatset refresh 되는듯?
table.Active:= True;
// frxdbdataset은 공용모듈에 컴포넌트로 올려두었음(동적 생성해도 될듯?)
frxdbdataset1.DataSet := Query1;
frxdbdataset2.DataSet := table;
// fastreport
// master,detail dataset 설정
TfrxDBDataset(frxReport1.FindObject('MasterData1')).DataSet := frxDBDataset1.DataSet;
TfrxDBDataset(frxReport1.FindObject('DetailData1')).DataSet := frxDBDataset2.DataSet;
// MASTER
TfrxMemoView(frxReport1.FindObject('오브젝트 명')).DataSet := frxDBDataset1;
TfrxMemoView(frxReport1.FindObject('오브젝트 명')).DataField := '필드명';
//DETAIL
TfrxMemoView(frxReport1.FindObject('오브젝트 명')).DataSet := frxDBDataset2;
TfrxMemoView(frxReport1.FindObject('오브젝트 명')).DataField := '필드명';
// 출력
frxReport1.PrintOptions.ShowDialog := False; //출력 시 진행 묻는 부분 없애기
frxReport1.ShowProgress := False; //출력 시 진행 프로그래스바 없애기
frxReport1.PrintOptions.Printer := '프린트명';
frxReport1.PrepareReport;
frxReport1.Print;
// temp 테이블 삭제
sql2 := 'DROP TABLE TEST..TEMP';
adoquery1.SQL.Text := sql2;
adoquery1.ExecSQL;
// 동적으로 생성했던 컴포넌트 free
Query1.Free;
Query2.Free;
Table.Free;
DS1.Free;
DS2.Free;
end;
'Delphi' 카테고리의 다른 글
[TMS AdvColumnGrid] 그리드 내에서 검색하기 (0) | 2021.06.03 |
---|---|
[TMS AdvColumnGrid] header 클릭 시 금액순으로 정렬하기 (0) | 2021.04.27 |
TWebbrowser 컴포넌트 핸들링하기! (0) | 2020.12.11 |
tms 그리드에서 그리드 내의 숫자 format 변경하기 (0) | 2020.11.16 |
txt 파일을 이용하여 log 찍기 (0) | 2020.10.29 |