Migaro. 技術Tips

                       

ミガロ. 製品の技術情報
IBMiの活用に役立つ情報を掲載!


Delphi OLEのExcel操作術 第1回:基本編

今回より、DelphiアプリケーションでExcelを操作する便利な方法を
全7回に分けてご紹介してまいります。

  

レイトバインディングとアーリーバインディングについて

DelphiでExcelを利用する場合、OLEで様々な操作を行うことができますが、
主に2つの方法があります。

  1. Late Binding (レイトバインディング)
  2. Early Binding (アーリーバインディング)

1. はComObjをusesに追加し、CreateOleObjectを使用する方法です。
2. はServersページにあるOfficeコンポーネント(TExcelApplication等)を使用する方法です。

主な違いをレイトバインディングについて以下に挙げます。

  • コンパイル時に文法チェックができない
    (コード補完機能を利用できない)
  • 定数定義を自分で行わなければいけない
  • 実行環境のExcelのバージョンに依存しない

アーリーバインディングは上記の逆になります。
本記事のシリーズでは、レイトバインディングについてご説明します。

レイトバインディングでは、
文法その他はExcelのVBAに準拠するとお考え下さい。

 

 


Excel起動時のロジック

では実際のコーディングです。

uses節には「System.Win.ComObj」を追加しておいて下さい。
(Delphi XE以前では「ComObj」)

OLEで扱う変数はVariant(またはOleVariant)型で宣言します。

var // 「OLEのExcel操作術」各Tips共通で使用する変数宣言
  MsExcel : OleVariant;      // ExcelのOLE変数
  MsApplication: OleVariant; // アプリケーションのOLE変数
  WBook : OleVariant;        // ブックのOLE変数
  WSheet : OleVariant;       // シートのOLE変数

Excelを起動し、新規ファイルを作成するには次のように記述します。

  // Excel起動
  MsExcel := CreateOleObject('Excel.Application');
  MsApplication := MsExcel.Application;
  MsApplication.Visible := True;  // 処理を画面に見せない場合はFalseにする

  // 新規ファイルを作成
  WBook  := MsApplication.WorkBooks.Add ;
  WSheet := WBook.ActiveSheet;

  // Excelのセルにタイトル文字列を出力
  WSheet.Cells[1,3].Value := '受注データ';
  WSheet.Cells[2,1].Value := '受注番号';
  WSheet.Cells[2,3].Value := '得意先';
  WSheet.Cells[3,3].Value := '納品先';

ファイル名を指定して開くには次のようになります。

  // ファイル名を指定して開く
  WBook  := MsApplication.WorkBooks.Open('C:\AppTest\Test.xls');
  WSheet := WBook.ActiveSheet;

 

 


Excel終了時のロジックと別名保存

反対にExcelを終了する場合には、
以下のようにCloseメソッドでファイルを閉じてからQuitメソッドで終了させます。

  // Excel終了
  MsApplication.WorkBooks.Close;
  MsExcel.Quit;

この例の場合、ブックが変更されていると保存確認のダイアログが表示されます。
ダイアログを出さずに終了するには、次のようないくつかの方法があります。

 

【ダイアログを出さずに保存する】
Saveメソッドを使用することで、ダイアログを表示せずに上書き保存します。
その後、Excelを終了します。

  // Bookを上書き保存
  WBook.Save;
  // Excel終了
  MsApplication.WorkBooks.Close;
  MsExcel.Quit;

 

【ダイアログを出さず、保存も行わない】
同じようにダイアログを出さずに、保存も行わない場合には次のように記述します。

  // 保存の確認を行わない
  WBook.Saved := True;
  // Excel終了
  MsApplication.WorkBooks.Close;
  MsExcel.Quit;

 

【ダイアログを出さず、別名を付けて保存】
ダイアログを出さずに、特定の別名で保存する場合は次のように記述します。
Saveの代わりにSaveAsメソッドを使用し、引数FileNameに別名をフルパスで指定します。

  // 別名で保存
  WBook.SaveAs(FileName := 'C:\Test\ABC.xls');
  // Excel終了
  MsApplication.WorkBooks.Close;
  MsExcel.Quit;

 

 

 

