2

多数のグリッドを使用していますが、これらのグリッドは、Excel のようにテーブル レイアウトで行と列をコピーすることをサポートしていません。

グリッドからいくつかの行と列をコピーし、適切に配置された列の適切な書式設定で Outlook 電子メールに貼り付けることができる必要があります。Excel からコピーすると、うまくいきます。

グリッドからコピーすると、タブ区切りのデータが取得されますが、それは機能しません。また、フォントは Courier のように等幅ではないため、データを同じ文字数にパディングしても機能しません。

Excel がこの余分な書式をクリップボードに入れる方法を知りたいです。ちなみに私はDelphiを使用していますが、アドバイスをいただければ幸いです。

編集: 最初に Excel 経由で移動するのではなく、グリッドから直接クリップボードに移動し、次に電子メールに移動します。

ありがとう!バート

4

2 に答える 2

4

Excel からクリップボードにコピーすると、さまざまな形式がクリップボードに配置されます。複製でき、目的の結果が得られるフォーマットの 1 つを見つける必要があります。

過去にこれを達成した方法は、HTML をクリップボードに置くことです。この機能を使用できるのは次のとおりです。

procedure ClipboardError;
begin
  raise EMyExceptionClass.Create('Could not complete clipboard operation.');
end;

procedure CheckClipboardHandle(Handle: Windows.HGLOBAL);
begin
  if Handle=0 then begin
    ClipboardError;
  end;
end;

procedure CheckClipboardPtr(Ptr: Pointer);
begin
  if not Assigned(Ptr) then begin
    ClipboardError;
  end;
end;

procedure PutInClipboard(ClipboardFormat: UINT; Buffer: Pointer; Count: Integer);
var
  Handle: Windows.HGLOBAL;
  Ptr: Pointer;
begin
  if Count>0 then begin
    Clipboard.Open;
    Try
      Handle := Windows.GlobalAlloc(GMEM_MOVEABLE, Count);
      Try
        CheckClipboardHandle(Handle);
        Ptr := Windows.GlobalLock(Handle);
        CheckClipboardPtr(Ptr);
        Move(Buffer^, Ptr^, Count);
        Windows.GlobalUnlock(Handle);
        Clipboard.SetAsHandle(ClipboardFormat, Handle);
      Except
        GlobalFree(Handle);
        raise;
      End;
    Finally
      Clipboard.Close;
    End;
  end;
end;

var
  HTMLClipboardFormat: UINT;

procedure PutHTMLInClipboard(Strings: TStrings);

var
  Data: TStringList;

  procedure WriteDescription(const StartOffset, EndOffset: Integer);
  begin
    while Data.Count<5 do begin
      Data.Add('');
    end;
    Data[0] := 'Version:0.9';
    Data[1] := Format('StartHTML:%.8d', [StartOffset]);
    Data[2] := Format('EndHTML:%.8d', [EndOffset]);
    Data[3] := Format('StartFragment:%.8d', [StartOffset]);
    Data[4] := Format('EndFragment:%.8d', [EndOffset]);
  end;

var
  StartOffset, EndOffset: Integer;
  Text: UTF8String;
begin
  Data := TStringList.Create;
  Try
    WriteDescription(0, 0);//write out description stub - will be replaced later
    StartOffset := Length(UTF8String(Data.Text));
    Data.AddStrings(Strings);
    EndOffset := Length(UTF8String(Data.Text))-1;
    WriteDescription(StartOffset, EndOffset);//now we know the offsets we can write proper description
    Text := Data.Text;
    PutInClipBoard(HTMLClipboardFormat, PAnsiChar(Text), Length(Text));
  Finally
    FreeAndNil(Data);
  End;
end;
....
initialization
  HTMLClipboardFormat := Windows.RegisterClipboardFormat('HTML Format');

あとは、その関数に渡す HTML を生成するだけです。それはあなた次第です。Excel を使用して HTML をクリップボードに置き、生成された HTML を検査することをお勧めします。あなたがする必要があることのガイドとしてそれを使用してください。

于 2013-03-18T09:21:55.003 に答える
1

この関数を使用して、グリッドの内容を Excel や表形式データをサポートするその他のアプリケーションにエクスポートできます。

procedure ExportDBGrid(DBGrid: TDBGrid; toExcel: Boolean);
var
  bm: TBookmark;
  col, row: Integer;
  sline: String;
  mem: TStringList;
  ExcelApp: Variant;
begin
  Screen.Cursor := crHourglass;
  try
    DBGrid.DataSource.DataSet.DisableControls;
    bm := DBGrid.DataSource.DataSet.GetBookmark;
    DBGrid.DataSource.DataSet.First;

    // create the Excel object
    if toExcel then
    begin
      ExcelApp := CreateOleObject('Excel.Application');
      ExcelApp.WorkBooks.Add(1); //xlWBatWorkSheet);
      ExcelApp.WorkBooks[1].WorkSheets[1].Name := 'Grid Data';
    end;

    // First we send the data to a memo
    // works faster than doing it directly to Excel
    mem := TStringList.Create;
    try
      sline := '';

      // add the info for the column names
      for col := 0 to DBGrid.FieldCount-1 do
        if Assigned(DBGrid.Fields[col]) then
          if DBGrid.Fields[col].Visible then
            sline := sline + DBGrid.Fields[col].DisplayLabel + #9;
      mem.Add(sline);

      // get the data into the memo
      for row := 0 to DBGrid.DataSource.DataSet.RecordCount-1 do
      begin
        sline := '';
        for col := 0 to DBGrid.FieldCount-1 do
          if Assigned(DBGrid.Fields[col]) then
            if DBGrid.Fields[col].Visible then
              sline := sline + DBGrid.Fields[col].AsString + #9;
        mem.Add(sline);
        DBGrid.DataSource.DataSet.Next;
      end;

      // we copy the data to the clipboard
      Clipboard.AsText := mem.Text;
    finally
      mem.Free;
    end;
    // if needed, send it to Excel
    // if not, we already have it in the clipboard
    if toExcel then
    begin
      ExcelApp.Workbooks[1].WorkSheets['Grid Data'].Paste;
      ExcelApp.Visible := true;
    end;
  finally
    DBGrid.DataSource.DataSet.GotoBookmark(bm);
    DBGrid.DataSource.DataSet.EnableControls;
    Screen.Cursor := crDefault;
  end;
end;
于 2013-03-18T08:45:55.980 に答える