2013-09-04 13 views
5

Sto cercando di realizzare l'esportazione in Excel da un (Windows Form) applicazioni VB.NET.Excel esportare senza Interop

Purtroppo, non posso utilizzare Office Interops perché l'applicazione dovrebbe funzionare su ogni macchina - anche se non è installato alcun Excel.

ho trovato il seguente esempio in Rete:

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 

Questo codice funziona ed esporta il mio set di dati in un file .xls.

Il problema: non posso aprire questo file, mentre il mio programma è in esecuzione. Sembra che il mio programma abbia ancora un handle su questo file. Posso vederlo ogni volta che utilizzo Sysinternals Process Explorer. Se chiudo il mio programma, posso aprire questo file senza problemi.

penso di avere a distruggere qualche oggetto o semplicemente chiudere il file. Per favore qualcuno potrebbe aiutare un noob a realizzarlo?

+0

Con questo modo, è comunque necessario avere il provider installato sulla macchina. Mi sembra che Jet non sia presente ovunque per impostazione predefinita. Perché non passare a OpenXml? I file .xlsx possono ora essere aperti con la versione precedente di Excel con il pacchetto di compatibilità. Solo un pensiero ... – Chris

+0

Ditto XML - il DataTable come metodo .WriteXML. Devi fornire un .Name al tavolo. L'utente può aprire il file da File Apri o trascinare/rilasciare su Excel. OPPURE creare un file .CSV che Excel possa aprire facilmente. Kellerman Software ha una libreria CSV (ed Excel I think) a buon mercato. – rheitzman

+0

@Chris: mi piace l'idea con OpenXML; dove posso trovare alcuni campioni [noob-aware]? – Alexander

risposta

3

Non so se questo è il problema, potrebbe. Non smaltire gli oggetti OleDbCommand. È possibile che mantenga un riferimento al file. Prova questo:

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 

Si noti inoltre che un form che si visualizzano con ShowDialog() metodo devono essere smaltiti troppo.

+0

Grazie mille, funziona perfettamente :) – Alexander

Problemi correlati