Delphi-在Excel中复制行

时间:2018-11-01 15:01:35

标签: excel delphi

Delphi Tokyo-我有一个Delphi应用程序,它可以处理Excel电子表格。我有一个源表...叫做RawData。我需要将特定行(基于过滤器)复制到同一工作簿(称为ActivitySheet)中的另一个工作表。尽管可以使它正常工作...在过程结束时,我收到一条Excel错误消息,消息为“图片太大,将被截断。”这使我相信我正在使用的命令正在使用剪贴板,因此我不想这样做。

这就是我现在正在做的事...

var
  ActivitySheet : _WorkSheet;
  destRange : OleVariant;
begin   

  oExcel.Worksheets.Add(EmptyParam, EmptyParam, 1, xlWorksheet, LOCALE_USER_DEFAULT);
  ActivitySheet:= oExcel.ActiveSheet as _Worksheet;
  ActivitySheet.Name := 'Activity';
  destRange := ActivitySheet.Range['A1', 'A1'];

  // Set RawData Sheet as active
  RawDataSheet.Activate(LOCALE_USER_DEFAULT);
  Application.ProcessMessages;


  // Now add the both filters that we want... (Not real filters, but easier to understand)
  RawDataSheet.UsedRange[LOCALE_USER_DEFAULT].AutoFilter(1, '=*Blue*', xlOr, '=*Red*', True );
  RawDataSheet.UsedRange[LOCALE_USER_DEFAULT].AutoFilter(2, '=Car', xlOr, '=Truck', True );

  ShowMessage(IntToStr(RawDataSheet.UsedRange[LOCALE_USER_DEFAULT].Rows.Count));
  RawDataSheet.UsedRange[LOCALE_USER_DEFAULT].Copy(destRange);
  ...

虽然此代码有效,并且仅基于当前过滤器复制有效的行,但在我的代码后面的“保存电子表格”阶段会给我错误。我考虑过使用Vararray,但是ShowMessage行向我显示了RawSheet中的TOTAL行,而不是Filtered行...因此,我必须遍历工作表中的所有行(而不是仅过滤行),然后确定如果该行有效...

将一组已过滤的行复制到新工作表的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

当我第一次看到这个q时,我不知道该怎么做。号码后 错误的开始,我遇到了这个答案

  

Excel Filtering and Copying in VBA

这表明,只要您知道执行此操作的确切“魔术”,即可非常简单地完成该操作。

这是我编写的代码。我一直在后期使用绑定到Excel,因为它 避免在任何地方都必须引用LOCALE_USER_DEFAULT。

type
  TDefaultForm = class(TForm)
    [...]
  public
    vExcel,
    vWB,
    vRange,
    vSheet,
    vActivitySheet,
    vRawDataSheet : OleVariant;
  end;
[...]
  procedure TDefaultForm.CopyFilteredRange;
  var
    i : Integer;
    vRange : OleVariant;
    vDestRange : OleVariant;
  begin
    vRange := vRawDataSheet.Range['A1', 'A100'];
    vDestRange := vActivitySheet.Range['A1', 'A1'];
    vRange.SpecialCells(xlCellTypeVisible).Copy(vDestRange);
  end;

  procedure TDefaultForm.TestFilter;
  var
    vRange : OleVariant;
  begin
    vExcel := CreateOleObject('Excel.Application');
    vExcel.Visible := True;

    vWB := vExcel.WorkBooks.Add;

    vRawDataSheet := vWB.ActiveSheet;
    vActivitySheet := vWB.Sheets[2];

    vRange := vRawDataSheet.Range['A1', 'A100'];

    vRange.Item[1, 1]  := 'Vehicle';
    vRange.Item[2, 1]  := 'Car';
    vRange.Item[3, 1]  := 'Truck';
    vRange.Item[4, 1]  := 'Truck';
    vRange.Item[5, 1]  := 'Car';
    vRange.Item[6, 1]  := 'Truck';
    vRange.Item[7, 1]  := 'Truck';

    vRawDataSheet.UsedRange.Select;

    vRawDataSheet.UsedRange.AutoFilter(Field := 1, Criteria1 := 'Car');
    CopyFilteredRange;
  end;

顺便说一句,如果您不熟悉它,可以在调用中传递参数的方式

   vRawDataSheet.UsedRange.AutoFilter(Field := 1, Criteria1 := 'Car');

是后期绑定的一种特殊的Delphi语法,它避免了传递的麻烦 早期绑定所需的所有参数。

顺便说一句,我收到了“ Picture too large ...”消息,但似乎很容易避免:只需在ClipBrd列表中包含Uses,然后在之后调用ClipBoard.Clear复制过滤的行。通常,我不喜欢把剪贴板弄乱,因为它是系统范围的资源,但是作为一种快速解决方案,清除它可能是可以接受的。