2013-09-04 7 views
5

Próbuję wykonać eksport do programu Excel z aplikacji VB.NET (Windows Forms).Eksport programu Excel bez interopu

Niestety, nie mogę korzystać z Office Interops, ponieważ aplikacja powinna działać na każdym komputerze - nawet jeśli nie ma zainstalowanego programu Excel.

znalazłem następującą próbkę na netto:

Public Sub ExportDatasetToExcel(ByVal ds As DataSet, Optional ByVal strHeader As String = "Save As") 

    'Proudly copied from: 
    'http://www.daniweb.com/software-development/vbnet/threads/368400/write-into-excel-using-oledb-connection#post1583200 

    Dim fileSave As New SaveFileDialog() 

    fileSave.Filter = "Excel 97-2003 Workbook (*.xls)|*.xls" 
    fileSave.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) 
    fileSave.Title = strHeader 
    fileSave.ShowDialog() 

    Dim xlsFilePath As String = fileSave.FileName 

    If xlsFilePath = "" Then 
     Exit Sub 
    End If 

    System.IO.File.Copy(storagePath & "\" & "empty.xls", xlsFilePath) 

    Cursor.Current = Cursors.WaitCursor 

    Dim conn As New OleDb.OleDbConnection(String.Format("provider=Microsoft.Jet.OLEDB.4.0; Data Source='{0}';" & "Extended Properties='Excel 8.0;HDR=YES;'", xlsFilePath)) 

    conn.Open() 

    Dim strTableQ(ds.Tables.Count) As String 

    Dim i As Integer = 0 

    'making table query 
    For i = 0 To ds.Tables.Count - 1 

     strTableQ(i) = "CREATE TABLE [" & ds.Tables(i).TableName & "](" 

     Dim j As Integer = 0 
     For j = 0 To ds.Tables(i).Columns.Count - 1 
      Dim dCol As DataColumn 
      dCol = ds.Tables(i).Columns(j) 
      strTableQ(i) &= " [" & dCol.ColumnName & "] varchar(255) , " 
     Next 
     strTableQ(i) = strTableQ(i).Substring(0, strTableQ(i).Length - 2) 
     strTableQ(i) &= ")" 

     Dim cmd As New OleDb.OleDbCommand(strTableQ(i), conn) 
     cmd.ExecuteNonQuery() 

    Next 

    'making insert query 
    Dim strInsertQ(ds.Tables.Count - 1) As String 
    For i = 0 To ds.Tables.Count - 1 
     strInsertQ(i) = "Insert Into " & ds.Tables(i).TableName & " Values (" 
     For k As Integer = 0 To ds.Tables(i).Columns.Count - 1 
      strInsertQ(i) &= "@" & ds.Tables(i).Columns(k).ColumnName & " , " 
     Next 
     strInsertQ(i) = strInsertQ(i).Substring(0, strInsertQ(i).Length - 2) 
     strInsertQ(i) &= ")" 
    Next 

    'Now inserting data 
    For i = 0 To ds.Tables.Count - 1 
     For j As Integer = 0 To ds.Tables(i).Rows.Count - 1 
      Dim cmd As New OleDb.OleDbCommand(strInsertQ(i), conn) 
      For k As Integer = 0 To ds.Tables(i).Columns.Count - 1 
       cmd.Parameters.AddWithValue("@" & ds.Tables(i).Columns(k).ColumnName.ToString(), ds.Tables(i).Rows(j)(k).ToString()) 
      Next 
      cmd.ExecuteNonQuery() 
      cmd.Parameters.Clear() 
     Next 
    Next 
    conn.Close() 
    conn.Dispose() 
    Cursor.Current = Cursors.Default 
End Sub 

Ten kod działa i eksportuje mój zestaw danych do pliku XLS.

Problem: Nie mogę otworzyć tego pliku, gdy uruchomiony jest mój program. Wygląda na to, że mój program nadal obsługuje ten plik. Widzę to za każdym razem, gdy używam Sysinternals Process Explorer. Jeśli zamknę program, mogę otworzyć ten plik bez żadnych problemów.

Myślę, że muszę zniszczyć jakiś obiekt lub po prostu zamknąć plik. Czy ktokolwiek mógłby pomóc noobowi w osiągnięciu tego celu?

+0

W ten sposób nadal trzeba zainstalować dostawcę na komputerze. Wydaje mi się, że Jet nie jest domyślnie obecny wszędzie. Dlaczego nie przejść na OpenXml? Pliki .xlsx można teraz otwierać przy użyciu poprzedniej wersji programu Excel z pakietem zgodności. Tylko myśl ... – Chris

+0

Ditto XML - DataTable jako metoda.WriteXML. Musisz podać .Name do stołu. Użytkownik może otworzyć plik z pliku Otwórz lub przeciągnij/upuść w programie Excel. LUB utwórz plik .CSV, który Excel łatwo otworzyć. Kellerman Software ma tanią bibliotekę .Net CSV (i Excela). – rheitzman

+0

@Chris: Podoba mi się pomysł z OpenXML; gdzie mogę znaleźć próbki [noob-aware]? – Alexander

Odpowiedz

3

Nie wiem, czy to jest problem, może. Nie wyrzucaj obiektów OleDbCommand. Możliwe, że zachowuje odwołanie do pliku. Spróbuj tego:

Public Sub ExportDatasetToExcel(ByVal ds As DataSet, Optional ByVal strHeader As String = "Save As") 

    'Proudly copied from: 
    'http://www.daniweb.com/software-development/vbnet/threads/368400/write-into-excel-using-oledb-connection#post1583200 

    Using fileSave As New SaveFileDialog() 
     fileSave.Filter = "Excel 97-2003 Workbook (*.xls)|*.xls" 
     fileSave.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) 
     fileSave.Title = strHeader 

     If fileSave.ShowDialog() = Windows.Forms.DialogResult.OK Then 
      Dim xlsFilePath As String = fileSave.FileName 
      If xlsFilePath = "" Then Exit Sub 

      System.IO.File.Copy(storagePath & "\" & "empty.xls", xlsFilePath) 

      Cursor.Current = Cursors.WaitCursor 

      Using conn As New OleDb.OleDbConnection(String.Format("provider=Microsoft.Jet.OLEDB.4.0; Data Source='{0}';" & "Extended Properties='Excel 8.0;HDR=YES;'", xlsFilePath)) 
       conn.Open() 
       Dim strTableQ(ds.Tables.Count) As String 
       Dim i As Integer = 0 

       'making table query 
       For i = 0 To ds.Tables.Count - 1 
        strTableQ(i) = "CREATE TABLE [" & ds.Tables(i).TableName & "](" 

        Dim j As Integer = 0 
        For j = 0 To ds.Tables(i).Columns.Count - 1 
         Dim dCol As DataColumn 
         dCol = ds.Tables(i).Columns(j) 
         strTableQ(i) &= " [" & dCol.ColumnName & "] varchar(255) , " 
        Next 
        strTableQ(i) = strTableQ(i).Substring(0, strTableQ(i).Length - 2) 
        strTableQ(i) &= ")" 

        Using cmd As New OleDb.OleDbCommand(strTableQ(i), conn) 
         cmd.ExecuteNonQuery() 
        End Using 
       Next 

       'making insert query 
       Dim strInsertQ(ds.Tables.Count - 1) As String 
       For i = 0 To ds.Tables.Count - 1 
        strInsertQ(i) = "Insert Into " & ds.Tables(i).TableName & " Values (" 
        For k As Integer = 0 To ds.Tables(i).Columns.Count - 1 
         strInsertQ(i) &= "@" & ds.Tables(i).Columns(k).ColumnName & " , " 
        Next 
        strInsertQ(i) = strInsertQ(i).Substring(0, strInsertQ(i).Length - 2) 
        strInsertQ(i) &= ")" 
       Next 

       'Now inserting data 
       For i = 0 To ds.Tables.Count - 1 
        For j As Integer = 0 To ds.Tables(i).Rows.Count - 1 
         Using cmd As New OleDb.OleDbCommand(strInsertQ(i), conn) 
          For k As Integer = 0 To ds.Tables(i).Columns.Count - 1 
           cmd.Parameters.AddWithValue("@" & ds.Tables(i).Columns(k).ColumnName.ToString(), ds.Tables(i).Rows(j)(k).ToString()) 
          Next 
          cmd.ExecuteNonQuery() 
          cmd.Parameters.Clear() 
         End Using 
        Next 
       Next 
       conn.Close() 
       Cursor.Current = Cursors.Default 

      End Using 
     End If 
    End Using 
End Sub 

Należy również pamiętać, że form że wystawianie ShowDialog() metody musi być umieszczona zbyt.

+0

Dziękuję bardzo, działa idealnie :) – Alexander