【问题标题】:Calling Excel Macro from C# throwing Compile Error : Sub Or Function not defined从 C# 调用 Excel 宏引发编译错误:未定义子或函数
【发布时间】:2017-04-05 18:13:41
【问题描述】:

我正在创建一个 Web 应用程序来替换当前的 Excel 宏应用程序。 Excel 宏中包含多个表单和模块。当我使用 xlApp.Run 方法在 C# 中调用宏函数时,该函数被调用但在函数调用其他子函数并使用全局公共变量时抛出错误。

错误: 1. 编译错误:未定义子或函数 - 在“Set svd = m_queries(GetSheetRootName(Sheet1))” 2. 运行时错误 424:需要对象 - 在“CompareWorksheetsToCombined”

代码:

Public Function CompareExcels(filePath1 As String, filePath2 As String)
Call MsgBox("Done comparing sheets1.", vbInformation, "Compare Complete")
On Error GoTo CompErr
Call MsgBox("Done comparing sheets2.", vbInformation, "Compare Complete")
Dim compBook As Workbook
Dim book1 As Workbook, book2 As Workbook
Dim sheet, Sheet1 As Worksheet, Sheet2 As Worksheet
Dim svd As ScriptViewDescription, obj
Dim l As Long
Dim sheetName As String
Dim a As Integer

'// Check to make sure we have valid options selected for compare
If ValidateOptions = False Then Exit Function

cmdCompare.Enabled = True

'// Create the comparison output workbook
Set compBook = OpenCompareOutput()

'// Get the workbooks we're comparing
Set book1 = Workbooks(filePath1)
Set book2 = Workbooks(filePath2)

'// Verify if the Summary Sheet Exists and compare the libraries.
'//If (WorksheetExists("[" & filePath1 & "]Summary")) And (WorksheetExists("[" & filePath2 & "]Summary")) Then

    Set Sheet1 = book1.Sheets("Summary")
    Set Sheet2 = book2.Sheets("Summary")

    '//If Sheet1.Cells(2, 3) = Sheet2.Cells(2, 3) Then
       '// a = MsgBox("Attention: You are comparing the data from Same Environment", vbCritical, "Critical Warning")
    '//End If
'//Else
    '//a = MsgBox("Summary Tab does not exist in either Workbook A or B and the Libraries are not compared", vbCritical, "Critical Warning")
'//End If

'// Look for selected sheets and then compare them
For l = 0 To lstSheets.ListCount - 1
    If lstSheets.selected(l) = True Then
        '// reset vars to make sure we don't accidentally re-use from last loop
        Set Sheet1 = Nothing
        Set Sheet2 = Nothing
        Set svd = Nothing

        '// Attempt to load up the vars with the new stuff
        sheetName = lstSheets.list(l)
        Set Sheet1 = book1.Sheets(sheetName)
        Set Sheet2 = book2.Sheets(sheetName)
        Set svd = m_queries(GetSheetRootName(Sheet1))

        '// Check vars and if we're good then compare
        If Not (Sheet1 Is Nothing) _
        And Not (Sheet2 Is Nothing) _
        And Not (svd Is Nothing) Then
            Call CompareWorksheetsToCombined(Sheet1, Sheet2, compBook, svd, txtPrefixA.Text, txtPrefixB.Text)
        End If
    End If
Next l

cmdCompare.Enabled = True
Call MsgBox("Done comparing sheets.", vbInformation, "Compare Complete")

Exit Function
CompErr:
Call MsgBox("Error while attempting to process compares." & vbCrLf & vbCrLf & "Error " & Err.Number & ": " & Err.Description, vbCritical, "Error During Compare")
cmdCompare.Enabled = True
End Function

请帮忙。

【问题讨论】:

  • 没有您的代码我们如何提供帮助?请阅读how to ask
  • 请立即查看。谢谢
  • 如果您要在服务器上自动化 excel,这不是一个好的方向:它真的不是为那样使用而设计的。
  • 您的建议
  • 我想这将是找到一个可以在服务器端运行并将您的 VBA 移植到 C# 的库

标签: c# vba excel


【解决方案1】:

不久前我写了一些软件,它在关闭前运行一个宏。

Microsoft.Office.Interop.Excel.Document.ActiveDocument.Application.Run("macroName")

见: https://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.aspx

这里有一些使用 Interop.Word 的 VB 整理,应该很容易移植。

