Quantcast
Channel: The Official Scripting Guys Forum! forum
Viewing all articles
Browse latest Browse all 15028

Subscribe to event within excel from powershell

$
0
0

I have been trying excel automation with powershell and have been trying to subscribe to an events within excel. The only way I have been able to accomplish this by creating an in memory PSWrapper type. I include the PS code example below. I have 2 problems.

  1. Is there a better/easier way to subscribe to excel events in excel automation with powershell?
  2. In the course of writing the example another problem came to light. The messagebox needs to appear on top of excel, unfortunately the MessageBoxOptions.DefaultDesktopOnly does not seem to work when used directly in powershell. Only the  RightAlign seems to work displaying a messagebox hidden beneath excel, DefaultDesktopOnly causes the messagebox not to display at all.

Can someone can add further light on this? Presently I am assuming when it comes to Excel automation the best approach would be to use some sort of .net wrapper.

With the PS code below run it from ps as -:start powershell.exe -ArgumentList "-noprofile","-noexit","-file [your file name]", otherwise you will not see all the console output and any message boxes.

I look forward to a reply.

BEGIN
{
 $OldCulture = Get-Culture
 set-culture -CultureInfo en-US



$source = @"
using System;
using Interop = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.Windows;



namespace ExcelWrapper
{
    public class PSWrapper
    {
        private Interop._Application excel = new Interop.Application();
        private bool visible = false;
        private Interop.Workbook workBook = null;

        

        public  Interop.WorkbookEvents_BeforeCloseEventHandler Del_onClose;
        public delegate void ExcelWorkbookCloseEventHandler();
        public event ExcelWorkbookCloseEventHandler OnExcelWorkbookCloseEvent;
       
        public Interop._Application Excel
        {
            get { return excel; }
        }

        public bool Visible
        {
            get { return Visible; }
            set { visible = value;
                  excel.Visible = visible;
            }
        }

        public void BeforeWorkBookClose()
        {
            if (Del_onClose == null)
            {
                Del_onClose += OnWorkbookClose;
                workBook.BeforeClose += Del_onClose;
            }
        }

        public void AddWorkbook()
        {
            if (workBook == null)
            {
                workBook = excel.Workbooks.Add();
            }


        }

        public Interop.Workbook WorkBook
        {
            get { return workBook; }
        }

        public Interop.Worksheet GetSheet(object index)
        {
            Interop.Worksheet workSheet = null;
            try
            {
                workSheet = (Interop.Worksheet)excel.ActiveWorkbook.Worksheets.get_Item(index);
            }
            catch (Exception)
            {
               
            }
            return workSheet;
        }


        public void ShowMessage(string message)
        {
         MessageBox.Show(message, 
         "Excel Wrapper dll Message", 
         MessageBoxButton.OK,
          MessageBoxImage.Information,
          0,
          MessageBoxOptions.DefaultDesktopOnly
          ); 
          System.Console.WriteLine("ShowMessage Called from PSWrapper");

        }

        private void OnWorkbookClose(ref bool cancel)
        {
            
            ShowMessage("This message has been called from OnWorkbookClose in ExcelWrapper dll");
            Console.WriteLine("Quit message called from OnWorkbookClose");
            OnExcelWorkbookCloseEvent();

        }

        public void Close()
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(excel); 
        }

 
    }
}
"@
$refs = ("System","System.Management","Microsoft.Office.Interop.Excel","windowsbase","PresentationFramework","PresentationCore","System.Xaml","System.Reflection"
)


Add-Type  -TypeDefinition $source -ReferencedAssemblies $refs -Language CSharp




}

PROCESS
{
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.window")

$wrapper = new-object ExcelWrapper.PSWrapper
$wrapper.AddWorkbook()
$wrapper.Workbook.ActiveSheet.Name = "MySheet"
$sht = $wrapper.Workbook.Worksheets.Item(1)"$($sht.Name)"
$sht2 = $wrapper.GetSheet(2)"$($sht2.Name)"
$sht3 = $wrapper.GetSheet("MySheet")"$($sht3.Name)"

$sht3.Range("A1").Cells = "This is a test workbook please close to see response to event."


 $onClose = {
       
       $wrapper.ShowMessage("Quit")
        write-host "Close event - called from Powershell using ExcelWrapper"
         [System.Windows.MessageBox]::Show("Close event - called from Powershell using MessageBox DefaultDesktopOnly", "Quit Message  Powershell", 
         [System.Windows.MessageBoxButton]::OK,
          [System.Windows.MessageBoxImage]::Information,
          0,
          [System.Windows.MessageBoxOptions]::DefaultDesktopOnly
          ) | out-null
        write-host "Close event - called from Powershell using Messagebox DefaultDesktop option - no messagebox displayed"
         [System.Windows.MessageBox]::Show("Close event - called from Powershell using MessageBox RightAlign", "Quit Message  Powershell", 
         [System.Windows.MessageBoxButton]::OK,
          [System.Windows.MessageBoxImage]::Information,
          0,
          [System.Windows.MessageBoxOptions]::RightAlign
          ) | out-null
        write-host "Close event - called from Powershell using Messagebox RightAlign option - messagebox displayed"
} 

Register-ObjectEvent -InputObject $wrapper -EventName OnExcelWorkbookCloseEvent -SourceIdentifier Quit -Action $onClose 
$wrapper.BeforeWorkbookClose()


$wrapper.Visible = $true


}

END
{
[System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture 

$wrapper.Close()
}



Viewing all articles
Browse latest Browse all 15028

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>