delphi控制Excel(二)

/ XL Report
unit LebutXLReport;
interface
uses
  Controls, xlReport, cxGrid, cxStyles, Dialogs, cxExportGrid4Link, ShellAPI,
  cxGridCustomTableView, LebutCommons, cxGridCustomView, DB, Classes, kbmMemTable,
  cxGridDBTableView, ComObj, cxCustomData, cxGridDBBandedTableView, cxGridDBCardView,
  cxGridTableView;
{*
  导出成 Excel
  @param AControls 在导出操作时不能进行任何操作的控件列表,如导出按钮、查询按钮
  @param AReport Excel 报表控件
}
procedure ReportToExcel(AControls: array of TControl; AReport: TxlReport); overload;
{*
  导出文件
  @param AGrid 要导出的网格
  @param AStye 修改网格的字体和颜色 默认为空
  @param AFileName 导出文件的路径和文件名 默认为空(应用程序所在路径)
  @param ADynamic 是否动态获得文件名 True 是 False 不是 默认为False
}
procedure ReportToExcel(AGrid: TcxGrid; AStye: TcxStyle = nil; AFileName: string = ''; ADynamic: Boolean = False); overload;


{*
  网格 完全展现到Excel中去
  暂时只支持 TcxGridDBTableView ,TcxGridDBBandedTableView类型网格
  @param AcxGridDBTableView 需要展现的网格
  @param ASheetName Excel的Sheet的命名[既要展示的有关什么的信息]
}
procedure ReportToExcel(AcxGridDBTableView: TcxCustomGridView; ASheetName: string); overload;
implementation
uses
  FormProgress, Forms, xlEngine, Windows, SysUtils;


procedure ReportToExcel(AControls: array of TControl; AReport: TxlReport);
var
  VProgressForm: TProgressForm;
  VIndex: Integer;
  VActive: Boolean;
begin
  VActive := False;


  Screen.Cursor := crHourGlass;
  try
    with AReport.DataSources do
    begin
      for VIndex := 0 to Count - 1 do
      begin
        Items[VIndex].Enabled := Items[VIndex].DataSet.Active;


        if Items[VIndex].Enabled then
          VActive := True;
      end;
    end;


    if VActive then
    begin
      for VIndex := 0 to Length(AControls) - 1 do
        AControls[VIndex].Enabled := False;


      VProgressForm := TProgressForm.Create(nil);
      try
        VProgressForm.SetProgressCaption('正在导出成 Excel,请稍等...');
        VProgressForm.Show;
        Application.ProcessMessages;
        try
          AReport.Report();
        except
          on erErr: ExlReportError do
            if erErr.Message = 'MS Excel not installed' then
              Application.MessageBox('您的系统没有安装 Excel,不能进行导出操作,请先安装 Excel!', '导出异常', MB_OK + MB_ICONERROR)
            else
              Application.MessageBox(PChar(erErr.Message), '导出异常', MB_OK + MB_ICONERROR);
        end;
      finally
        FreeAndNil(VProgressForm);


        for VIndex := 0 to Length(AControls) - 1 do
          AControls[VIndex].Enabled := True;
      end;
    end
    else
    begin
      MessageBox(0,'必须有数据才能进行导出,请先进行点击查询按钮进行查询','导出提示',MB_OK + MB_ICONINFORMATION);
    end;
  finally
    Screen.Cursor := crDefault;
  end;
end;


procedure ReportToExcel(AGrid: TcxGrid; AStye: TcxStyle = nil; AFileName: string = ''; ADynamic: Boolean = False);
var
  VFileName: string;
  VIndex: Integer;
  VStyle: array of TcxStyle;
  VExt: string;
begin
  if ADynamic then
    with TSaveDialog.Create(nil) do
      try
        DefaultExt := 'xls';
        if Execute then
          VFileName := FileName
        else
          Exit;
      finally
        Free;
      end
  else if AFileName = '' then
    VFileName := ChangeFileExt(AppExeName, '.xls')
  else
    VFileName := AFileName;


  if AStye <> nil then
  begin
    SetLength(VStyle, AGrid.Levels.Count);
    for VIndex := 0 to AGrid.Levels.Count - 1 do
      if AGrid.Levels[VIndex].GridView is TcxCustomGridTableView then
        with (AGrid.Levels[VIndex].GridView as TcxCustomGridTableView).Styles do
        begin
          VStyle[VIndex] := Content;
          Content := AStye;
        end;
  end;
  try
    try
      VExt := ExtractFileExt(VFileName);


      if VExt = '.txt' then
        ExportGrid4ToTEXT(VFileName, AGrid, True, True)
      else if VExt = '.xml' then
        ExportGrid4ToXML(VFileName, AGrid, True, True)
      else if VExt = '.html' then
        ExportGrid4ToHTML(VFileName, AGrid, True, True)
      else if VExt = '.xls' then
        ExportGrid4ToExcel(VFileName, AGrid, True, True);
    except
      Application.MessageBox('导出不成功,可能是导出文件正处于打开状态或其他原因!', '提示', MB_OK + MB_ICONERROR);
      Exit;
    end;


    ShellExecuteFile(VFileName);
  finally
    if AStye <> nil then
      for VIndex := 0 to AGrid.Levels.Count - 1 do
        if AGrid.Levels[VIndex].GridView is TcxCustomGridTableView then
          (AGrid.Levels[VIndex].GridView as TcxCustomGridTableView).Styles.Content := VStyle[VIndex];
  end;
