2016-08-24 2 views
2

MS Word文書に埋め込まれているブックを編集するときに問題を引き起こす既存のExcel VSTOアドインで作業しています。その環境でaddinが機能することは必須ではありませんが、アドインが扱うものと無関係なファイルを顧客が操作している場合でも、埋め込みが誤動作しています。少なくとも、そのワークブックのためにそれ自体を初期化しないようにする必要があります。VSTO Excelアドインは、ブックがワードドキュメントに埋め込まれているかどうかをどのように伝えることができますか?

私が研究してきたいくつかの道:

  1. Microsoft.Office.Interop.Excel.Workbook.Applicationのドキュメントを読み取ります。「 せずに、オブジェクトの修飾子を使用する場合、このプロパティは、Applicationオブジェクトを返します。 オブジェクト修飾子と共に使用すると、 が指定されたオブジェクトの作成者を表すApplicationオブジェクトが返されます(OLEオートメーションオブジェクトでこの プロパティを使用して戻ることができます)。そのオブジェクトの のアプリケーション)これは有望ですが、私は理解していません "オブジェクト修飾子付き"とはC#の文脈での意味です。
  2. This linkは、コマンドライン引数を調べることを推奨しています。しかし、Excelをスタンドアロンで開いて、埋め込まれたExcelオブジェクトでWord文書を開いた場合、Wordは埋め込みに同じインスタンスを使用し、コマンドライン引数には "-embedded"フラグは含まれません。
  3. 私は、既存のスタンドアロンインスタンスを再利用するのではなく、新しいExcelインスタンスを強制的に使用するようにしたいと思いますが、その方法もわかりません。

Excelの単一インスタンスは、埋め込み型とスタンドアロン型の両方のブックを同時にホストすることができるため、この情報はブックレベルでなければなりません。

+0

は、あなたがこれまでFIました:オフィス2016)の上に私のために動作しませんでしたworkbook.Containerをチェックするために答えますこれを見て? Word文書に埋め込みExcelブックのアドインを無効にしたいのですが。 – tjsmith

+0

申し訳ありませんが、この問題は解決していません。しかし、私はまだ解決策に興味があります。 –

答えて

0

Workbook.Containerプロパティを確認することで、ブックが別のアプリケーションに埋め込まれているかどうかを判断できます。ワークブックが埋め込まれている場合、埋め込みブックを含むWord Documentオブジェクトが含まれます。

public bool IsEmbedded(Workbook workbook) 
{ 
    try 
    { 
     // via the container you get a handle to the parent Word document object 
     var container = workbook.Container; 
     return true; 
    } 
    catch (COMException ex) 
    { 
     if (ex.ErrorCode == -2146822566) 
     { 
      // Exception message is: 
      // "This property is only available if the document is an OLE object." 
      return false; 
     } 

     throw; 
    } 
} 

Workbook.PathまたはWorkbook.Name性質に依存することも可能である。それ以外の場合はプロパティを呼び出すと、そのtry-catchブロックにチェックをラップすることを確認し、例外がスローされます。私にとって

私が埋め込まれたExcelワークブックのためにこれらのプロパティをチェックするとき、私は次のような結果を得る:

// this is empty for an embedded workbook 
Application.Workbooks[1].Path; 

// this contains the string "Worksheet in <document name>.docx" 
Application.Workbooks[1].Name; 

+0

コール**ワークブック。コンテナ**は私のためには機能しません。ブックがスタンドアロンのExcelアプリケーションであるかWordに埋め込まれたブックであるかにかかわらず常に-2146822566(0x800A165A)例外がスローされます。私のシステムについては何が違うでしょうか?私はOffice 2016を使用しています。 –

+0

おそらく、ブックの埋め込み方法は異なりますか?ちょっと推測すると...サンプル文書を共有できますか? –

+0

私は2つのシナリオを練習しています:(1)Excelを実行し、空のワークシートを作成します。 (2)Wordを実行し、 "挿入"リボンで "オブジェクト..."を選択し、 "新規作成"と "Microsoft Excelワークシート"を選択します。次に、新しく作成したExcelワークシートを選択します。私があなたが文書化したものとは異なるエラーコードを取得していることに注意してください。私はWorkbook.Containerが "部分的に信頼できるアセンブリ"で利用できない場所を読んでいます。これが寄与する要因であるかどうかを研究しようとしています。 –

0

