尾崎 浩司
株式会社ミガロ
システム事業部 システム2課

連携で広がるDelphi/400活用術
開発の効率を上げるには既存のいろいろな仕組みと「連携」することが最もよい手段だ。
ここでは、Delphi/400 と他の仕組みとを連携する手法を具体的な手順を含め紹介する。

略歴
1973 年 8 月 16 日 生
1996 年三重大学 工学部卒
1999 年 10 月株式会社ミガロ入社
1999 年 10 月システム事業部配属●はじめに●COM を使ったアプリケーション連携●Web で提供される情報との連携●さいごにはじめに
Delphi/400 は、IBM i を使用するアプリケーションを開発するのに、最適な開発ツールである。と同時に、制約のない Windows アプリケーションを構築するのにも、最適な開発ツールである。

現在の仕事内容
入社以来、主に Delphi/400 を利用した受託開発を担当している。

あろう。データベースから取得したデー間接的に IBM i のデータを使用するこタを Excel に出力する、ソース 1 のよとも可能になるというわけである。

うなアプリケーションを、私もたびたび開発している。
【ソース 1】

COM
こ の よ う な 連 携 を 実 現 す る の が、それでは、COM として情報を提供するサーバーはどのようにして開発するのか、見ていこう。

適用業務において可能性は無限に広が「COM」と呼ばれる技術である。COM

まず、新規プロジェクトを作成する。

るが、1 から全てを構築するとなると工はコンポーネント・オブジェクト・モデ

そして、Delphi のメニューから［ファ数がいくらあっても足りないであろう。

ルの略で、アプリケーションの持つ機能イル］→［新規作成］→［その他］を選開発の効率を上げるには、すでに用意さをオブジェクト化し、別のアプリケー択し、選択カテゴリ「ActiveX」から「オーれているいろいろな仕組みと「連携」をションから容易に利用できるようにするトメーションオブジェクト」を選択する。

行うことが最適な手段だ。

技術である。

【図 1a】

本稿では、Delphi/400 と他の仕組み

こ の COM と い う 技 術 に よ り、すると、ウィザードが始まるので、とを連携する手法を、具体的な手順を示

Delphi/400 からいろいろなアプリケー「CoClass 名」欄にクライアントがアクしながら紹介していこう。これをきっかションの機能を使用することが可能になセスするためのクラス名を入力する。こけに、皆様の開発のバリエーションが広る。さらに、他のアプリケーションに機こでは "AS400Infomation" としよう。
【図がれば幸いである。

能を提供するプログラムを構築すること1b】も可能である。

80

COMサーバーの開発

ウィザードが終了すると「タイプライCOMを使ったアプリケーション連携

例えば、IBM i から情報を取得するロブラリ」と呼ばれるインターフェースをジックを、Delphi/400 で開発し、COM定義する画面が表示される。
【図 1c】とすることで、他のツールからの利用がこの画面で、外部に提供するプロパ「連携」というとまず思いつくのが、可能になる。そうすることでエンドユーティあるいはメソッドを定義するわけだ。

業務で最も使用する Excel との連携でザーは、Excel や Access の VBA 等で、"IAS400Infomation" をクリックする図1a

図1b

図1c81

と、メソッドおよびプロパティの新規作力し、プログラムを実行する。
（反対にきると思うので、ぜひ皆様も新たな連携成が選択可能になるので、必要に応じた

レ ジ ス ト リ を 解 除 す る 場 合、「/にチャレンジしてほしい。

インターフェース定義を行う。メソッドunregserver」
を指定して実行する）。
【図であれば名前を定義し、プロパティであ2】

れば名前と属性（タイプ）を定義する。

プログラムを実行するとどうなるか。

Webで提供される情報との連携

ここでは、メソッドとして "GetData"

実行後、画面は何も表示されず、そのまを定義し、［読み込み ¦ 書き込み］プロ

まプログラムが終了するはずだ。ここでインターネットには多彩な情報が公開

パティとして "CustNo"（タイプは数字は、レジストリへの登録が行われるだけされている。ふだん皆様もいろいろ利用

属性［Long］）と［読み込み専用］プロだからである。つまり、これで COM 登されているだろう。これらの情報とシスパティとして "CustName"（タイプは文録が完了となり、他のアプリケーションテムとが連携すれば、便利になるのでは

字 属 性［BSTR］） を 定 義 す る。
【図から利用可能になる。と考えたことはないだろうか？

1d】。

実際にこの作成したプログラムが動作

例えば、システムに登録されている得インターフェースの定義が終了した

するのは、COM を利用するクライアン

