1

Delphi 7 で Ole Automation を使用して、Excel スプレッドシートの特定の範囲内の各セルのテキストを抽出しようとしています。

ちょうど今、(ワークブックが既に開いていると仮定して) ワークシートから範囲を選択し、.Value2 関数を使用して Variant 配列を設定する関数があります。

function GetExcelRange(const AWorkbookIndex: integer; const AWorksheetIndex: integer; const firstCol, lastCol, firstRow, lastRow: integer): Variant;
var
 AWorkbook, ARange: OleVariant;
begin
 Result := Unassigned;
 if not VarIsEmpty(ExcelApp) then
 begin
  if ExcelApp.Workbooks.Count >= AWorkbookIndex then
  begin
   AWorkbook := ExcelApp.Workbooks[AWorkbookIndex];
   try
    if AWorkbook.Worksheets.Count >= AWorksheetIndex then
    begin;
     ARange := AWorkbook.WorkSheets[AWorksheetIndex].Range[AWorkbook.WorkSheets[AWorksheetIndex].Cells[firstRow, firstCol],
                                   AWorkbook.WorkSheets[AWorksheetIndex].Cells[lastRow, lastCol]];
     Result := ARange.Value2;
    end;
   finally
    AWorkbook := Unassigned;
    ARange := Unassigned;
   end;
  end;
 end;
end;

私が期待するのは、行を次のように変更できることですResult := ARange.Textが、null オブジェクトを返します。

Ole オブジェクトがアクティブな間は各セルを反復処理せず、上記のように範囲全体のテキストを配列に貼り付けたいと思います。

4

2 に答える 2

4

あなたの質問から、Excel でユーザーに表示されるセルのテキストの内容を読みたいと推測します。範囲全体で操作を実行できるとは思いません。私が過去に行った方法は、このようなものです。アーリー バインド COM を使用していることに注意してください。

function GetCellVariant(const Sheet: ExcelWorksheet; const Row, Col: Integer): OleVariant;

  function ErrorText(const Cell: ExcelRange; hr: HRESULT): string;
  const
    ErrorBase=HRESULT($800A0000);
  var
    i: Integer;
  begin
    Result := Cell.Text;
    for i := 1 to Length(Result) do begin
      if Result[i]<>'#' then begin
        exit;
      end;
    end;
    if hr=ErrorBase or xlErrDiv0 then begin
      Result := '#DIV/0!';
    end else if hr=ErrorBase or xlErrNA then begin
      Result := '#N/A';
    end else if hr=ErrorBase or xlErrName then begin
      Result := '#NAME?';
    end else if hr=ErrorBase or xlErrNull then begin
      Result := '#NULL!';
    end else if hr=ErrorBase or xlErrNum then begin
      Result := '#NUM!';
    end else if hr=ErrorBase or xlErrRef then begin
      Result := '#REF!';
    end else if hr=ErrorBase or xlErrValue then begin
      Result := '#VALUE!';
    end else begin
      Result := 'an error';
    end;
  end;

var
  Cell: ExcelRange;
  hr: HRESULT;
begin
  Cell := GetCellAsRange(Sheet, Row, Col);//effectively this is Sheet.Range
  if VarIsError(Cell.Value, hr) then begin
    raise ECellValueError.CreateFmt(
      'Cell %s contains %s.',
      [R1C1toA1(Row,Col), ErrorText(Cell, hr)]
    );
  end;
  Result := Cell.Value;
end;

function GetCellString(const Sheet: ExcelWorksheet; const Row, Col: Integer): string;
var
  Value: Variant;
  Cell: ExcelRange;
begin
  Value := GetCellVariant(Sheet, Row, Col);
  if VarIsNumeric(Value) then begin
    Cell := GetCellAsRange(Sheet, Row, Col);
    Result := Sheet.Application.WorksheetFunction.Text(Cell.Value, Cell.NumberFormatLocal);
  end else begin
    Result := ConvertToString(Value);//this converts a Variant to string
  end;
end;

実際、このコードは、スタック オーバーフローで私がここで尋ねた最初の質問から生まれました。

于 2013-03-05T17:21:56.457 に答える