协助打开从 C# VSTO Excel 项目到关闭的 .xlsx 文件的连接(w/o 打开 .xlsx 文件)

Assistance opening a connection from C# VSTO Excel project to a closed .xlsx file (w/o opening the .xlsx file)

我正在尝试将我在 VBA 中编写的 Excel 加载项转换为 C# VSTO。作为 C# 和 VS 的新手,这似乎是扩展我技能的好方法,而无需提出新的项目想法。

原来的 AddIn 的一个特点是它可以将多个关闭的 .xlsx 工作簿读入内存,做一些基本的数学运算并将新数据输出到一个新的工作簿中。最初,这是使用 Adodb.Connection 实现的。目前,我无法将连接复制到 VSTO 插件中的工作簿。

正在读取的工作簿需要保持关闭状态。每个工作簿都有三到五个工作表,但我只需要其中一个具有静态名称的数据。这些列有 headers,但它们不是很友好 headers,例如 "Exclusive? (1=Yes, 0=No)" 或 "Discharge Date|Time Display"。列名是静态的,但列号不是。另外,我只处理每个工作簿中的少量数据。

到目前为止,我已经研究了几个不同的选项。 LinqToExcel 看起来很有希望,但由于我正在使用的列名太糟糕而未能实现。我还尝试使用 OleDbConnection 和 Adodb.connection 但收效甚微。

这是VBA成功的代码。

    'Connection
    Dim Cnx As ADODB.Connection: Set Cnx = New ADODB.Connection
    With Cnx
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .ConnectionString = "Data Source=" & fileToCopy & _
           ";Extended Properties='Excel 12.0 xml;HDR=Yes;IMEX=1;Readonly=False'"
        .Open
    End With

    'Command String
    Dim headerString As String, request_SQL As String
    headerString = "[" & FullName & "]," & "[" & MRN & "]," & "[" & OHFColumnName & "]," & "[" & STSColumnName & "]," & "[" & IRColumnName & "]," & "[" & ERColumnName & "]"
    request_SQL = "SELECT " & headerString & " FROM [" & NewbornsWS & "$] WHERE [" & FullName & "] IS NOT NULL OR [" & OHFColumnName & "] IS NOT NULL;"

    'Create RecordSet
    Dim Rst As ADODB.Recordset: Set Rst = New ADODB.Recordset
    If OpenRecordset(Rst, request_SQL, Cnx) Then
        Err.Raise vbObjectError + 518, Description:=Error518
    End If

Private Function OpenRecordset(ByRef Rst As ADODB.Recordset, ByVal request_SQL As String, ByRef Cnx As ADODB.Connection) As Boolean
    'Error Trapping for the RecordSet
    myCallStack.Push "MonthStats.OpenRecordset"
    Dim backupRequestString As String
    On Error Resume Next
    Rst.Open request_SQL, Cnx, adOpenStatic, adLockReadOnly, adCmdText
    If Err.Number = 0 Then
        OpenRecordset = False
        myCallStack.Pop
        Exit Function
    Else
        Rst.Close
        OpenRecordset = True
        myCallStack.Pop
        Exit Function
    End If
    myCallStack.Pop
End Function

失败尝试:

我尝试在 C# 中使用 Adodb。这失败@ cnx.Open(connectionString);。

using ADODB;

 internal static BreastFeedingData GetXlFileData(string fileName)
        {
            try
            {
                string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" + fileName +
                    ";Extended Properties='Excel 12.0 xml;HDR=Yes;IMEX=1;Readonly=False'";
                Connection cnx = new Connection();
                cnx.Open(connectionString);

                Recordset rst = new Recordset();

                string headerString = $"[{MFullName}], [{MMRN}], [{MDDColumName}], [{MOHFColumnName}], [{MSTSColumnNameV}], [{MSTSColumnNameC}], [{MIRColumnName}], [{MERColumnName}]";
                string request_SQL = $"SELECT {headerString} FROM [{MNewbornsWS}$] WHERE [{MFullName}] IS NOT NULL OR [{MOHFColumnName}] IS NOT NULL;";

                rst.Open(request_SQL, cnx, CursorTypeEnum.adOpenStatic, LockTypeEnum.adLockReadOnly, 1);
                BreastFeedingData breastFeedingData = ReadFromData(rst);
                rst.Close();
                return breastFeedingData;
            }
            catch (System.Runtime.InteropServices.COMException)
            {
                throw;
            }
        }

