Freeko

Hey guys,

although it isn't strictly VSTO-related question I'm sure you'll know hot to do it and help me Smile

So, I wrote simple COM add-in for word, excel and powerpoint. One of the functions of this add-in would be to retrieve current document path / location (E.G: "C:/Users/USername/Documents/presentation.ppt".) and then do something with it.


Is there a method that would work for all programs listed above Something like

file_loc = Microsoft.Office.something.something.something;

In C#!

thanks in advance!


Re: Visual Studio Tools for Office Retrieve current document path

FaisalNasir-MSFT

Hi,

In the addin class you can get the path of the current document (active document) like this.

//for word

file_loc = this.Application.ActiveDocument.FullName;

// for excel

file_loc = this.Application.ActiveWorkbook.FullName;

//for powerpoint

file_loc = this.Application.ActivePresentation.FullName;

Hope this helps.

- Faisal





Re: Visual Studio Tools for Office Retrieve current document path

Freeko

I don't have this.Application property.

all I have is this.applicationObject which is defined as private object. Within this object I only have "equals / gettype / tostring gethashcode".

I guess I'm missing a reference or "using" directive. I have references to Excel, Word, PPT, Microsoft.Office.Core, Extensibility, System.Windows.Forms, System.Data, System and System.XML.

About "using":

using System;
using Extensibility;
using System.Runtime.InteropService;
using System.Reflection;
using Microsoft.Office.Core;

I'm trying to call it from private function inside my main class.




Re: Visual Studio Tools for Office Retrieve current document path

Helmut Obertanner

Hello Freeko,

must be something like this:

Type applicationType = applicationObject.GetType();

string propertyName = "";

switch (applicationType.ToString ())

{

case "Microsoft.Office.Interop.Word.ApplicationClass":

propertyName = "ActiveDocument";

break;

case "Microsoft.Office.Interop.Excel.ApplicationClass":

propertyName = "ActiveWorkbook";

break;

case "Microsoft.Office.Interop.Powerpoint.ApplicationClass":

propertyName = "ActivePresentation";

break;

}

object activeDocument = applicationType.InvokeMember(propertyName, BindingFlags.GetProperty , null, applicationObject, null);

string documentPath = (string)activeDocument.GetType().InvokeMember("FullName", BindingFlags.GetProperty, null, activeDocument, null);

Hope this may give you a start.

Greets, Helmut






Re: Visual Studio Tools for Office Retrieve current document path

Freeko

Wow, thank you (both) for your time; that really helped!

Again, I'm sorry for such beginner' questions but just "came" from unix and .net is sooooo different. But much better documented and supported!




Re: Visual Studio Tools for Office Retrieve current document path

Xm3KHs

I tried this code, but the only type i get in "Type applicationType = applicationObject.GetType(); applicationType.ToString() ;" is "System.__ComObject"

So the switch statement never catchs it. Word is the only that returns the right type. How can i get the right types for the others (Excel, Powerpoint, ...)

How can i get applicationType.ToString() to return "Microsoft.Office.Interop.Excel.ApplicationClass" insted of "System.__ComObject"

Need help, Please!




Re: Visual Studio Tools for Office Retrieve current document path

X4U

Hello Xm3KHs,

make sure that you installed the Primary Interop Assemblies.

I rechecked and the code works fine - at last for e.g. Word:

My Environment:

WinXPSP2 ; Office 2007 and VSTO SE

If you haven't installed the PIA's then you will get the COM object error.

Are you sure you are using VSTO

Hope this helps,

greets, Helmut






Re: Visual Studio Tools for Office Retrieve current document path

Xm3KHs

Could you try another program besides Word, for example Excel

I have the Primary Interop Assemblies installed, and everything else.
And i'm not getting any error.

It's working ok (only in Word).
The other programs return System.__ComObject instead of Microsoft.Office.Interop.Excel.ApplicationClass, Microsoft.Office.Interop.Powerpoint.ApplicationClass, ...

It's not a error, it's only the return type that it's not the expected.

Thanks in advance.




Re: Visual Studio Tools for Office Retrieve current document path

X4U

Hi Xm3KHs,

you are right. doesn't work for Excel.

So maybe try this - should work for all ...

Type applicationType = application.GetType();

string ApplicationName = (string)applicationType.InvokeMember("Name", BindingFlags.GetProperty, null, applicationObject, null);

By the way you also can try the As function

Excel.Application excel = applicationObject as Excel.Application;

if (excel != null){

// Excel AddIn

} else {

Word.Application word = applicationObject as Word.Application;

if (word != null){

// Word AddIn

} else etc..

}

One of the both must work :-)

Hope this helps,

greets, Helmut






Re: Visual Studio Tools for Office Retrieve current document path

Xm3KHs

Hi, again

