○ エクセルと他のプログラムの連帯

エクセルを開いた状態でセルを他のプログラムから書き換えたり書き込んだりできるとなんだか色々出来そうです。
そこで実現する方法を考えていきたいと思います。

まずは、エクセルVBAでのタイマーを作成しました。

Option Explicit

Dim Timer As Date

Sub TimerStart()
    Range("A1") = Format$(Now, "yy年mm月dd日 hh時mm分ss秒")
    Timer = DateAdd("s", 1, Now)
    Call Application.OnTime(Timer, "TimerStart")
End Sub

Sub TimerStop()
    Call Application.OnTime(Timer, "TimerStart", , False)
End Sub

エクセルのシートのVBAを開いて標準モジュールを追加してこのコードを貼り付けます。
その後、エクセルのメニューからツール→マクロ→マクロ を開いてTimerStartを実行すると1秒毎にセルのA1が更新されます。
タイマーを停止するにはTimerStopを実行します。

タイマーの動作中はカーソルがチラチラするのが難点です。
→ office2000ではチラチラしましたが、もう少し新しいバージョンの2003だとチラチラしませんでした。
共有メモリを使ってデータを連帯していこうと思います。

共有メモリを使ったアプリケーション間の通信

この方法を使って作成するとします。
実現するのに必要な事柄は、共有メモリのデータ構造を決める事です。
そこで、一つの文字列を改行区切り文字 CRLF を使用して分割して、最初の5個のデータはエクセルの読み込むデータ、次の5個はエクセルの書き込むデータとします。

上記仕様に従って作成したVBAのコード
Option Explicit

Private Declare Sub SetString Lib "c:\shard.dll" (ByVal str As String)
Private Declare Function GetString Lib "c:\shard.dll" () As String

Dim Timer As Date

Sub TimerStart()
    Dim str As String
    Dim ar As Variant
    str = GetString()
    ar = Split(str, vbCrLf)
    If 5 < UBound(ar) Then
        Range("B2") = ar(0)
        Range("B3") = ar(1)
        Range("B4") = ar(2)
        Range("B5") = ar(3)
        Range("B6") = ar(4)
        str = ar(0) + vbCrLf + ar(1) + vbCrLf + ar(2) + vbCrLf + ar(3) + vbCrLf + ar(4) + vbCrLf
        str = str + CStr(Range("C2")) _
        + vbCrLf + CStr(Range("C3")) _
        + vbCrLf + CStr(Range("C4")) _
        + vbCrLf + CStr(Range("C5")) _
        + vbCrLf + CStr(Range("C6")) + vbCrLf
        On Error Resume Next
        SetString (str)
        On Error GoTo 0
    End If
    Timer = DateAdd("s", 1, Now)
    Call Application.OnTime(Timer, "TimerStart")
End Sub

Sub TimerStop()
    On Error Resume Next
    Call Application.OnTime(Timer, "TimerStart", , False)
End Sub
赤文字部分ではSetStringで謎のエラーが出るためエラー処理をしています。
VB6でも同様なのですが、インタプリタで動作させるとなぜかエラーが発生するようです。
VB6では実行ファイルにするとエラーは出ませんでした。

このプログラムではセルのB2〜B6に共有メモリの内容を受け取り、セルのC2〜C6の内容を書き込みます。
ツール→マクロ→マクロ を開いてTimerStartを実行してタイマーを動作させないと動きません。

しかし、タイマーの動作中はエクセルのコピーアンドペーストがうまく行かなかったりします。
その時は、ツール→マクロ→マクロ を開いてTimerStopを実行してタイマーを止める必要があります。
エクセルを開いた時に自動的にタイマーを起動させるには次のようにします
Private Function Auto_Open()
    Call TimerStart
End Function


動作を確認するために、共有メモリに書き込むエクセルに対応したVB6のプログラムを作成しました。
excel_shared.zip
実行するには、Cドライブ直下に shard.dll をコピーします。
次に、エクセルの表を開いて、メニューからツール→マクロ→マクロ を開いてTimerStartを実行します。
次にVB6で作成した、Project1.exeを実行して、書き込みボタンを押すと動作開始してエクセルの表に読み書きができるはずです。




動作確認に使用しているVB6のコードも置いておきます
Text1 と Label1 はコントロール配列で各5個をフォームに張り付けています。
タイマーのインターバルは500に設定しています。
フォームに書き込みボタンを張り付けて以下のコードを書き込んで作成しています。

Private Declare Sub SetString Lib "c:\shard.dll" (ByVal str As String)
Private Declare Function GetString Lib "c:\shard.dll" () As String

Private Sub Command1_Click()
    Call SetString(Text1(0).Text + vbCrLf _
    + Text1(1).Text + vbCrLf _
    + Text1(2).Text + vbCrLf _
    + Text1(3).Text + vbCrLf _
    + Text1(4).Text + vbCrLf _
    )  '共有メモリに書き込み
End Sub

Private Sub Timer1_Timer()
    Dim str As String
    Dim ar As Variant
    ar = Split(GetString(), vbCrLf)
    If 9 <= UBound(ar) Then
        Label1(0).Caption = ar(5)
        Label1(1).Caption = ar(6)
        Label1(2).Caption = ar(7)
        Label1(3).Caption = ar(8)
        Label1(4).Caption = ar(9)
    End If
End Sub


▼ セルの値変更方式から関数方式へ
セルの値を更新したり取得する場合はうまく動作しました。
次にExcelの読み書きの関数を作成してもうまく行くのではないかと思い実験してみました。
標準モジュールに次のようにpublicな関数のコードを書き込むとエクセルで使える関数が作成できます。
Public Function readData(index As Integer) As String
    If readArea < index Then
        readData = str_ar(index)
    Else
        readData = "NG"
    End If
End Function

Public Function writeData(index As Integer, data As String) As String
    If readArea <= index And writeArea > index Then
        str_ar(index + readArea - 1) = data
        writeData = CStr(index) + " Write OK"
    Else
        writeData = CStr(index) + " Write NG"
    End If
End Function
しかしながら、この方法ではエクセルのセル自体の計算ができないため断念しました。
セル自体になんらかのアクションを与えないと再計算がされないようです。


▲トップページ