C#からExcel VBAをRun

 通常交信とコンテストのログに使っているjg6jav_log.xlsmの周波数とモードの情報は、C#で作った無線機のコントローラーIC7851RCから取得している。従前は、Clipboardを使って取得して記入していたがそれがうまくいかない事例が最近頻繁に発生して困っている。なのでなんとか直接取得できないかいろいろ調べていたらC#からExcelのVBA標準モジュールを起動できることが判った。渡したい情報を引数にしてしまえば目的を果たせる。その情報をどう扱うかは、Excel VBA側に目的シートの何処にそれらを情報を転記するかなどの処理を任せることで解決した。正直Clipboardを使った方が扱い易く動作も速かったように思うけれどもClipboardが時々正常に動作せず情報が転記されないという問題は解決した。

C# IC7851RCから情報をExcelへ渡す

// -- IC7851RC ---
using Microsoft.VisualBasic;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;

        //
        //  EXCELへ情報転記 Run Excel VBA
        private void Send_RigInfo(int RunNr, bool Boo = false,  string callsign = "")
        {
            try
            {
                Process[] ps = Process.GetProcessesByName("Excel");
                if (ps.Length < 0) return;
                Interaction.AppActivate(ps[0].Id);
                var XLS = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
                var WB = (Excel.Workbook)XLS.ActiveWorkbook;
                if (WB.Name != "jg6jav_log.xlsm") return;
                var Sh = (Excel.Worksheet)WB.ActiveSheet;
                if (Sh.Name != "Contest" && Sh.Name != "QSO LOG") return;
                string CallName = RunNr switch
                {
                    1 => "RcvRigInfo",
                    2 => "StatusCheck",
                    _ => ""
                };
                XLS.Run(CallName, Boo, RI.Freq, LogMode, RI.RFP, callsign);
                Marshal.ReleaseComObject(XLS);
            }
            catch (System.Exception ex)
            {
                StatusLabel.Text = ex.Message;
            }
        }
       //
        // Excel から SendKey CTRL+I or CTRL+W で作動
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            Keys KeyTop = e.KeyCode;
            if (e.Control)
            {  // [ctrl]+
                switch (KeyTop)
                {
                case Keys.I:
                    Send_RigInfo(1, true);
                    break;
                case Keys.W: // Rig Info to Excel
                    Send_RigInfo(1,false);
                    break;
                }
            }
        }

Excel側からリクエストがなくても運用バンドが変更になったらこのメソッドはNoPost=trueで実行される。これで現在運用中のバンドが把握できるようになった。仔細は割愛するがIC7851RC内からはKeyDownイベントと周波数が変わった時に発動するメソッドとCW送出メソッド内でもこのメソッドは条件により実行される。

情報受け取りExcel VBA

'---// IC7851RCからRun実行により情報取得//---
Private Sub RcvRigInfo(NoPost As Boolean, rFreq As Variant, rMode As Variant, rPower As Variant, rCallsign As Variant)
    Dim aRow As Long
    Dim Sw As Boolean
    rigFreq = rFreq
    rigMode = rMode
    rigPower = rPower
    rigBand = Band(rigFreq)
    If NoPost Then Exit Sub
    RcvInfo = True
    aRow = PostingCell.Row
    If Application.EnableEvents Then
        Sw = True
        Call AppLock
    End If
    Select Case ActiveSheet.Name
    Case "Contest"
        If rCallsign <> "" Then
            Call StatusCheck(False)
            Cells(aRow, 6).Value = rCallsign
        End If
        With Cells(aRow, 4)
            If .Value <> rigFreq Then .Value = rigFreq
        End With
        With Cells(aRow, 5)
            If .Value <> rigMode Then .Value = rigMode
        End With
    Case "QSO LOG"
        If rCallsign <> "" Then Cells(aRow, 4).Value = rCallsign
        Cells(aRow, 7).Value = rigFreq
        Cells(aRow, 8).Value = rigMode
        Cells(aRow, 9).Value = rigPower
    End Select
    If Sw Then AppReset
End Sub
'
'---// IC7851RCからRun実行により情報取得とConest Run/S%P状態切り換え //---
Sub StatusCheck(Sw As Boolean, Optional rFreq As Variant = 0, Optional rMode As Variant = 0, _
                Optional rPower As Variant = 0, Optional Void = "")
    If rFreq > 0 Then
        rigFreq = rFreq
        rigMode = rMode
        rigPower = rPower
    End If
    With ActiveSheet
        If .Name <> "Contest" Then
            Exit Sub
        End If
        With .CheckBox1
            If .Value = Sw Then Exit Sub
            .Value = Sw
        End With
    End With
End Sub
'
'---// IC7851RCへ情報取得要求 SKey "^W"(STRL+W)or "^I"(CTRL+I) //
Sub GetRigInfo(SKey As String)
    On Error Resume Next
    Set PostingCell = ActiveCell
    AppActivate "IC-7851"
    SendKeys (SKey)
    AppActivate Application.Caption
    On Error GoTo 0
End Sub

VBAからC#のメソッド起動は、IC7851RCにSendKeysで行い目的のメソッドを実行させる。コンテストでは、交信最終CWメッセージ終端にトリガー文字列を含ませることでIC7851RCのメソッドが実行されるようにした。

コメント