Just like Freeko, i want to get the path of the current document in any Office Application.
I tried to use the code in this forum thread, but it only works for Word.
The code below is my try, so far. But it as a problem (it doesn't work)
Following Helmut suggestion i used the AS function, but actually it's not really solving my problem.
The switch statement from the code above had to be replaced by the if...else chain as i post below.
This code still works for Word, but it doesn't work for Excel, Powerpoint, ...


Code Snippet

object oName =
applicationObject.GetType().InvokeMember("Name", BindingFlags.GetProperty, null, applicationObject, null);

Type applicationType = applicationObject.GetType();

object activeDocument = null;

if (oName.ToString().IndexOf("Word") != -1)
activeDocument = applicationType.InvokeMember("ActiveDocument", BindingFlags.GetProperty , null, applicationObject, null);
else if (oName.ToString().IndexOf("Excel") != -1)
{
Microsoft.Office.Interop.Excel.Application excel = applicationType as Microsoft.Office.Interop.Excel.Application;
activeDocument = excel.ActiveWorkbook;
}
else if (oName.ToString().IndexOf("Powerpoint") != -1)
{
Microsoft.Office.Interop.PowerPoint.Application powerpoint = applicationType as Microsoft.Office.Interop.PowerPoint.Application;
activeDocument = powerpoint.ActivePresentation;
}

if (activeDocument != null)
{
string documentPath = (string)activeDocument.GetType().InvokeMember("FullName", BindingFlags.GetProperty, null, activeDocument, null);
...
}





Re: Visual Studio Tools for Office Retrieve current document path

Xm3KHs

Need HELP! Please!
Does anybody have a ideia, how to get path the current document on any office application (Excel, Powerpoint, Word, ...)




Re: Visual Studio Tools for Office Retrieve current document path

X4U

Hello,

I rechecked, installed Office 2000 on XP and created a Shared AddIn.

Also when I use late binging - it's not possible to get the Name Property from Excel by .Net assembly

I rechecked with Office XP - same behavior.

Recheck with Office 2007 - works fine on my machine.

So for this I have no answer.

Maybe we should play around a little with using get_Name method instead of a property.

I will try this and let you know.

Can you tell us what Office version and OS you use

Greets, Helmut






Re: Visual Studio Tools for Office Retrieve current document path

Xm3KHs

My machine:
Windows Server 2003 - Standard Edition - Service Pack 1
Office Professional Edition 2003 (with .NET Programmability Support in all apps)
VSTO - Visual Studio Tools for Microsoft Office
Visual Studio .NET 2003

Created Shared Add-in:
(in Connect.cs)
public void OnStartupComplete(ref System.Array custom) {
CommandBars oCommandBars;
CommandBar oStandardBar;
try {
oCommandBars =
(CommandBars)applicationObject.GetType().InvokeMember("CommandBars", BindingFlags.GetProperty, null, applicationObject, null);
}
catch (Exception) {
//Outlook has the CommandBars collection on the Explorer object
object oActiveExplorer =
applicationObject.GetType().InvokeMember("ActiveExplorer", BindingFlags.GetProperty, null, applicationObject,null);
oCommandBars =
(CommandBars)oActiveExplorer.GetType().InvokeMember("CommandBars", BindingFlags.GetProperty, null, oActiveExplorer, null);
}
object oName =
applicationObject.GetType().InvokeMember("Name", BindingFlags.GetProperty, null, applicationObject, null);
try {
if (oName.ToString().IndexOf("Excel") != -1)
oStandardBar = oCommandBars["Worksheet Menu Bar"];
else
oStandardBar = oCommandBars["Menu Bar"];
}
catch (Exception) {
oStandardBar = oCommandBars.ActiveMenuBar;
}
//In case the button was not deleted, use the existing one
try {
MyButton = (CommandBarButton)oStandardBar.Controls["My Custom Button"];
}
catch (Exception) {
MyButton = CreateButton(oStandardBar, "My Custom Button");
}
MyButton.Click += new _CommandBarButtonEvents_ClickEventHandler(this.MyButton_Click);
oStandardBar = null;
oCommandBars = null;
}

private void MyButton_Click(CommandBarButton cmdBarButton, ref bool cancel) {
object oName =
applicationObject.GetType().InvokeMember("Name", BindingFlags.GetProperty, null, applicationObject, null);
Type applicationType = applicationObject.GetType();
string propertyName = String.Empty;
if (oName.ToString().IndexOf("Word") != -1)
propertyName = "ActiveDocument";
else if (oName.ToString().IndexOf("Excel") != -1)
propertyName = "ActiveWorkbook";
else if (oName.ToString().IndexOf("Powerpoint") != -1)
propertyName = "ActivePresentation";
else if (oName.ToString().IndexOf("Publisher") != -1)
propertyName = "ActiveDocument";
else if (oName.ToString().IndexOf("Access") != -1)
propertyName = "CurrentProject";
if (!propertyName.Equals(String.Empty)) {
MessageBox.Show(oName.ToString() + "\n(" + applicationType.FullName + " - " + Microsoft.VisualBasic.Information.TypeName(applicationObject) + ")");
object activeDocument = applicationType.InvokeMember(propertyName, BindingFlags.GetProperty , null, applicationObject, null);
string documentPath = (string)activeDocument.GetType().InvokeMember("FullName", BindingFlags.GetProperty, null, activeDocument, null);
MessageBox.Show("(" + documentPath + ")");
}
}

private CommandBarButton CreateButton(CommandBar Parent, string Caption) {
CommandBarButton cbb = null;
try {
cbb = (CommandBarButton)Parent.Controls.Add(MsoControlType.msoControlButton, Type.Missing, Type.Missing, Type.Missing, true);
cbb.Visible = true;
cbb.Caption = Caption;
cbb.Style = MsoButtonStyle.msoButtonCaption;
cbb.Tag = Caption.Replace("&", String.Empty);
cbb.OnAction = "!<OptArchiveAddin.Connect>";
}
catch (Exception ex) {
MessageBox.Show(ex.Message, ex.Source, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return cbb;
}
PS: Add
- using System.Reflection;
- using System.Windows.Forms;
- CommandBarButton MyButton; to the class vars
- Microsoft.VisualBasic to the references
- System.Windows.Forms to the references

With this code, in Word everything works ok:
applicationType.FullName returns Microsoft.Office.Interop.Word.ApplicationClass,
but for example in Excel it returns System.__ComObject and the underlying type ends in Application instead of ApplicationClass, which is the Interface (this could explain why it can't access other attributes that are specific of a instance of a Class.




Re: Visual Studio Tools for Office Retrieve current document path

X4U

Hi,

I think I worked it out.

First my scenarios:

I Installed a XP machine with VS2005 and Office2003 and created a simple shared AddIn wich should be loaded in all Office Apps.

I could reproduce that the AddIn doesn't load in Excel.

I could fix this with creating a ComShim with the ComShim Wizard.

So this is the Solution that my AddIn won't load within Excel.

But getting the Name Property worked fine.

I used this code snippet (delegates only with .Net 2.0)

Works fine for all Applications in different Office Versions.

My AddIn has no reference to any Office dll.

Code Snippet

///
/// Implements the OnConnection method of the IDTExtensibility2 interface.
/// Receives notification that the Add-in is being loaded.
///
///
/// Root object of the host application.
///
///
/// Describes how the Add-in is being loaded.
///
///
/// Object representing this Add-in.
///
///
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
{
applicationObject = application;
addInInstance = addInInst;

string applicationName = GetProperty(ref applicationObject, "Name");
string applicationVersion = GetProperty(ref applicationObject, "Version");

MessageBox.Show(string.Format("AddIn loaded within: {0} Version: {1}.", applicationName, applicationVersion));

}

///
/// Returns a property with the given Name latebound as the given type.
///
/// The targetType
/// The object where to retrieve the property from.
/// The Name of the property.
/// returns the specific value or throws an error.
private T GetProperty(ref object target, string propertyName)
{
return (T)target.GetType().InvokeMember(propertyName, BindingFlags.GetProperty, null, target, null);
}

So if the Latebound GetProperty Method doesn't work I suggest to go to control panel / add remove programms and do a repair for your Office.

Also apply the latest Office Service Pack.

2. When I look at your sourcecode some notes:

Code Snippet
try {
oCommandBars =
(CommandBars)applicationObject.GetType().InvokeMember("CommandBars", BindingFlags.GetProperty, null, applicationObject, null);
}
catch (Exception) {
//Outlook has the CommandBars collection on the Explorer object
object oActiveExplorer =
applicationObject.GetType().InvokeMember("ActiveExplorer", BindingFlags.GetProperty, null, applicationObject,null);
oCommandBars =
(CommandBars)oActiveExplorer.GetType().InvokeMember("CommandBars", BindingFlags.GetProperty, null, oActiveExplorer, null);
}

when you do such code within the exceptionhandler and you will get an exception ther, your AddIn will be disabled.

E.g. when Outlook is started from another programm you maybe have no ActiveExplorer -> crash...

So I suggest no code within the Catch block...

Also:

Recently I learned NOT to use the ....Class objects e.g. use Application class NOT ApplicationClass object.

I know you are missing some events -> cast explicitly to the corresponding event interface ->

((Excel.AppEvents_Event)excelApp).NewWorkbook += new ....

Hope this helps,

greets Helmut






Re: Visual Studio Tools for Office Retrieve current document path

Xm3KHs

Please try the code i posted in a new shared add-in project.
It only needs to pasted in the Connect.cs and follow the steps described after and it's ready to work.
My problem isn't getting the application name or version, but the Current Document opened in the application. So i can get the path to it.

Application Name and Version show up in all applications correctly. But not the current document, which in each application has a different property name.

If i could get this object, i could interact with it.
I have done other interactions with documents, but they where created by creating a new object in the code and then interacting with that new object.

I really need to know path to the document that the user is creating, because the add-in has to send it to a Remote Archive.

Thank you for your help, but i think my problem still exists

I will try to update my office ... (hopefully it can do something better)