end;


procedure ReportToExcel(AcxGridDBTableView: TcxCustomGridView; ASheetName: string); overload;
var
  VExcelApp: Variant;
  i, j, m, VIndex, VPosition, VPosition2, VInteger, VUnite: Integer;
  VDataSet: TDataSet;
  VArrayList: TStrings;
  VString, VStringResult, VFilter, VFieldName, Vlist, VBandCaption, VBandCaptionNext: string;
  VFieldType: TFieldType;
  VProgressForm: TProgressForm;
  VkbmMemTableCompareOptions: TkbmMemTableCompareOptions;
  VBookMark: Pointer;
  VFloat: Double;


  // 获取网格类型 1:TcxGridDBTableView 2:TcxGridDBBandedTableView 其余的3
  function GetGridType: Integer;
  begin
    if AcxGridDBTableView.ClassType = TcxGridDBTableView then
      Result := 1
    else if AcxGridDBTableView.ClassType = TcxGridDBBandedTableView then
      Result := 2
    else
      Result := 3;
  end;


  // 获取数据集
  function GetDataSet: TDataSet;
  begin
    Result := nil;
    case GetGridType of
      1: Result := (AcxGridDBTableView as TcxGridDBTableView).DataController.DataSource.DataSet;
      2: Result := (AcxGridDBTableView as TcxGridDBBandedTableView).DataController.DataSource.DataSet;
    end;
  end;


  // 网格断开
  procedure GridCut;
  begin
    VBookMark := VDataSet.GetBookmark;
    AcxGridDBTableView.BeginUpdate;
    case GetGridType of
      1: (AcxGridDBTableView as TcxGridDBTableView).DataController.DataSource.DataSet := nil;
      2: (AcxGridDBTableView as TcxGridDBBandedTableView).DataController.DataSource.DataSet := nil;
    end;
  end;


  // 网格连接上
  procedure GridConnect;
  begin
    VDataSet.GotoBookmark(VBookMark);
    case GetGridType of
      1: (AcxGridDBTableView as TcxGridDBTableView).DataController.DataSource.DataSet := VDataSet;
      2: (AcxGridDBTableView as TcxGridDBBandedTableView).DataController.DataSource.DataSet := VDataSet;
    end;
    AcxGridDBTableView.EndUpdate;
  end;


  // 获取列数
  function GetColumnCount: Integer;
  begin
    Result := 0;
    case GetGridType of
      1: Result := (AcxGridDBTableView as TcxGridDBTableView).ColumnCount;
      2: Result := (AcxGridDBTableView as TcxGridDBBandedTableView).ColumnCount;
    end;
  end;


  // 获取某一列 AInteger: 哪一列
  function GetColumn(AInteger: Integer): TcxGridColumn;
  begin
    Result := nil;
    case GetGridType of
      1: Result := (AcxGridDBTableView as TcxGridDBTableView).Columns[AInteger] as TcxGridColumn;
      2: Result := (AcxGridDBTableView as TcxGridDBBandedTableView).Columns[AInteger] as TcxGridColumn;
    end;
  end;


  //获取一共排序的列数
  function GetSortedItemCount: Integer;
  begin
    Result := 0;
    case GetGridType of
      1: Result := (AcxGridDBTableView as TcxGridDBTableView).SortedItemCount;
      2: Result := (AcxGridDBTableView as TcxGridDBBandedTableView).SortedItemCount;
    end;
  end;


  //获取一排序绑定的字段 AInteger: 哪一列
  function GetFieldName(AInteger: Integer): string;
  begin
    Result := '';
    case GetGridType of
      1: Result := (AcxGridDBTableView as TcxGridDBTableView).Columns[AInteger].DataBinding.FieldName;
      2: Result := (AcxGridDBTableView as TcxGridDBBandedTableView).Columns[AInteger].DataBinding.FieldName;
    end;
  end;


  // 获取过滤条件
  function GetFilterText: string;
  begin
    Result := '';
    case GetGridType of
      1: Result := (AcxGridDBTableView as TcxGridDBTableView).DataController.Filter.FilterText;
      2: Result := (AcxGridDBTableView as TcxGridDBBandedTableView).DataController.Filter.FilterText;
    end;
  end;
