从 Excel 文档中的代码隐藏获取 ActiveX 或表单对象(文本框)

Reach ActiveX or Form objects (textbox) from codebehind in an Excel document

excel 文件中有几个文本框作为 ActiveX 对象,我想从代码隐藏中访问它们。

我正在为其他字段使用 ClosedXML,但我愿意接受其他建议。

您可以在 VBA 中创建文件(在 %appdata% 文件夹中),并在该文件中保存文本框值 (by example, .ini file)。

然后在 C# 中打开文件。

VBA(.xlsm 文件)

'               PtrSafe for 64bit (for 32bit, remove it)
Private Declare PtrSafe Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" _
    (ByVal lpApplicationName As String, ByVal lpKeyName As Any, _
    ByVal lpString As Any, ByVal lpFileName As String) As Long

Private Sub TextBox1_Change()
    WritePrivateProfileString "Page1", "TextBox1", TextBox1.Text, "C:\Users\HS\Desktop\exceltab.ini"
End Sub

C:\Users\HS\Desktop\exceltab.ini

[Page1]
TextBox1=ok

如果您想使用 ClosedXML,您可以 link 具有 LinkedCell 属性的文本区域和单元格。

像这样:

参见:

如果您使用的是 ClosedXML,则应查看 XLWSContentManager

根据Microsoft

ActiveX controls are represented by OLEObject objects in the OLEObjects collection (all OLEObject objects are also in the Shapes collection)

因此,使用 ClosedXML,您需要使用 XLWSContents.OleObjects,但如果控件不是 ActiveX 控件,而是内置的 Excel Form 控件,你需要使用 XLWSContents.Controls.

但请注意 MS 文档 - ClosedXML 的实现可能还需要您检查形状。

您可以如下遍历所有OLE 对象,并通过文本框名称或文本框Text 来识别您需要的文本框。您可以使用工作簿外部或任何代码的工作表引用,而不是我。

Private Sub GetActiveXControls()

  For Each Item In Me.OLEObjects
    'Debug.Print Item.Name
    If TypeName(Item.Object) = "TextBox" Then
      Debug.Print "text = " & Item.Object.text
    End If
  Next

End Sub

要从 C# 访问 OLE 对象,请添加对 Microsoft Forms 2.0 对象库的引用。您可以遍历所需复选框和文本框的控件。享受!

using Excel = Microsoft.Office.Interop.Excel;
using VBE = Microsoft.Vbe.Interop.Forms;

private static void ExcelOperation(string xlFileName)
        {
            var xlApp = new Excel.Application();
            var xlWorkbook = xlApp.Workbooks.Open(xlFileName);
            var xlSheet = xlWorkbook.Worksheets["your_sheet_Name"] as Excel.Worksheet;

            try
            {
                Excel.OLEObjects oleObjects = xlSheet.OLEObjects() as Excel.OLEObjects;
                foreach (Excel.OLEObject item in oleObjects)
                {                   
                    if (item.progID == "Forms.TextBox.1")
                    {
                        VBE.TextBox xlTB = item.Object as VBE.TextBox;
                        Console.WriteLine("Name: " + item.Name);
                        Console.WriteLine("Text: " + xlTB.Text);
                        Console.WriteLine("Value: " + xlTB.get_Value());
                        Marshal.ReleaseComObject(xlTB); xlTB = null;
                    }
                    else if (item.progID == "Forms.CheckBox.1")
                    {
                        VBE.CheckBox xlCB = item.Object as VBE.CheckBox;
                        Console.WriteLine("checkbox: " + item.Name);
                        Console.WriteLine("Value: " + xlCB.get_Value());
                        Marshal.ReleaseComObject(xlCB); xlCB = null;
                    }                    

                }

                Marshal.ReleaseComObject(oleObjects); oleObjects = null;
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Marshal.ReleaseComObject(xlSheet); xlSheet = null;
            xlWorkbook.Close();
            Marshal.ReleaseComObject(xlWorkbook); xlWorkbook = null;
            Marshal.ReleaseComObject(xlApp); xlApp = null;
        }