別名を付けて保存する際のファイル形式について

上記例では「SaveAs」というメソッドを使って別名保存を行っていますが、
上記例のように、SaveAsの引数がFileNameのみの場合、
元ファイルと同じ形式で保存されます。

ここで拡張子だけを変更して保存すると、
拡張子だけが異なる同形式のままのファイルが保存されてしまいます。

※ そのファイルをExcelで開こうとすると警告が表示されます。
  XLSXLSXの形式の違いで警告になるパターンが最も多いかと思います。

この現象を改善するため、以下のように第2引数「FileFormat」を
追加することで、指定のファイル形式で保存することができます。

※ Excelのバージョンが対象のファイル形式での保存に対応している必要がございます。
※ DelphiやExcelのバージョンによっては、保存時にエラーになる場合もございます。その際はご容赦下さい。

  // 別名で保存
  WBook.SaveAs(FileName := 'C:\Test\ABC.xls');  // 拡張子を問わず、元のファイルと同形式
  WBook.SaveAs(FileName := 'C:\Test\ABC.xls',  FileFormat := 56); // Excel 97-2003 ブック
  WBook.SaveAs(FileName := 'C:\Test\ABC.xlsx', FileFormat := 51); // Excelブック
  WBook.SaveAs(FileName := 'C:\Test\ABC.xlsm', FileFormat := 52); // Excelマクロ有効ブック
  WBook.SaveAs(FileName := 'C:\Test\ABC.csv',  FileFormat := 6);  // CSV (コンマ区切り)
  WBook.SaveAs(FileName := 'C:\Test\ABC.pdf',  FileFormat := 57); // PDF
  WBook.SaveAs(FileName := 'C:\Test\ABC.xps',  FileFormat := 58); // XPSドキュメント

なお、SaveAsの引数を「FileName」「FileFormat」の順で記述する場合は、
 『 WBook.SaveAs(‘C:\Test\ABC.xlsx’, 51); 』
といった形で省略形で記述することも可能です。

 

 


シートの操作

ここからはシートの操作についてご紹介しましょう。

 

【シートの選択】
シート名を指定して行うには次のようになります。

  WBook.Sheets['Sheet2'].Select;

シートの番号を指定して行う場合は番号を指定します。
先頭のシート番号は1になりますので、2番目のシートであれば次のように指定します。

  WBook.Sheets[2].Select;

 

【シートの追加】
選択されているSheetの前に追加するには、追加メソッドを呼び出すだけです。

  WBook.WorkSheets.Add;

もし特定のシートの前に追加するのであれば、
上記の【シートの選択】で選択してから追加メソッドを実行します。

また一番最後にシートを追加するには、
シート数がWorksheets.Countから取得して次のように行います。
位置はbeforeやafterで指定できます。

  WBook.Worksheets.Add.Move(after := WBook.Worksheets[WBook.Worksheets.Count]);

反対に先頭にシートを追加するには、先頭のシート番号が1ですので次のようになります。

  WBook.Worksheets.Add.Move(before:=WBook.Worksheets[1]);

 

【シートの削除】
シート名またはシート番号を指定します。

  //(シート名で削除時)
  WBook.Sheets['Sheet3'].Delete;
  //(シート番号で削除時)
  WBook.Sheets[3].Delete;

このメソッドを呼ぶと確認メッセージがExcelから表示されますが、
DisplayAlertsを切り替えることでメッセージを出さずに行うこともできます。
DisplayAlertsをFalseにしたときには、メソッド実行後はTrueに戻しておかなければ
以後必要なメッセージも表示されなくなりますのでご注意下さい。

  MsApplication.DisplayAlerts := False;  // メッセージOFF
  WBook.Sheets['Sheet3'].Delete;         // シート削除
  MsApplication.DisplayAlerts := True;   // メッセージをONに戻す

 

【シートのコピー】
シート名またはシート番号を指定して行えます。
位置をbeforeやafterで指定できることも、シート追加の場合と同じです。

  //(シート名で指定の場合)
  WBook.Worksheets['Sheet2'].Copy(before:=WBook.Worksheets['Sheet1']);
  //(シート番号で指定の場合)
  WBook.Worksheets[2].Copy(Before:=WBook.Worksheets[1]);

 

 


