2014-04-01 13 views
10

Đây là một tình huống giả định.Làm thế nào để trưng ra một lớp C# vào một mô-đun VBA trong một bổ trợ cấp tài liệu?

Tôi muốn tìm hiểu xem có thể hiển thị lớp C# với VBA trong bổ trợ cấp tài liệu hay không.

Dưới đây là một SSCCE:

Trong VS PRO 2012 Tôi đã bắt đầu một dự án mới, Selected Office -> Excel 2010 Workbook. (make sure you select .Net framework ver 4)

Tôi đã thêm điều khiển DateTimePicker vào Sheet1.

Tôi có thể đặt/lấy thuộc tính .Value khỏi điều khiển DateTimePicker trong giải pháp C# mà không gặp sự cố.

Trong khi gỡ lỗi: Trong VBA, thuộc tính .Valuekhông phơi sáng. (thử .OLEFormat.Object.Value)

enter image description here

Không phải tất cả các thuộc tính có thể được tiếp xúc với VBA vì ActiveX kiểm soát DateTimePicker được bọc bởi MSForms để Excel nhận nó (tương thích).

tôi cần để có thể lấy giá trị thực tế của điều khiển bọc từ VBA, nhưng tôi không chắc chắn như thế nào đi về nó (cho dù đó là tốt hay không) ...

tôi biết rằng bản thân điều khiển hỗ trợ các sự kiện nhưng đây không phải là con đường tôi muốn thực hiện. Tôi muốn có thể lấy giá trị tĩnh/hiện tại ngoài một điều khiển.


Đây là những gì tôi muốn để có thể làm:

  • Thêm một lớp học để giải pháp C# tôi

  • Expose nó, vì vậy nó recreatable từ VBA như Dim obj as new MyExposedClass

  • sau đó có MyExposedClass tham chiếu cửa hàng vào DateTimePicker như nó xuất hiện trong C# (tất cả các tài sản có sẵn)

  • sau đó tôi có thể định nghĩa một hàm GetValue(string controlName) mà trả về giá trị gia tăng từ C# POV


Vì vậy, tôi tìm thấy this solution + (this one) dường như hoạt động với một ứng dụng cấp bổ trợ nhưng nó không hoạt động với một tài liệu cấp tài liệu bổ trợ.

Khi tôi gỡ rối giải pháp của tôi và Object Browser mở VBA của tôi có thể thấy rằng tài liệu tham khảo sẽ được tự động thêm vào Microsoft Visual Studio 2008 Tools for Office Execution Engine 9.0 Type Library nhưng tôi không nghĩ rằng tôi có thể thêm một lớp thêm để nó ...

Khi Tôi mở các tài liệu tham khảo trong VBE không có thêm tài liệu tham khảo thêm vào dự án nhưng trong thư mục/debug của giải pháp của tôi có một ExcelWorkbook1.dll vậy làm thế nào nó thậm chí gắn liền với giải pháp?

Vì vậy, câu hỏi của tôi là:

Làm thế nào tôi có thể tiếp xúc với một lớp trong một tài liệu cấp add-in cho Excel bằng C# để mở rộng phạm vi tài sản tiếp cận theo mặc định trên điều khiển Net?

Cập nhật:

này là gần nhất tôi có cho đến nay nhưng nó chỉ cho phép bạn để lộ tài liệu chủ như Worksheet, Workbook, Chart vv Nó cho phép bạn gọi các phương pháp mặc dù vậy tôi sẽ để điều tra này hơn nữa và trở lại với một số thông tin phản hồi

Calling Code in Document-Level Customizations from VBA

How to: Expose Code to VBA in a Visual C# Project

Walkthrough: Calling Code from VBA in a Visual C# Project

Trả lời

5