意先マスターの住所情報から、地図のら、「ソースコード更新」というボタン

トがオブジェクトを生成したときとな

Web サイトが表示できたり、出張精算を押してみよう。するとソース 2 のようる。

画面で入力した駅名から路線検索ができなソースコードが自動作成される。あとは、そこに仕様に応じたユーザーコードを追加すればよい。
【ソース 2】

COMサーバーのサンプル

COMを使用するクライアント
では、COM を使用するクライアントはどうなるか。今回は、Excel から利用してみよう。

たりするとたいへん便利と思われる。

Webサービス
世の中には一般に「Web サービス」と呼ばれる仕組みがあり、SOAP と呼今回は、"CustNo" プロパティに得意Excel を起動し、シートの中に得意先ばれるプロトコルを使用すると完全な連先コードを指定し、GetData メソッドコードのセルと得意先名のセル、それか携 が 可 能 だ。 ま た、Delphi/400 か らを呼び出すことにより、データベースから検索用のボタンを用意する。
【図 3】

Web サービスを使用する仕組みも用意

ら得意先マスターを検索し、取得した得そして、ボタンのクリックに対するイ

意先名を結果として CustName プロパベント処理として、次のような VBA

ティにセットする COM サーバーを作成コードを入力する。
【ソース 5】してみた。
【ソース 3】

されている。
しかし、これらを使いこなすには、SOAP や XML 等の知識が必要になって完成した Excel を「マクロを有効」くるため、少し敷居が高いのも事実であこのサンプルでは、新規プロジェクトにして実行する。画面上で得意先コードる。ゆえに Web の連携は難しいと考え作成時にあらかじめ用意されているを入力した後、検索ボタンを押すことで、ていないだろうか？ 実は、そこまでのフォーム（ここでは frmMain と命名）に、データベースから検索された得意先名がことをしなくても、ちょっとした連携でDataBase コンポーネントと Query コセットされるだろう。
【図 4】あれば容易に実現可能である。

ンポーネントを貼り付け、データベース

ここで、Excel 上で作成したソース 5

接続定義ならびにデータ抽出用の SQLのソースをよく見てみよう。言語の違いの定義を行っている。

は あ る が、ソ ー ス 1 で、Delphi か ら、インターネットエクスプローラで、ア

郵便番号検索Webアプリケーション

なお、今回作成している COM オブ

Excel オブジェクトを生成して使用した

ドレス欄に以下のように入力してほしジェクトは、データベースへのアクセスのと似ていないか。同じように、Excelい。

機能のみを持ったものとなる。
そのため、から、今回作成した COM のオブジェク画面（フォーム）は表示不要である。

トを作成し、プロパティおよびメソッド

http://search.post.japanpost.jp/cgi-を使用しているのがわかる。

zip/zipcode.php?zip=5560017

このような COM オブジェクトを作成する場合、プロジェクトファイルのソー
ス コ ー ド を 表 示 し、"Application.

今回は、単純なマスター検索を行う連

これは、日本郵便の郵便番号検索

ShowMainForm := False;" の 1 行を追携ではあるが、この COM オブジェクトWeb アプリケーションである。この加して完成となる。
【ソース 4】を使用するユーザーは、IBM i のデータURL から、郵便番号 556-0017 地域の所構造を意識せずにデータにアクセスでき在地がわかる。
【図 5】

COM登録

82

る。

完成したプログラムを他のアプリケー

つまり、IBM i 上のデータをそのまま

このように、一般的な Web アプリケー

ションより利用可能にするためには、レ公開すると機密上よくない場合にも、こションは、Web ブラウザから Web ア

ジストリ登録が必要になる。のような仕組みを検討することにより、プリケーションに問い合わせを行うことで動作する。

Delphi/400 開発環境下でレジストリ必要に応じた項目のみを公開できる。

登録を行う場合は、Delphi のメニュー

ユーザーが、IBM i のデータを、自由にこ の と き の 問 い 合 わ せ 方 法 に は、から［実行］→［実行時引数］を選択し、安全に利用できるのではないだろうか。

GET メソッドと POST メソッドという「パラメータ」欄に「/regserver」と入それ以外にもいろいろな連携が実現で2 種 類 が 存 在 す る の だ が、 そ の 中 で

図1d

図2

図383

GET メソッドは、URL の中に問い合わ

URL エンコードはどうすればよいか？

せを記載するのが特徴だ。先ほどの郵便実は HTTPApp というユニットを uses

番号検索の場合、"?zip=5560017" とい節に追加すると、HTTPEncode 関数がう部分が問い合わせクエリーとなる。

使用できるようになり、これを使うと容つまり、GET メソッドで問い合わせ易に URL エンコードが可能である。