begin
  if GetGridType = 3 then
  begin
    Application.MessageBox(PChar(Format('暂时还不支持该“%s”类型网格导出!', [AcxGridDBTableView.ClassName])), '提示', MB_OK + MB_ICONERROR);
    Exit;
  end;


  VProgressForm := TProgressForm.Create(nil);
  try
    VProgressForm.SetProgressCaption('正在导出成 Excel,请稍等...');
    VProgressForm.Show;
    Application.ProcessMessages;


    try
      VExcelApp := CreateOleObject('Excel.Application');
    except
      on E: Exception do
      begin
        Application.MessageBox(PChar(E.Message), '提示', MB_ICONERROR);
        Exit;
      end;
    end;


    VExcelApp.Visible := False;
    VExcelApp.Caption := Format('Microsoft Excel %s', [ASheetName]);


    VInteger := VExcelApp.SheetsInNewWorkbook;
    try
      VExcelApp.SheetsInNewWorkbook := 1;
      VExcelApp.WorkBooks.Add();
      VExcelApp.WorkSheets[1].Name := ASheetName;
    finally
      VExcelApp.SheetsInNewWorkbook := VInteger;
    end;


    // 获取数据集
    VDataSet := GetDataSet;


    try
      // 网格断开
      GridCut;


      // 进行排序
      for i := 0 to GetColumnCount - 1 do
        with GetColumn(i) do
          if SortIndex = GetSortedItemCount - 1 then
            if SortOrder = soAscending then
            begin
              (VDataSet as TkbmMemTable).SortOn(GetFieldName(i), []);
              Break;
            end
            else if SortOrder = soDescending then
            begin
              VkbmMemTableCompareOptions := [mtcoDescending];
              (VDataSet as TkbmMemTable).SortOn(GetFieldName(i), VkbmMemTableCompareOptions);
              Break;
            end;


      // 数据进入
      VIndex := 0;
      VUnite := 1;
      VBandCaption := '';
      VBandCaptionNext := '';


      for i := 0 to GetColumnCount - 1 do
        with GetColumn(i) do
          if Visible then
          begin
            Inc(VIndex);
            j := GetGridType + 1;


            VFieldName := GetFieldName(i);


            // 设置列宽
            if Width < 2168 then
              VExcelApp.Columns[VIndex].ColumnWidth := Width/8.0
            else
              VExcelApp.Columns[VIndex].ColumnWidth := 255;


            if GetGridType = 2 then
            begin
              VBandCaptionNext := (AcxGridDBTableView as TcxGridDBBandedTableView).Columns[i].Position.Band.Caption;


              if VIndex = 1 then
              begin
                VBandCaption := VBandCaptionNext;
                VExcelApp.Cells[1, 1].Value := VBandCaptionNext;
              end
              else if i = GetColumnCount - 1 then
              begin
                if VBandCaptionNext = VBandCaption then
                begin
                  VExcelApp.ActiveSheet.Range[VExcelApp.Cells[1, VUnite], VExcelApp.Cells[1, VIndex]].Select;
                  VExcelApp.Selection.Merge;
                end
                else
                  VExcelApp.Cells[1, VIndex].Value := VBandCaptionNext;
              end
              else
              begin
                if VBandCaptionNext <> VBandCaption then
                begin
                  VExcelApp.ActiveSheet.Range[VExcelApp.Cells[1, VUnite], VExcelApp.Cells[1, VIndex - 1]].Select;
                  VExcelApp.Selection.Merge;
                  VUnite := VIndex;
                  VExcelApp.Cells[1, VIndex].Value := VBandCaptionNext;
                  VBandCaption := VBandCaptionNext;
                end;
              end;
            end;


            VExcelApp.Cells[GetGridType, VIndex].Value := Caption;


            case VDataSet.FindField(VFieldName).DataType of
              ftDateTime: begin
                            with VDataSet do
                            begin
                              First;
                              while not Eof do
                              begin
                                VFloat := FieldByName(VFieldName).AsFloat;
                                if FieldByName(VFieldName).AsString <> '' then
                                  if VFloat <= 1 then
                                  begin
                                    VExcelApp.Columns[VIndex].NumberFormatLocal := 'hh:mm:ss';
                                    Break;
                                  end
                                  else if VFloat > Trunc(VFloat) then
                                  begin
                                    VExcelApp.Columns[VIndex].NumberFormatLocal := 'yyyy-mm-dd hh:mm:ss';
                                    Break;
                                  end
                                  else if VFloat = Trunc(VFloat) then
                                  begin
                                    VExcelApp.Columns[VIndex].NumberFormatLocal := 'yyyy-mm-dd';
                                    Break;
                                  end;
                                Next;
                              end;
                            end;
                          end;
              ftString: VExcelApp.Columns[VIndex].NumberFormatLocal := '@';
            end;


            with VDataSet do
            begin
              First;
              while not Eof do
              begin
                VExcelApp.Cells[j, VIndex].Value := FieldByName(VFieldName).AsString;


                Next;
                Inc(j);
              end;
            end;
          end;


      // 字体设置为 9 号
      VExcelApp.Cells.Select;
      VExcelApp.Selection.Font.Name := '宋体';
      VExcelApp.Selection.Font.Size := 9;


      // 自动换行
      VExcelApp.Selection.WrapText := True;
      VExcelApp.Selection.VerticalAlignment := '1';


      //冻结窗格
      VExcelApp.Rows[GetGridType + 1].Select;
      VExcelApp.ActiveWindow.FreezePanes := True;


      // 过滤
      VExcelApp.Cells[GetGridType, 1].AutoFilter;


      // 取得过滤条件
      VFilter := GetFilterText;


      // 开始过滤
      if VFilter <> '' then
      begin
        // 去掉前'(',后')'
        VFilter := Copy(VFilter, 2, Length(VFilter) - 2);


        //,替换') AND ('
        VFilter := StringReplace(VFilter, ') AND (', ',', [rfReplaceAll]);


        // 分离到数组
        VArrayList := Split2List(VFilter, ',');
        try
          for m := 0 to VArrayList.Count - 1 do
          begin
            Vlist := VArrayList[m];
            // 获取 ' = ' 的位置
            VPosition := Pos(' = ', Vlist);


            // 取过滤条件
            if VPosition <> 0 then
            begin
              VString := LowerCase(Copy(Vlist, 1, VPosition - 1));
              VStringResult := Copy(Vlist, VPosition + 3, Length(Vlist) - VPosition - 2);


              VIndex := 0;
              for i := 0 to GetColumnCount - 1 do
                with GetColumn(i) do
                  if Visible then
                  begin
                    Inc(VIndex);


                    VFieldName := GetFieldName(i);
                    VFieldType := VDataSet.FindField(VFieldName).DataType;


                    if LowerCase(VFieldName) = VString then
                    begin
                      if VFieldType = ftFloat then
                        VExcelApp.Selection.AutoFilter(VIndex, VStringResult)
                      else if VStringResult = 'NULL' then
                        VExcelApp.Selection.AutoFilter(VIndex, '=')
                      else
                        VExcelApp.Selection.AutoFilter(VIndex, Copy(VStringResult, 2, Length(VStringResult) - 2));


                      Break;
                    end;
                  end;
            end
            else
            begin
              VPosition2 := Pos(' <> ', Vlist);
              VString := LowerCase(Copy(Vlist, 1, VPosition2 - 1));


              VIndex := 0;


              for i := 0 to GetColumnCount - 1 do
                with GetColumn(i) do
                  if Visible then
                  begin
                    Inc(VIndex);


                    VFieldName := GetFieldName(i);


                    if LowerCase(VFieldName) = VString then
                    begin
                      VExcelApp.Selection.AutoFilter(VIndex, '<>');
                      Break;
                    end;
                  end;
            end;
          end;
        finally
          FreeAndNil(VArrayList);
        end;
      end;


      case GetGridType of
        1: begin
             // 居中
             VExcelApp.Rows[1].Select;
             VExcelApp.Selection.HorizontalAlignment := '3';//xlCenter 1--常规、2--靠左、3--居中、4--靠右
             //光标跑上去
             VExcelApp.Cells[2, 1].Select;
           end;
        2: begin
             // 居中
             VExcelApp.Rows[1].Select;
             VExcelApp.Selection.HorizontalAlignment := '3';//xlCenter 1--常规、2--靠左、3--居中、4--靠右
             VExcelApp.Rows[2].Select;
             VExcelApp.Selection.HorizontalAlignment := '3';//xlCenter 1--常规、2--靠左、3--居中、4--靠右
             //光标跑上去
             VExcelApp.Cells[3, 1].Select;
           end;
      end;
    finally
      // 网格连接上
      GridConnect;
    end;


    // 显示
    VExcelApp.Visible := True;
  finally
    FreeAndNil(VProgressForm);
  end;
end;


end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值