从C#调用Excel宏编译错误:未定义Sub或Function

时间:2017-04-05 18:13:42

标签: c# excel vba excel-vba

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

错误: 1.编译错误:Sub或Function未定义 - 在“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

请帮忙。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

我们假设你有一个看起来像这样的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

答案 2 :(得分:0)

问题是什么?它没有用?在我工作时,我无法测试这些东西;我机器上的所有东西都完全锁定了。如果计算机打开电话我很幸运...

我知道,下面的脚本肯定会有效。

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();
            }
        }
    }
}