することが可能な Web アプリケーショ

なお、URL エンコードの際には、対ンは、変数を含む URL を渡すだけで連象の Web サイトが使用する文字コード携が可能になるのである。

体系によりさらに変換が必要な場合もあ

連携プログラムの作成
それでは、簡単な連携プログラムを作成してみよう。
まず、新規プロジェクトを作成し、Button、Edit そ し て WebBrowser コ
ンポーネントを貼り付ける。
【図 6】る。先ほどの Google 検索サイトでは、UTF-8 という文字コード体系を使用しているので、このような場合、さらにAnsiToUtf8 関数を使うとよい。

Google検索を実現した
Delphi/400連携プログラム

そして、ボタンコンポーネントの先ほど作成した日本郵便の検索プログ

Click イ ベ ン ト に、 処 理 を 記 述 す る。

ラムを改良してみよう。ソース 7 は、【ソース 6】

Google 検索を実現した Delphi/400 連

では、完成したプログラムを実行して携プログラムとなる。
【ソース 7】

みよう。先ほどのブラウザ画面からの表完成したプログラムを実行すると、示結果と同じ内容が、Delphi のフォー

Delphi の画面で指定したキーワードをム上に表示されることが確認できる。
【図もとに Google 検索を行い、結果が画面7】に表示されていることがわかる。
【図 9】

このように Web 情報への連携はとても簡単である。

Google検索

さいごに
このように、単純に Web サイトに対もう 1 つ見てみよう。先ほどと同じよして問い合わせし、結果を画面に表示すうに、インターネットエクスプローラ上るだけの「連携」であった。とはいえ、に下記アドレスを入力してほしい。

皆様が開発するアプリケーションにおいて、入力した値がそのままパラメータとhttp://www.google.co.jp/search?num

して利用できるようになれば、いろいろ=30&q=%E3%83%9F%E3%82%AC%Eな呼び出しが可能になるだろう。

3%83%AD

今回紹介した以外にも、Get メソッドを使用した検索可能なサイトが多数存在

これは皆様おなじみの Google 検索である。検索キーワード " ミガロ " で、結果が 30 件表示されている。
【図 8】
このサイトも先ほどと同じように、Get メソッドで問い合わせを行ってい

例えば、http://ready.to/search/list/というサイトでは、ブラウザから直接呼び出せるサイトが紹介されている。参考にしてはいかがだろうか。

る。"q=%E3%83…" のところを見てほアイデアしだいでは便利な連携が可能しい。実は、この部分は「ミガロ」といと思われるので、ぜひともいろいろチャうキーワードで検索しなさいという問いレンジしていただきたい。

合わせを表しているのだが、符号化されているのがわかるであろう。
つまり、Get メソッドで問い合わせする際には、通常 2 バイト文字等は利用できないのである。加えて、このように空白文字や特殊記号、日本語等の全角文字を符号化するルールを「URL エンコード」と呼んでいる。
では、Delphi/400 から使用する際に、84する。

M

図4

図5

図685

図7

図8

図986

ソース1
uses ComObj;//Excel にデータ出力
with Table1 do
begin
Active := True;

procedure TForm1.Button1Click(Sender: TObject);

try

var

i := 0;

MsExcel, MsApplication, WBook, WSheet: OleVariant;First;

i: integer;

while not eof do

begin

begin

//Excel 起動

WSheet.Cells[i+3,1].Value := FieldByName('CUSTNO').

MsExcel := CreateOleObject('Excel.Application');

AsInteger;

MsApplication := MsExcel.Application;

WSheet.Cells[i+3,2].Value :=MsApplication.Visible := True;

FieldByName('COMPANY').AsString;

WBook := MsApplication.WorkBooks.Add;

WSheet.Cells[i+3,3].Value := FieldByName('ADDR1').

WSheet :=WBook.ActiveSheet;

AsString;//Excel にタイトル出力

Next;

WSheet.Cells[1,3].Value := ' 得意先マスター一覧表 ';i := i + 1;

WSheet.Cells[1,3].Font.Size := 15;

end;

WSheet.Cells[2,1].Value := ' 得意先コード ';finally

WSheet.Cells[2,2].Value := ' 得意先名 ';Active := False;

WSheet.Cells[2,3].Value := ' 住所 ';end;

WSheet.Cells[2,1].Font.Bold := 'True';end;

WSheet.Cells[2,2].Font.Bold := 'True';end;

WSheet.Cells[2,3].Font.Bold := 'True';

ソース2

function TAS400Infomation.Get_CustName: WideString;
begin

