Помощь в открытии соединения из проекта Excel C # VSTO с закрытым файлом .xlsx (без открытия файла .xlsx) - PullRequest
4 голосов
/ 03 апреля 2019

Я пытаюсь преобразовать надстройку Excel, которую я написал в VBA, в C # VSTO.Будучи довольно новым для C # и VS, мне показалось, что это хороший способ расширить мои навыки без необходимости придумывать новую идею проекта.

Одна из особенностей оригинального AddIn заключается в том, что он может читать несколько закрытых файлов .xlsx.рабочие книги в память, выполнить некоторые основные математические операции и вывести новые данные в новую рабочую книгу.Первоначально это было достигнуто с помощью Adodb.Connection.В настоящее время я не могу реплицировать соединение с книгами в надстройке VSTO.

Книги, которые читаются из-за необходимости оставаться закрытыми.Каждая рабочая тетрадь имеет от трех до пяти рабочих листов, но мне требуются данные только от одной из них, которая имеет статическое имя.У столбцов есть заголовки, но они не очень дружелюбны, как, например, «Эксклюзив? (1 = Да, 0 = Нет)» или «Дата выгрузки | Отображение времени».Имена столбцов являются статическими, а номера столбцов - нет.Кроме того, я имею дело только с небольшими объемами данных в каждой книге.

До сих пор я рассматривал несколько различных вариантов.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

Неудачные попытки:

Моя попытка использовать Adodb вC #.Это не удалось @ 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Пожалуйста, дайте мне знать, если требуется дополнительная информация.Заранее благодарим за любую помощь, которую вы могли бы оказать, помогая мне решить эту проблему.

1 Ответ

3 голосов
/ 03 апреля 2019

Книги, которые читаются из, должны оставаться закрытыми.

Попробуйте эту основную функцию, которую я быстро написал. Это в VB.Net.

xlsFile - это закрытое имя файла Excel с путем, а ShName - это имя листа.

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 не удалось найти объект 'Newborns_3 $'. это правильное название листа, который я ищу. - Courtland9777 48 минут назад

Испытано и проверено

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...