2012-07-31 45 views
5

¿Cuál es la forma más rápida de exportar filas de DataGridView en el rango de 460328 a 800328 a Excel o en una tabla de base de datos de SQL Server sin usar Microsoft Office La interoperabilidad como interoperabilidad es bastante lenta y pesada en los recursos del sistema.¿Cuál es la forma más rápida de exportar filas de dataGridView a Excel o a una base de datos de SQL Server?

+0

la manera * más rápida *? O, la * primera * manera? –

+0

Excel y SQL son objetivos muy diferentes y requieren soluciones diferentes. Por favor, puede ser más específico, p. ¿Sería suficiente CSV para Excel? ¿Puede entonces importar a granel los datos en SQL Server? ¿Es este un ejercicio de una vez o lo necesita repetidamente? – StuartLC

+0

Vea esto http://stackoverflow.com/questions/10248361/c-sharp-write-datagridview-data-into-a-sql-table o este http://stackoverflow.com/questions/5022531/best-way- to-bulk-insert-from-ac-sharp-datatable para sql. Hacer inserciones fila por fila será lento para grandes conjuntos de datos. –

Respuesta

7

Para exportar a Excel, si no está utilizando el XML basado en 2007 o 2010, Interop es prácticamente el único camino a seguir. Aunque no es tan malo como su reputación. Enumeraré algunas soluciones.

1 a Excel

Primera añadir una referencia de componente Microsoft.Office.Interop.Excel a su proyecto. Esto debería estar bajo la pestaña .NET en Proyecto -> Agregar referencia. agregue la instrucción using a su formulario:

usando Excel = Microsoft.Office.Interop.Excel;

agregar un control de botón, y añadir este código para que el cuerpo:

private void btnExport_Click(object sender, EventArgs e) 
    { 

     Excel.Application app = new Excel.Application(); 
     app.Visible = true; 
     Excel.Workbook wb = app.Workbooks.Add(1); 
     Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets[1]; 
     // changing the name of active sheet 
     ws.Name = "Exported from gridview"; 

     ws.Rows.HorizontalAlignment = HorizontalAlignment.Center; 
     // storing header part in Excel 
     for (int i = 1; i < dataGridView1.Columns.Count + 1; i++) 
     { 
      ws.Cells[1, i] = dataGridView1.Columns[i - 1].HeaderText; 
     } 


     // storing Each row and column value to excel sheet 
     for (int i = 0; i < dataGridView1.Rows.Count - 1; i++) 
     { 
      for (int j = 0; j < dataGridView1.Columns.Count; j++) 
      { 
       ws.Cells[i + 2, j + 1] = dataGridView1.Rows[i].Cells[j].Value.ToString(); 
      } 
     } 

     // sizing the columns 
     ws.Cells.EntireColumn.AutoFit(); 

     // save the application 
     wb.SaveAs("c:\\output.xls",Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive , Type.Missing, Type.Missing, Type.Missing, Type.Missing); 

     // Exit from the application 
     app.Quit(); 
    } 
} 

2 - a SQL Server

Esto no requiere de interoperabilidad. Para facilitar el uso, pase su objeto List al evento que ejecuta las inserciones. Si tiene tablas configuradas para que se correspondan con su columna de vista de cuadrícula, es fácil. Aquí, uso un sproc.