unit Unit1;
end;{$WARN SYMBOL_PLATFORM OFF}function TAS400Infomation.Get_CustNo: Integer;interface

begin

uses

end;

ComObj, ActiveX, AS400Info_TLB, StdVcl;
procedure TAS400Infomation.GetData;
type

begin

TAS400Infomation = class(TAutoObject,IAS400Infomation)end;

protected
function Get_CustName: WideString; safecall;procedure TAS400Infomation.Set_CustNo(Value: Integer);function Get_CustNo: Integer; safecall;begin

procedure GetData; safecall;procedure Set_CustNo(Value: Integer); safecall;

end;

end;

initialization
TAutoObjectFactory.Create(ComServer,implementation

TAS400Infomation, Class_AS400Infomation,
ciMultiInstance, tmApartment);

uses ComServ;

end.

87

// 得意先名を取得する

ソース3

with frmMain.Query1 do----- << ここまで省略 >> ------

begin// クエリーを閉じる
Active := False;

type
TAS400Infomation = class(TAutoObject,IAS400Infomation)// 得意先コードパラメータに得意先コード内部値を代入

privateする// 内部変数

ParamByName('CUSTNO').AsInteger := FCustNo;

FCustNo: Integer;// 得意先コード

FCustName: String;// 得意先名// クエリーを実行する

protected

Active := True;

function Get_CustName: WideString; safecall;tryfunction Get_CustNo: Integer; safecall;First;

procedure GetData; safecall;procedure Set_CustNo(Value: Integer); safecall;// データが存在しない場合、エラーとする

end;

if Eof and Bof thenraise Exception.Create(' 指定された得意先コードはimplementation存在しません。');

uses ComServ, MainFrm, SysUtils, Dialogs, DBTables;// 取得結果を得意先名内部値に代入する
FCustName := FieldByName('CUSTNM').AsString;function TAS400Infomation.Get_CustName: WideString;

finally

begin// クエリーを閉じる// 得意先名の内部値を渡す

Active := False;

Result := FCustName;

end;

end;

end;
exceptfunction TAS400Infomation.Get_CustNo: Integer;// エラーメッセージの表示

begin

on E: Exception do// 得意先コードの内部値を渡す

begin

Result := FCustNo;

MessageDlg(E.Message, mtError, [mbOK], 0);

end;

end;
end;

procedure TAS400Infomation.GetData;

end;

begin
try

procedure TAS400Infomation.Set_CustNo(Value: Integer);// 得意先コードが指定されない場合、エラーとする

begin

if FCustNo = 0 then// パラメータを内部値にセットし、得意先名を初期化する

raise Exception.Create(' 得意先コードが指定されていまFCustNo := Value;せん。');

FCustName := '';end;// クエリーを使用し、得意先コードをキーに得意先マスターを検索し、88----- << 以下省略 >> -----

ソース4
Application.Initialize;
Application.CreateForm(TfrmMain, frmMain);
Application.ShowMainForm := False; // ( 追加 ) メイン
フォームを表示しない
Application.Run;' 取引先コードのセット

ソース5

lngCustNo = ActiveSheet.Range("C2").ValueobjAS400Info.CustNo = lngCustNo

Option Explicit' データの取得 ( メソッドの実行）
Private Sub CommandButton1_Click()Dim objAS400Info As Object '---- 得意先情報取得オブジェクトDim lngCustNo As Long

objAS400Info.GetData' 取得した得意先名のセット
ActiveSheet.Range("C7").Value = objAS400Info.

'---- 得意先コード

CustName' 得意先情報取得オブジェクトの生成' オブジェクトの解放

Set objAS400Info = CreateObject("AS400Info.

Set objAS400Info = Nothing

AS400Infomation")
End Sub

ソース6

zipcode.php?zip=';sURLText := sURLText + Edit1.Text;

procedure TForm1.Button1Click(Sender: TObject);var// 問い合わせを実行し、結果を WebBrowser コンポーネン

sURLText: String;

トに表示

begin

WebBrowser1.Navigate(sURLText);// URL 文の作成

end;

sURLText := 'http://search.post.japanpost.jp/cgi-zip/

ソース7
uses HTTPApp; // HTTPApp ユニットを追加する

sURLText := 'http://www.google.co.jp/
search?num=30&q=';
sURLText := sURLText + HTTPEncode(AnsiToUtf8(Edit1.
Text));

procedure TForm1.Button1Click(Sender: TObject);var// 問い合わせを実行し、結果を WebBrowser コンポーネン

sURLText: String;

トに表示

begin

WebBrowser1.Navigate(sURLText);// URL 文の作成

end;

89