기술탐구

라자루스로 만들어 보는 비밀번호 관리 프로그램 [뭐였더라] (5) 엑셀파일 출력 II

appleii 2021. 8. 23. 16:48

데이터베이스를 엑셀 파일로 출력하는 것에 성공했지만, 마음에 들지 않는 점이 있다. 실행화면에 표시되는 DBGrid 의 데이터와 일치하지 않는 것이다.

[ DBGrid 에서의 필드이름 ]
[ 엑셀파일에서의 필드이름 ]


데이터베이스와 DBGrid 에 표시되는 데이터에는 차이가 있다. 데이터베이스에는 PK 필드가 있지만 DBGrid 에는 표시되지 않는다. 그리고 데이터베이스의 필드이름은 영어로 표시되어 있지만 , DBGrid 의 필드에는 별도의 캡션이 표시된다. FPSExport 에서 제공하는 내보내기(Export) 프로시져들은 기본적으로 데이터베이스 내용 그대로 내보내는 것을 전제로 하고 있다.   DBGrid 에 표시되는 모습 그대로 엑셀 파일로 출력하려면 어떻게 해야 할까. 

엑셀 문서는 한개의 페이지가 WorkSheet , WorkSheet 가 여러개 모여서 WorkBook 으로 구성된다. WorkSheet 내의 한개의 칸은 Cell 이라고 부른다. WorkBook 을 Create 하고 WorkSheet 를 Add 하면 한개의 엑셀 문서가 완성된다. uses 에 fpspreadsheet 와 fpstypes 를 추가시키고 다음 문장을 입력하면 문서가 만들어진다.

  Book := TsWorkBook.Create;
  Sheet := Book.AddWorksheet('비밀번호 관리');     

엑셀 문서를 만들고 그 내부에 구현해야 하는 기능은 다음과 같다.

- DBGrid 컬럼의 [Visible] Property 가 True 일 때만 엑셀파일로 출력
- DBGrid 컬럼의 캡션을 엑셀파일의 첫행에 출력

[ DBGrid Column 이 Visible = False ]


DBGrid 의 Column 이 Visible 일 때만 엑셀문서에 쓰기한다. 첫행은 DBGrid 의 Caption 을 WriteText 한다. DBGrid 의 Column 이 Visible 일 때만 VisCol 을 1 증가시켜서 엑셀문서의 Column 을 증가시키는 원리를 주목해보자.

 
for Col := 0 to ADataSet.Fields.Count - 1 do
begin
  if AGrid.Columns[Col].Visible then ////DBGrid 의 컬럼이 Visible 일 때만 진행한다.
  begin
    Cell := Sheet.WriteText(Row, VisCol, AGrid.Columns[Col].Title.Caption);
    Sheet.WriteBackgroundColor(cell, clMoneyGreen); //첫 행의 배경색
    VisCol := VisCol + 1;
  end;
end;                          

전체코드는 다음과 같다. 

 
procedure TMainForm.ExportDBGridToExcel(AGrid: TDBGrid; AFileName: String);
var
  Book: TsWorkBook;
  Sheet: TsWorkSheet;
  Row, Col, VisCol: Integer;
  Cell: PCell;
  ADataSet: TDataSet;
  Field: TField;
begin
  ADataSet := AGrid.DataSource.DataSet;
  Book := TsWorkBook.Create;
  Sheet := Book.AddWorksheet('비밀번호 관리');
  Row := 0; Col := 0; VisCol := 0;

  try
      //DBGrid 의 캡션을 워크시트의 첫행에 출력한다.
    for Col := 0 to ADataSet.Fields.Count - 1 do
    begin
      if AGrid.Columns[Col].Visible then //DBGrid 의 컬럼이 Visible 일 때만 진행한다.
      begin
        Cell := Sheet.WriteText(Row, VisCol, AGrid.Columns[Col].Title.Caption);
        Sheet.WriteBackgroundColor(cell, clMoneyGreen); //첫 행의 배경색  
        VisCol := VisCol + 1;
      end;
    end;

    Inc(Row); //워크시트를 두번재 행으로 이동
    ADataSet.First; //데이터세트의 첫행으로 이동

    while not ADataSet.EOF do  //마지막 레코드까지 계속 진행한다.
    begin
      VisCol := 0;
      for Col := 0 to AGrid.Columns.Count - 1 do
      begin
        if AGrid.Columns[Col].Visible then //DBGrid 의 컬럼이 visible 일때만 진행한다.
        begin
          Field := AGrid.Columns[Col].Field; //DBGrid 의field 를 넣고 type 을 결정한다.

          if Field.DataType in [ftInteger, ftWord, ftSmallint, ftAutoinc, ftLargeInt] then
            Sheet.WriteNumber(Row, VisCol, ADataSet.Fields[Col].AsInteger)
          else if Field.DataType in [ftBCD, ftFloat, ftFMTBcd] then
            Sheet.WriteNumber(Row, VisCol, ADataSet.Fields[Col].AsFloat)
          else if Field.DataType in [ftCurrency] then
            Sheet.WriteCurrency(Row, VisCol, ADataSet.Fields[Col].AsFloat)
          else if Field.DataType in [ftString, ftFixedChar] then
            Sheet.WriteText(Row, VisCol, ADataSet.Fields[Col].AsString)
          else if Field.DataType in [ftWideMemo, ftWideString, ftFixedWideChar] then
            Sheet.WriteText(Row, VisCol, UTF8Encode(ADataSet.Fields[Col].AsWideString))
          else if Field.DataType in [ftMemo, ftFmtMemo, ftWideMemo] then
            Sheet.WriteText(Row, VisCol, ADataSet.Fields[Col].AsString)
          else if Field.DataType = ftBoolean then
            Sheet.WriteBoolValue(Row, VisCol, ADataSet.Fields[Col].AsBoolean)
          else
            Sheet.WriteText(Row, VisCol, ADataSet.Fields[Col].AsString);
          VisCol := VisCol + 1; //DBGrid 의 컬럼이 visible 일때만 워크시트의 오른쪽으로 증가시킨다.
        end;
      end;

      Inc(Row);
      ADataSet.Next;
    end;

    Book.WriteToFile(AFileName, sfOOXML, True);
    QuestionDlg('엑셀 내보내기', '엑셀파일 ' + AFileName +
        ' 가 만들어졌습니다.', mtCustom, [mrYes, '확인'], '');

  finally
    Book.Free;
  end;
end;                               

최종 결과물은 다음과 같다. 

[ 엑셀 문서로 출력한 결과 ]
whatwas.zip
2.64MB
whatwas_source.zip
0.87MB