private void btnToSQL_Click(object sender, EventArgs e) 
    { 
     string connStr = @"Data Source=(local)\sqlexpress;Initial Catalog=rTALIS;Integrated Security=True"; 
     var cn = new SqlConnection(connStr); 
     var cm = new SqlCommand("exec usp_InsertRecord", cn); 
     cm.CommandType = System.Data.CommandType.StoredProcedure; 
     try 
     { 
      cn.Open(); 
      foreach (Row r in rows) 
      { 
       cm.Parameters.Clear(); 
       cm.Parameters.AddWithValue("@Number1", r.Number1); 
       cm.Parameters.AddWithValue("@Number2", r.Number2); 
       cm.Parameters.AddWithValue("@Number3", r.Number3); 
       cm.Parameters.AddWithValue("@Number4", r.Number4); 
       cm.Parameters.AddWithValue("@Number5", r.Number5); 
       cm.Parameters.AddWithValue("@Number6", r.Number6); 
       cm.Parameters.AddWithValue("@Number7", r.Number7); 
       cm.Parameters.AddWithValue("@Date1", r.Date1); 
       cm.ExecuteNonQuery(); 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
     finally 
     { 
      cn.Close(); 
     } 
    } 

Dejarme saber si necesito modificar esto para usted. En el ejemplo original, tenía List rows = new List(); declarado en el método form_Load. Esto funcionó para esa solución, pero su alcance ahora es demasiado limitado. Lo he movido hacia arriba o hacia afuera en la clase, de modo que se puede llamar a cualquier parte del formulario (específicamente btnToSQL_Click). He comentado un vistazo a continuación:

List<Row> rows = new List<Row>(); 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     //var rows = new List<Row>(); //limited scope 
     var sr = new StreamReader(@"C:\so_test.txt"); 
     while (!sr.EndOfStream) 
     { 
      string s = sr.ReadLine(); 
      if (!String.IsNullOrEmpty(s.Trim())) 
      { 
       rows.Add(new Row(s)); 
      } 
     } 
     sr.Close(); 
     dataGridView1.DataSource = rows; 
    } 
+2

Lea la pregunta nuevamente. OP escribió: 'sin usar la interoperabilidad de Microsoft Office ya que la interoperabilidad es bastante lenta y pesada'' – Reniuz

+0

Sí, tienes razón. Sacando mi bolígrafo rojo. – GrayFox374

1

Una opción sería escribir datos en un archivo CSV en lugar de en un archivo de Excel. Excel no tendría problemas para leerlo después.

Si no está familiarizado, en archivos CSV (es decir, separados por comas) los campos están separados por comas y las filas están separadas por líneas nuevas (\n o \r\n).

Algo así (no puede compilar!):

private void WriteData() { 
    using (var file = System.IO.StreamWriter(@"C:\Path\To\File.csv")) { 
     foreach (var row in dataGrid.Rows) { 
      foreach (var cell in row.Cells) { 
       // Note that if some cells contain commas, 
       // you'd need to wrap them in quotes. 
       file.Write(cell.Value).Write(","); 
      } 
     } 
     file.Write("\n"); 
    } 
} 

Para obtener un rendimiento más rápido, sino que también puede ser una buena idea recoger unos pocos cientos (o miles) filas en una sola cadena y luego escribir a una archivo, en lugar de escribir celda por celda.

+0

StreamWriter almacenará el buffer internamente de todos modos, por lo que escribir algunos caracteres a la vez no debería ser un problema http://stackoverflow.com/questions/2001596/c-sharp-streamwriter-when-is-stream-physically-written-to -file – StuartLC

+0

@nonnb: ¡Gracias! No lo sabía – ikh

+0

Obtiene los datos de un archivo TSV (separado por tabuladores), por lo que esto no lo ayudará; él estaría de vuelta donde comenzó. Este era su anterior? : http://stackoverflow.com/questions/11720787/how-can-i-correctly-parse-a-text-file-delimited-by-white-space/11723728 – GrayFox374

1

Para transferir a Excel, este es el método más rápido que he encontrado (aunque no utilizar Office InterOp). Pasa por cada celda en DataGridView y asígnala a una matriz de objetos. A continuación, asigne la matriz completa a un rango de Excel. Esto es mucho más rápido que asignar un valor a cada celda de Excel individualmente porque solo invoca InterOp una vez. Perdonar a la VB:

Sub Export() 
    Dim xlApp As New Excel.Application 
    Dim wb As Excel.Workbook = xlApp.Workbooks.Add 
    Dim ws As Excel.Worksheet = wb.Worksheets(1) 
    Dim dgv as DataGridView = MyDataGridView 

    Dim ExportArray(dgv.Rows.Count, dgv.Columns.Count - 1) As Object 
    Dim j, i As Integer 

    For j = 0 To dgv.Columns.Count - 1 
     ExportArray(0, j) = dgv.Columns(j).Name 
     For i = 1 To dgv.Rows.Count 
      ExportArray(i, j) = dgv(j, i - 1).Value 
     Next 
    Next 

    Dim col As String = ColNumtoLetter(j) 
    ws.Range("A1:" & col & i).Value = ExportArray 
End Sub 

Private Function ColNumtoLetter(ByVal iCol As Integer) As String 
    Dim Result As String = "" 

    Dim iAlpha As Integer = Int(iCol/26.001) 
    Dim iRemainder As Integer = iCol - (iAlpha * 26) 

    If iAlpha > 0 Then 
     Result = Chr(iAlpha + 64) 
    End If 
    If iRemainder > 0 Then 
     Result = Result & Chr(iRemainder + 64) 
    End If 

    Return Result 
End Function 

El segundo método simplemente traduce el número de la columna final al nombre de columna de Excel correspondiente. Para obtener más información, consulte "Fast Exporting from DataSet to Excel" y "Export Data to Excel Much Faster".

2

Consulte Create Excel files from C# without office, ya que esto se refiere al uso de EPPlus, que funciona muy bien. Pude crear mis datos CSV de la tabla de datos y la carga masiva en la memoria del archivo de Excel para transmitir. Simplemente unas pocas líneas de código. Varible csvData es el valor de cadena de todos sus csvData.

using(ExcelPackage pck = new ExcelPackage()) 
    { 
     //Create the worksheet 
     ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Sheet1"); 

     // set the delimiter 
     etf.Delimiter = ','; 
     etf.EOL = "\n"; 
     etf.TextQualifier = "\""; 

     //Load the datatable into the sheet, starting from cell A1. Print the column names on row 1 
     ws.Cells["A1"].LoadFromText(csvData, etf); 
     return pck.GetAsByteArray(); 
    } 
1

Aquí utilicé DataTable para escribir datos en el archivo de Excel. Creo que la vista de cuadrícula de datos también es similar a la DataTable.

En primer lugar obtener datos de la base de datos:

db.GetData(sqlgetprint); 

Es llamada para el método que el método es:

class DataBaseConnection 
{ 
    private OdbcConnection conn1 = new OdbcConnection(@"FILEDSN=C:/OTPub/Ot.dsn;" + "Uid=sa;" + "[email protected];"); //"DSN=Ot_DataODBC;" + "Uid=sa;" + "[email protected];" 

    //select 
    public System.Data.DataTable GetData(string sql) 
    { 
     try 
     { 

      conn1.Open(); 
      OdbcDataAdapter adpt = new OdbcDataAdapter(sql, conn1); 
      DataTable dt = new DataTable(); 
      adpt.Fill(dt); 
      conn1.Close(); 
      return dt; 

     } 
     catch (Exception ex) 
     { 
      conn1.Close(); 
      throw ex; 
     } 
    }  
} 

Después de eso objeto crear para DataBaseConncetion clase en su forma de trabajo

DataBaseConnection db = new DataBaseConnection(); 

En su evento de clic de botón puede escribir este código para escribir en el archivo de Excel

string sqlgetprint = "SELECT Service_No,Full_name, Acc_No, OP_date, On_time, Off_time, OP_hours, Payment FROM Print_Op ORDER BY Service_No , OP_date"; 
      DataTable dtall = db.GetData(sqlgetprint); 

      SaveFileDialog saveFileDialog1 = new SaveFileDialog(); 
      saveFileDialog1.Filter = "Excel Documents (*.xls)|*.xls"; 
      saveFileDialog1.FileName = "Employee Details.xls"; 

      if (saveFileDialog1.ShowDialog() == DialogResult.OK) 
      { 
       string fname = saveFileDialog1.FileName; 


       StreamWriter wr = new StreamWriter(fname); 
       for (int i = 0; i < dtall.Columns.Count; i++) 
       { 
        wr.Write(dtall.Columns[i].ToString().ToUpper() + "\t"); 
       } 

       wr.WriteLine(); 

       //write rows to excel file 
       for (int i = 0; i < (dtall.Rows.Count); i++) 
       { 
        for (int j = 0; j < dtall.Columns.Count; j++) 
        { 
         if (dtall.Rows[i][j] != null) 
         { 
          wr.Write(Convert.ToString(dtall.Rows[i][j]) + "\t"); 
         } 
         else 
         { 
          wr.Write("\t"); 
         } 
        } 
        //go to next line 
        wr.WriteLine(); 
       } 
       //close file 
       wr.Close(); 
       if (File.Exists(fname)) 
       { 
        System.Diagnostics.Process.Start(fname); 
       } 

      } 
     } 

     catch (Exception) 
     { 

      MessageBox.Show("Error Create Excel Sheet!"); 
     } 
Cuestiones relacionadas