Imports Word = Microsoft.Office.Interop.Word

    Dim objWordApp As New Word.Application
    Dim objDoc As Word.Document

    Private Sub Form1_Load(ByVal sender As System.Object, e As System.EventArgs) Handles MyBase.Load

        'Establish application path, replace appPath on deployment
        Dim appPath As String = Application.StartupPath()

        'Run application in foreground or background.  
        'If in background (false), be sure to add objDoc.close() and objWordApp.Quit()
        objWordApp.Visible = False

        Dim objDoc As Word.Document = objWordApp.Documents.Open(appPath & "path.to.file", [ReadOnly]:=True)

        objDoc = objWordApp.ActiveDocument

        With objDoc
        ...Manipulate document...
        End With

        'clear objDoc object
        objDoc = Nothing

        'quit msWord
        lblStatus.Text = "Quitting MS Word"
        objWordApp.Quit()

        'clear objWord object
        objWordApp = Nothing

        'close com objects on parent system
        lblStatus.Text = "Releasing COM objects"
        If Not objDoc Is Nothing Then
            System.Runtime.InteropServices.Marshal.ReleaseComObject(objDoc)
        End If
        If Not objWordApp Is Nothing Then
            System.Runtime.InteropServices.Marshal.ReleaseComObject(objWordApp)
        End If

        'set filename
        lblStatus.Text = "Sending BLOB to DB"
        Dim filename As String = Path.GetFileName(saveString)

        'open a filestream
        Dim fs As FileStream = New FileStream(saveString, FileMode.Open, FileAccess.Read)

        'open a binary reader stream
        Dim br As BinaryReader = New BinaryReader(fs)

        'create array to store the BLOB
        Dim bytes As Byte() = br.ReadBytes(Convert.ToInt32(fs.Length))

        'Write the BLOB to the DB and set box as unselected
        Dim cmdStoreBlob As SqlCommand = New SqlCommand("UPDATE TABLENAME SET
            COLUMN = @VAR, [SELECTED] = @VAR2 WHERE [SELECTED] = 'True'", connection)
        cmdStoreBlob.Parameters.Add("@VAR1", SqlDbType.VarBinary).Value = bytes
        cmdStoreBlob.Parameters.Add("@VAR2", SqlDbType.Bit).Value = 0
        cmdStoreBlob.ExecuteNonQuery()

        'close binary reader and file stream
        lblStatus.Text = "Cleaning Up"
        br.Close()
        fs.Close() 'close file stream

        'close SQL server connection
        connection.Close()

        'exit application
        Application.Exit()
    End Sub
End Class

【讨论】:

    【解决方案2】:

    假设您有一个如下所示的 Excel 宏

    Sub ShowMsg(msg As String, title As String)
        MsgBox msg, vbInformation, title
    End Sub
    

    这是将参数传递给该宏然后调用它的 C# 代码。 (使用 VS2010 + Excel 2010 试用和测试)

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using Excel = Microsoft.Office.Interop.Excel;
    
    namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                //~~> Define your Excel Objects
                Excel.Application xlApp = new Excel.Application();
    
                Excel.Workbook xlWorkBook;
    
                //~~> Start Excel and open the workbook.
                xlWorkBook = xlApp.Workbooks.Open("E:\\Users\\Siddharth Rout\\Desktop\\book1.xlsm");
    
                //~~> Run the macros by supplying the necessary arguments
                xlApp.Run("ShowMsg", "Hello from C# Client", "Demo to run Excel macros from C#");
    
                //~~> Clean-up: Close the workbook
                xlWorkBook.Close(false);
    
                //~~> Quit the Excel Application
                xlApp.Quit();
    
                //~~> Clean Up
                releaseObject(xlApp);
                releaseObject(xlWorkBook);
            }
    
            //~~> Release the objects
            private void releaseObject(object obj)
            {
                try
                {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
                    obj = null;
                }
                catch (Exception ex)
                {
                    obj = null;
                }
                finally
                {
                    GC.Collect();
                }
            }
        }
    }
    

    https://social.msdn.microsoft.com/Forums/Lync/en-US/2e33b8e5-c9fd-42a1-8d67-3d61d2cedc1c/how-to-call-excel-macros-programmatically-in-c?forum=exceldev

    【讨论】:

    • 这不是我需要的。请帮助从C#调用主函数时如何调用子函数
    【解决方案3】:

    出了什么问题?它没有工作?我在工作时无法测试这些东西;我机器上的所有东西都被完全锁定了。如果电脑能开机我就很幸运了……

    我知道,下面的脚本确实有效。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using Excel = Microsoft.Office.Interop.Excel;
    
    
    namespace WindowsFormsApplication5
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
    
                //"http://programmingeveryday.wordpress.com/2013/02/20/run-excel-macro-programmatically-in-c/"
                //~~> Define your Excel Objects
                Excel.Application xlApp = new Excel.Application();
    
                Excel.Workbook xlWorkBook;
    
                //~~> Start Excel and open the workbook.
                xlWorkBook = xlApp.Workbooks.Open("C:\\Users\\Ryan\\Desktop\\RunMacro.xlsb");
    
                //~~> Run the macros by supplying the necessary arguments
                xlApp.Run("ShowMessage");
    
    
                //~~> Clean-up: Close the workbook
                xlWorkBook.Close(false);
    
                //~~> Quit the Excel Application
                xlApp.Quit();
    
                //~~> Clean Up
                releaseObject(xlApp);
                releaseObject(xlWorkBook);
            }
    
            //~~> Release the objects
            private void releaseObject(object obj)
            {
                try
                {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
                    obj = null;
                }
                catch (Exception ex)
                {
                    obj = null;
                }
                finally
                {
                    GC.Collect();
                }
            }
        }
    }
    

    【讨论】:

    • 你最好关闭你的电脑
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 2012-05-11
    • 1970-01-01
    相关资源
    最近更新 更多