これは、ブックが埋め込まれたOLEオブジェクト(他のであれば、あなたを伝えるために働きます https://theofficecontext.com/2013/04/10/how-to-determine-if-an-excel-workbook-is-embedded-and-more/

public static class ExcelExtensionMethods 
{ 

[DllImport("ole32.dll")] 
static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc); 

/// <summary> 
/// WORKBOOK EXTENSION METHOD 
/// Checks to see if the Workbook is embeeded inside of 
/// another ActiveX Document type, sy=uch as Word or Excel. 
/// </summary> 
/// <param name="PobjWb"></param> 
/// <returns></returns> 
public static bool IsEmbedded(this Excel.Workbook PobjWb) 
{ 
    if (PobjWb.Path == null || PobjWb.Path.Length == 0) 
    { 
     try 
     { 
      // requires using Microsoft.VisualStudio.OLE.Interop; 
      // and you have to manually add this to reference from here: 
      // C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.OLE.Interop.dll 
      IOleObject LobjOleObject = ((object)PobjWb) as IOleObject; 
      IOleClientSite LobjPpClientSite; 
      // get the client site 
      LobjOleObject.GetClientSite(out LobjPpClientSite); 
      // if there is one - we are embedded 
      if (LobjPpClientSite != null) 
      { 
       return true; 
      } 
      else 
      { 
       // not embedded 
       return false; 
      } 
     } 
     catch (Exception ex) 
     { 
      // exception 
      Debug.Print(ex.ToString()); 
      return false; 
     } 
     finally { } 
    } 
    else 
    { 
     // not embedded 
     return false; 
    } 
} 

/// <summary> 
/// WORKBOOK EXTENSION METHOD 
/// This method return the name of the class that we 
/// are embedded inside of. 
/// If we are not embedded it return null. 
/// If there is any exception it return null. 
/// If the container cannot be accessed it returns UNKNOWN. 
/// </summary> 
/// <param name="PobjWb"></param> 
/// <returns></returns> 
public static string EmbedClassName(this Excel.Workbook PobjWb) 
{ 
    try 
    { 
     IOleObject LobjOleObject = ((object)PobjWb) as IOleObject; 
     IOleClientSite LobjPpClientSite; 
     // get the client site 
     LobjOleObject.GetClientSite(out LobjPpClientSite); 
     if (LobjPpClientSite != null) 
     { 
      IOleContainer LobjPpContainer; 
      LobjPpClientSite.GetContainer(out LobjPpContainer); 
      if (LobjPpContainer != null) 
      { 
       return LobjPpContainer.GetType().Name; 
      } 
      else 
      { 
       // something wrong - container is not valid 
       return "UNKNOWN"; 
      } 
     } 
     else 
     { 
      // not embedded 
      return null; 
     } 
    } 
    catch (Exception ex) 
    { 
     Debug.Print(ex.ToString()); 
     return null; // failed 
    } 
} 

/// <summary> 
/// WORKBOOK EXTENSION METHOD 
/// Get the full path to the file that the workbook is embedded 
/// inside of. 
/// If we are not embeeded then this will return null. 
/// If we are embedded but there are issues with the container 
/// or an exception occurs, it will return null. 
/// Otherwise we get the full path and filename. 
/// </summary> 
/// <param name="PobjWb"></param> 
/// <returns></returns> 
public static string EmbedMoniker(this Excel.Workbook PobjWb) 
{ 
    try 
    { 
     IOleObject LobjOleObject = ((object)PobjWb) as IOleObject; 
     IOleClientSite LobjPpClientSite; 
     // get the client site 
     LobjOleObject.GetClientSite(out LobjPpClientSite); 
     if (LobjPpClientSite != null) 
     { 
      IOleContainer LobjPpContainer; 
      LobjPpClientSite.GetContainer(out LobjPpContainer); 
      if (LobjPpContainer != null) 
      { 
       // get the moniker 
       IMoniker LobjMoniker; 
       LobjPpClientSite.GetMoniker((uint)OLEGETMONIKER.OLEGETMONIKER_FORCEASSIGN, 
              (uint)OLEWHICHMK.OLEWHICHMK_OBJFULL, 
              out LobjMoniker); 
       if (LobjMoniker != null) 
       { 
        // now pull the moniker display name 
        // this will be in the form of PATH!Context 
        string LstrDisplayName; 
        IBindCtx LobjCtx = null; 
        CreateBindCtx(0, out LobjCtx); // required (imported function) 
        LobjMoniker.GetDisplayName(LobjCtx, null, out LstrDisplayName); 
        // remove context is exists 
        if (LstrDisplayName.Contains("!")) 
        { 
         string[] LobjMonikerArray = LstrDisplayName.Split('!'); 
         // return the first part - which should be the path 
         return LobjMonikerArray[0]; 
        } 
        else 
        { 
         // return full display name 
         return LstrDisplayName; 
        } 
       } 
       else 
       { 
        // no moniker value 
        return null; 
       } 
      } 
      else 
      { 
       // something wrong - container is not valid 
       return null; 
      } 
     } 
     else 
     { 
      // not embedded 
      return null; 
     } 
    } 
    catch (Exception ex) 
    { 
     Debug.Print(ex.ToString()); 
     return null; // failed 
    } 
} 
} 
+0

私はこれを試してみます...しかし、私はこの問題に取り組む前に時間がかかるかもしれません。 –

+0

こんにちは。上記はあなたのために働いたのですか?私は説明したようにIsEmbeddedを実装しようとしましたが、運はありません。私はOffice 2016を使用しています –

+0

...しかし、私はワークブックのオープンハンドラで動作しませんでした。それを閉じるハンドラで使用するとうまくいきます。私は開いている間にそれを検出する必要があります。 –

関連する問題