2014年7月11日 星期五

BCB透過DDE連結EXCEL

基於上一篇的DDE概念匯整後, 在此進一步整理BCB如何透過DDE讀取及設定EXCEL的儲存格資料

通訊架構

EXCEL為DDE server, BCB為DDE client, 以BCB讀取及設定EXCEL SHEET1內D1資料格的資料



BCB物件

各將Systme下的DdeClientConvDdeClientItem物件放置From1內

BCB程式

void __fastcall TForm1::FormCreate(TObject *Sender)
{
    // 建立及打開一條連線
    DdeClientConv1->SetLink("Excel", "Sheet1");
    DdeClientConv1->OpenLink();
 
    // 指定到r1c4(D1資料格, r代表row, c代表column)
    DdeClientItem1->DdeConv=DdeClientConv1;
    DdeClientItem1->DdeItem="r1c4";

    Memo1->Text = DdeClientItem1->Text;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::DdeClientItem1Change(TObject *Sender)
{
    Memo1->Text = DdeClientItem1->Text;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    DdeClientConv1->PokeData("r1c4", Edit1->Text.c_str());
}

TIPS


  1. 通訊連線前, DDE server需先執行, 也就是Excel要先啟動
  2. 先以DdeClientConv1用Service及Topic建立及打開一條通至EXCEL SHEET1的連線
  3. 將DdeClientItem1的Item指定到r1c4(D1資料格), 如此DdeClientItem1即與D1資料格的資料同步
  4. 用Poke的方式, 將資料由BCB寫入EXCEL


問題

但若以相同方式新增DdeClientItem2要讀取r2c4(D2資料格), DdeClientItem2卻無法與D2資料格的資料同步, why???
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    DdeClientConv1->SetLink("Excel", "Sheet1");
    DdeClientConv1->OpenLink();

    DdeClientItem1->DdeConv=DdeClientConv1;
    DdeClientItem1->DdeItem="r1c4";
    Memo1->Text = DdeClientItem1->Text;

    DdeClientItem2->DdeConv=DdeClientConv1;
    DdeClientItem2->DdeItem="r2c4";
    Memo2->Text = DdeClientItem2->Text;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::DdeClientItem1Change(TObject *Sender)
{
    Memo1->Text = DdeClientItem1->Text;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::DdeClientItem2Change(TObject *Sender)
{
    Memo2->Text = DdeClientItem2->Text;
}
//---------------------------------------------------------------------------

折衷方式

void __fastcall TForm1::FormCreate(TObject *Sender)
{
    DdeClientConv1->SetLink("Excel", "Sheet1");
    DdeClientConv1->OpenLink();

    DdeClientItem1->DdeConv=DdeClientConv1;
    DdeClientItem1->DdeItem="r4c4";
    DdeClientItem1->DdeItem="r3c4";
    DdeClientItem1->DdeItem="r2c4";
    DdeClientItem1->DdeItem="r1c4";

    Memo1->Text = DdeClientItem1->Text;

    Memo2->Text = DdeClientConv1->RequestData("r2c4");
    Memo3->Text = DdeClientConv1->RequestData("r3c4");
    Memo4->Text = DdeClientConv1->RequestData("r4c4");
}
//---------------------------------------------------------------------------

void __fastcall TForm1::DdeClientItem1Change(TObject *Sender)
{
    Memo1->Text = DdeClientItem1->Text;

    Memo2->Text = DdeClientConv1->RequestData("r2c4");
    Memo3->Text = DdeClientConv1->RequestData("r3c4");
    Memo4->Text = DdeClientConv1->RequestData("r4c4");
}
//---------------------------------------------------------------------------

  • 因為DdeClientItem1已經在TForm1::FormCreate連結過EXCEL的D1~D4, 所以當D1~D4的資料有變動時, TForm1::DdeClientItem1Change也會跟著觸發
  • 此時再以RequestData重新讀取其他資料即可
  • 這種作法在連結的資料量大時, 或許會有程式RequestData通訊負載量過大的疑慮, 此點若有實做的機會時, 再補上說明

沒有留言:

張貼留言