7

相互運用は非常に遅く、システムリソースに負担がかかるため、Microsoft Office相互運用を使用せずに、460328〜800328の範囲のDataGridView行をExcelまたはSQL Serverデータベーステーブルにエクスポートする最速の方法は何ですか?

4

7 に答える 7

8

Excelにエクスポートする場合、XMLベースの2007または2010を使用していない場合は、Interopがほとんど唯一の方法です。評判ほど悪くはありませんが。いくつかの解決策をリストします。

1Excelへ

まず、Microsoft.Office.Interop.Excelコンポーネント参照をプロジェクトに追加します。これは、[プロジェクト]->[参照の追加]の[.NET]タブにあるはずです。フォームにusingステートメントを追加します。

Excelを使用=Microsoft.Office.Interop.Excel;

ボタンコントロールを追加し、このコードを本体に追加します。

    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-SQLServerへ

これには相互運用は必要ありません。使いやすくするために、挿入を実行するイベントにListオブジェクトを渡します。グリッドビューの列に対応するようにテーブルを設定している場合は、簡単です。ここでは、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();
        }
    }

これを微調整する必要がある場合はお知らせください。元の例では、List rows = new List();がありました。form_Loadメソッドで宣言されています。これはそのソリューションでは機能しましたが、範囲が制限されすぎています。私はそれをクラスに上/外に移動したので、フォームのどこからでもinを呼び出すことができます(具体的にはbtnToSQL_Click)。私はそれを以下にコメントアウトしました:

    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;
    }
于 2012-07-31T14:53:50.800 に答える
3

Excelに転送する場合、これは私が見つけた最速の方法です(ただし、Office InterOpを使用します)。DataGridViewの各セルをループして、オブジェクトの配列に割り当てます。次に、配列全体をExcel範囲に割り当てます。これは、InterOpを1回だけ呼び出すため、各Excelセルに個別に値を割り当てるよりもはるかに高速です。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

2番目の方法は、最終的な列番号を対応するExcelの列名に変換するだけです。

詳細については、「DataSetからExcelへの高速エクスポート」および「 Excelへのデータのエクスポートを大幅に高速化」を参照してください。

于 2014-05-20T13:40:58.100 に答える
2

これは非常にうまく機能するEPPlusの使用を指しているため、 OfficeなしでC#からExcelファイルを作成するを確認してください-データテーブルからCSVデータを作成し、Excelファイルをメモリに大量にロードしてストリーミングすることができました。ほんの数行のコード。可変csvDataは、すべての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( );
   }
于 2014-07-25T01:20:46.917 に答える
1

1つのオプションは、ExcelファイルではなくCSVファイルにデータを書き込むことです。Excelは後でそれを読むのに問題はありません。

よく知らない場合は、CSV(つまりコンマ区切り)ファイルでは、フィールドはコンマで区切られ、行は改行(\nまたは\r\n)で区切られます。

次のようなもの(コンパイルされない可能性があります!):

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");
    }
}

パフォーマンスを向上させるには、セルごとに書き込むのではなく、数百(または数千)行を1つの文字列に集めて、それをファイルに書き込むこともお勧めします。

于 2012-07-31T14:36:05.833 に答える
1

ここでは、DataTableを使用してExcelファイルにデータを書き込みました。データグリッドビューもDataTableと同じだと思います。

最初にデータベースからデータを取得します。

db.GetData(sqlgetprint);

メソッドの呼び出しは次のとおりです。

class DataBaseConnection
{
    private OdbcConnection conn1 = new OdbcConnection(@"FILEDSN=C:/OTPub/Ot.dsn;" + "Uid=sa;" + "Pwd=otdata@123;"); //"DSN=Ot_DataODBC;" + "Uid=sa;" +  "Pwd=otdata@123;"

    //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;
        }
    }    
}

その後、作業フォームにDataBaseConncetionクラスのオブジェクトを作成します

 DataBaseConnection db = new DataBaseConnection();

ボタンクリックイベントで、このコードを記述して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!");
        }
于 2017-03-17T06:22:43.650 に答える
0

これはより速い方法かもしれません、

    using Excel = Microsoft.Office.Interop.Excel;

    public static void SaveGridToExcel(DataGridView DGV)
    {

        if (DGV.Rows.Count > 0)
        {
            string filename = "";
            SaveFileDialog SV = new SaveFileDialog();
            SV.Filter = "EXCEL FILES|*.xlsx;*.xls";
            DialogResult result = SV.ShowDialog();


            if (result == DialogResult.OK)
            {

                filename = SV.FileName;
                bool multiselect = DGV.MultiSelect;
                DGV.MultiSelect = true;
                DGV.SelectAll();
                DGV.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText;
                Clipboard.SetDataObject(DGV.GetClipboardContent());
                var results = System.Convert.ToString(Clipboard.GetData(DataFormats.Text));
                DGV.ClearSelection();
                DGV.MultiSelect = multiselect;
                Microsoft.Office.Interop.Excel.Application XCELAPP = null;
                Microsoft.Office.Interop.Excel.Workbook XWORKBOOK = null;
                Microsoft.Office.Interop.Excel.Worksheet XSHEET = null;
                object misValue = System.Reflection.Missing.Value;
                XCELAPP = new Excel.Application();
                XWORKBOOK = XCELAPP.Workbooks.Add(misValue);
                XCELAPP.DisplayAlerts = false;
                XCELAPP.Visible = false;
                XSHEET = XWORKBOOK.ActiveSheet;
                XSHEET.Paste();
                XWORKBOOK.SaveAs(filename, Excel.XlFileFormat.xlOpenXMLWorkbook);
                XWORKBOOK.Close(false);
                XCELAPP.Quit();
                try
                {                      
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(XSHEET);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(XWORKBOOK);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(XCELAPP);
                }
                catch { }
            }
        }
    }
于 2018-12-04T05:16:24.093 に答える
0

私にとって、速度を上げるための最善の改善は、この方法を使用することでした。

private const string connectionString = "OLEDB;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Data Source=MYDBSERVER;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=SERVERID;Use Encryption for Data=False;Tag with column collation when possible=False;Initial Catalog=DBName"; 

object misValue = System.Reflection.Missing.Value;
Excel.Application xlsApp = new Excel.Application();
Excel.Workbook xlsWorkbook = xlsApp.Workbooks.Add(misValue);
Excel.Worksheet myWS = xlsWorkbook.Sheets[1];

 Excel.ListObject lo = myWS.ListObjects.AddEx(Excel.XlListObjectSourceType.xlSrcQuery, connectionString, true, 
 Excel.XlYesNoGuess.xlGuess, myWS.Range["A5"]);
 
//A5 is the starting cell

lo.QueryTable.CommandText = "SELECT * FROM TABLE";
lo.Refresh();

「for」ループ(各セルの書き込み)を使用してDataReader / Datatableを試しましたが、どちらも5800行(および40列)のクエリの回復に時間がかかりすぎました。数字で:

DataReader-5:16分
この方法-13秒

于 2021-08-22T17:39:06.860 に答える