Bạn sẽ cần phải tạo một giao diện công khai để hiển thị lớp cho VBA, điều này làm việc cho tôi như một addin cấp tài liệu.

  1. Mở một bảng tính Excel mới và sao chép đoạn mã sau vào một MODULE

    Sub CallVSTOMethod() 
    Dim dt As Date 
    Dim VSTOSheet1 As DocLevelAddin.Sheet1 
        Set VSTOSheet1 = GetManagedClass(Sheet1) 
        dt = VSTOSheet1.GetDatePickerVal 
    End Sub 
    
  2. Lưu Excel là "TestProj.xlsm" và gần gũi.

  3. mở VS, dự án mới, Excel Workbook 20XX và đặt tên cho dự án "DocLevelAddin"
  4. Trong trình hướng dẫn, chọn sao chép một tài liệu hiện có và chọn bảng tính mới được tạo ra "TestProj.xlsm"
  5. Trên Excel Sheet1 thêm sự kiểm soát DateTimePicker vào tờ từ trong tệp VS, nhấp đúp để tạo ra một sự kiện ValueChanged và cập nhật các mã trong Sheet1.cs để đọc

    private DateTime dtVal; 
    private void dateTimePicker1_ValueChanged(object sender, EventArgs e) 
    { 
        dtVal = dateTimePicker1.Value; 
    } 
    
  6. Vẫn trong Sheet1.cs, thêm một phương pháp nào để trở dtVal

    public DateTime GetDatePickerVal() 
    { 
        return dtVal; 
    } 
    
  7. Cũng thêm dòng sau vào Sheet1.cs

    protected override object GetAutomationObject() 
    { 
        return this; 
    } 
    
  8. Trên public partial class Sheet1 trong Sheet1.cs thêm dòng sau

    [System.Runtime.InteropServices.ComVisible(true)] 
    [System.Runtime.InteropServices.ClassInterface( 
        System.Runtime.InteropServices.ClassInterfaceType.None)] 
    
  9. Bây giờ bạn cần để tạo ra một cộng đồng giao diện cho phương thức. Trong Sheet1.cs nhấn chuột phải chọn Refactor, Extract Interface và kiểm tra các phương pháp công GetDatePickerVal

  10. Tận dụng công cộng giao diện và COM có thể nhìn thấy

    [System.Runtime.InteropServices.ComVisible(true)] 
    public interface ISheet1 
    { 
        DateTime GetDatePickerVal(); 
    } 
    
  11. đúp Sheet1.cs nhấp chuột để bảng tính Excel có thể nhìn thấy. Chọn bất kỳ tế bào để mở cửa sổ thuộc tính và thay đổi thuộc tính ReferenceAssemblyFromVbaProject = true

  12. Trong Excel bạn có thể cần phải goto Trung tâm Trust Cài đặt và thêm thư mục VS Giải pháp và thư mục phụ như địa điểm tin cậy

  13. Run dự án và mã trong Excel MODULE sẽ trả về dateTimepicker thông qua phương thức GetDatePickerVal tiếp xúc.

enter image description here

Sheet1.cs:

using System; 
using System.Collections.Generic; 
using System.Data; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Xml.Linq; 
using Microsoft.Office.Tools.Excel; 
using Microsoft.VisualStudio.Tools.Applications.Runtime; 
using Excel = Microsoft.Office.Interop.Excel; 
using Office = Microsoft.Office.Core; 

namespace DocLevelAddin 
{ 
    [System.Runtime.InteropServices.ComVisible(true)] 
    [System.Runtime.InteropServices.ClassInterface(
     System.Runtime.InteropServices.ClassInterfaceType.None)] 
    public partial class Sheet1 : DocLevelAddin.ISheet1 
    { 
     private void Sheet1_Startup(object sender, System.EventArgs e) 
     { 
     } 

     private void Sheet1_Shutdown(object sender, System.EventArgs e) 
     { 
     } 

     #region VSTO Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InternalStartup() 
     { 
      this.dateTimePicker1.ValueChanged += new System.EventHandler(this.dateTimePicker1_ValueChanged); 
      this.Startup += new System.EventHandler(this.Sheet1_Startup); 
      this.Shutdown += new System.EventHandler(this.Sheet1_Shutdown); 

     } 

     #endregion 

     private DateTime dtVal; 
     private void dateTimePicker1_ValueChanged(object sender, EventArgs e) 
     { 
      dtVal = dateTimePicker1.Value; 
     } 

     public DateTime GetDatePickerVal() 
     { 
      return dtVal; 
     } 

     protected override object GetAutomationObject() 
     { 
      return this; 
     } 

    } 
} 

ISheet1.cs:

using System; 
namespace DocLevelAddin 
{ 
    [System.Runtime.InteropServices.ComVisible(true)] 
    public interface ISheet1 
    { 
     DateTime GetDatePickerVal(); 
    } 
} 
Các vấn đề liên quan