シート数や最終行列の取得

ここからはExcelの持つ情報を取得する方法についてご紹介しましょう。

【シート数】
SheetsはそのBookに含まれるすべてのシートのオブジェクトで、
そのCountプロパティで取得します。

var
  cnt : integer;
begin
  cnt := WBook.Sheets.Count;

 

【シート名】
SheetオブジェクトにあるNameプロパティで取得できます。
現在選択中のシート名は次のようになります。

var
  nm : string;
begin
  nm := WBook.ActiveSheet.Name;

シート番号を指定してシート名を取得する場合には次のようになります。

  nm := WBook.Sheets[1].Name;

 

【最終列と最終行】
UsedRange
を使用するとデータが入力されている領域を調べることができます。
最終列と最終行はそれぞれColumns.CountとRows.Countで取得できます。

var
  r,c : Integer;
begin
  c := WSheet.UsedRange.Columns.Count;
  r := WSheet.UsedRange.Rows.Count;

 

 


DBGridの表示内容をExcelに出力する

下記プログラムサンプルでは、
あらかじめDBGridに何らかのデータが表示されていることを前提とし、
Button1をクリックすると、グリッド内容がExcelに出力されます。

※クリップボードを使用するため、uses節に「Vcl.Clipbrd」が必要です。(XE以前では「Clipbrd」)
※クリップボードを使用するため、処理中に他の用途でクリップボードを使用するとエラーになります。

procedure TForm1.Button1Click(Sender: TObject);
const
  TAB_STR  = #9;         // TAB文字
  CRLF_STR = #13#10 ;    // 改行(CRLF)文字
var
  i: Integer;
  strText: String;
  MsExcel, MsApplication, WBook, WSheet : OleVariant; // Excelの各OLE変数
  ADataSet: TDataSet;
begin
  // 文字列変数の初期化
  strText := '';

  // DBGridに関連付けされているDataSetを変数に代入
  ADataSet := DBGrid1.DataSource.DataSet;

  // DataSetのオープン
  if not ADataSet.Active then ADataSet.Active := True; 

  // DBGridに表示されているフィールドの列名を取得し、文字列に代入
  for i := 0 to DBGrid1.Columns.Count - 1 do
  begin
    strText := strText + DBGrid1.Columns[i].Field.DisplayLabel + TAB_STR;
  end;
  strText := strText + CRLF_STR;
  // DBGridに表示されているデータを取得し、文字列に代入
  ADataSet.First;
  while not ADataSet.Eof do  // 最終レコードになるまで繰り返し
  begin
    for i := 0 to DBGrid1.Columns.Count - 1 do
    begin
      strText := strText + DBGrid1.Columns[i].Field.DisplayText + TAB_STR;
    end;
    ADataSet.Next;
    strText := strText + CRLF_STR;
  end;

  // クリップボードに取得した文字列をコピー
  Clipboard.Clear;
  Clipboard.AsText := strText;

  // エクセルを起動し、クリップボードの内容を貼り付け
  MsExcel := CreateOleObject('Excel.Application');
  MsApplication := MsExcel.Application;
  MsApplication.Visible := False;  // 処理を画面に見せない場合はFalseにする

  WBook  := MsApplication.WorkBooks.Add ;
  WSheet := WBook.ActiveSheet;
  WSheet.Cells[1, 1].Select;
  WSheet.Paste;
  WSheet.Cells[1, 1].Select;

  // エクセルを表示
  MsExcel.Visible := True;

  // クリップボードのクリア
  Clipboard.Clear;
end;

 


(本記事は、以下の資料をもとに最新情報を含めた再構成をしております。)

  • ミガロ.情報マガジン「MIGARO News!!」
    • Vol.114 2010年5月号より(バインディングとExcel起動時のロジック)
    • Vol.115 2010年6月号より(Excel終了時のロジックと別名保存)
        (別形式保存については新規書き下ろし)
    • Vol.119 2010年10月号より(シートの操作)
    • Vol.120 2010年11月号より(シート数や最終行列の取得)
    • Vol.027 2003年4月号より(DBGridの表示内容をExcelに出力)