我也尝试过这个,运行 问题 @ cmd.Fill(excelDataSet);

private static TStats GetOpenXlFileData(DateTime dateTime, string fileName)
        {
            string connectionString = string.
                Format("Provider=Microsoft.ACE.OLEDB.12.0; data source={0}; " +
                "Extended Properties='Excel 12.0; HDR = Yes; IMEX = 1; Readonly = False'", fileName);

            OleDbConnection con = new System.Data.OleDb.OleDbConnection(connectionString);

            string headerString = $"[{MFullName}], [{MMRN}], [{MOHFColumnName}], [{MSTSColumnNameV}], [{MSTSColumnNameC}], [{MIRColumnName}], [{MERColumnName}]";
            string request_SQL = string.Format("SELECT {0} FROM [{1}$] WHERE [{2}] IS NOT NULL OR [{3}] IS NOT NULL;",
                headerString, MNewbornsWS, MFullName, MOHFColumnName);

            OleDbDataAdapter cmd = new System.Data.OleDb.OleDbDataAdapter(request_SQL, con);

            con.Open();
            System.Data.DataSet excelDataSet = new DataSet();
            cmd.Fill(excelDataSet);
            DataTable data = excelDataSet.Tables[0];
            TStats stats = ReadFromData(data, dateTime);
            con.Close();
            return stats;
        }

我不确定我的问题是在我的代码本身还是在我的 VS 设置中。如果需要更多信息,请告诉我。预先感谢您在帮助我解决此问题时可能提供的任何帮助。

The workbooks that are being read from need to remain closed.

试试我快速编写的这个基本函数。这是在 VB.Net.

xlsFile 是带路径的封闭 excel 文件名,ShName 是 sheet 名称。

Private Function LoadFromFile(xlsFile As String, ShName As String) As DataTable
    Dim dt As DataTable = Nothing

    '~~> Get the file data in the datatable
    Try
        '~~> Get data from file
        Using MyConnection As New System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" &
                                                          xlsFile &
                                                          ";Extended Properties=""Excel 12.0;HDR=No;IMEX=1""")
            MyConnection.Open()

            Dim SheetName As String = ShName & "$"

            Using MyCommand As New OleDb.OleDbDataAdapter("select * from [" & SheetName & "]", MyConnection)
                dt = New DataTable
                MyCommand.Fill(dt)
            End Using
        End Using
    Catch ex As Exception
        MessageBox.Show(ex.Message, "System Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try

    Return dt
End Function

Access database engine could not find the object 'Newborns_3$'. this is the correct name of the worksheet I am looking for. – Courtland9777 48 mins ago

久经考验

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim tmpdt As DataTable

        tmpdt = LoadFromFile("C:\Users\routs\Desktop\book1.xlsx", "Newborns_3")

        MessageBox.Show (tmpdt.Rows.Count)
    End Sub

    Private Function LoadFromFile(xlsFile As String, ShName As String) As DataTable
        Dim dt As DataTable = Nothing

        '~~> Get the file data in the datatable
        Try
            '~~> Get data from file
            Using MyConnection As New System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" &
                                                              xlsFile &
                                                              ";Extended Properties=""Excel 12.0;HDR=No;IMEX=1""")
                MyConnection.Open()

                Dim SheetName As String = ShName & "$"

                Using MyCommand As New OleDb.OleDbDataAdapter("select * from [" & SheetName & "]", MyConnection)
                    dt = New DataTable
                    MyCommand.Fill (dt)
                End Using
            End Using
        Catch ex As Exception
            MessageBox.Show(ex.Message, "System Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

        Return dt
    End Function
End Class