簡體   English   中英

使用 spire.XLS 和 C# 將選定行從 datagridview 導出到 excel

[英]Export selected rows from datagridview to excel using spire.XLS & C#

我正在嘗試使用 spire.XLS 將 windows 表單應用程序上手動選擇的 datagridview 行導出到 excel 文件,並在最后一行中添加最后一列的總和。 datagridview 數據如下:

dgv

當我在選擇第一行和最后一行后運行代碼時,excel 應該如下所示: 擅長

這是我的代碼:

        void ExportBtnXLSXClick(object sender, EventArgs e)
    {
        Workbook book = new Workbook();
        Worksheet sheet = book.Worksheets[0];
        sheet.Name = "Exported from gridview";
        
        //Convert data from datagridview to datatable
        DataTable dt=GetDgvToTable(dataGridView1);

        //Export datatable to excel
        sheet.InsertDataTable(dt, true, 1, 1, -1, -1);
        //sheet.InsertDataTable(dt, true, 1, 1, true);
        sheet.Range[1,1,sheet.LastRow,sheet.LastColumn].AutoFitColumns();
        sheet.AllocatedRange.BorderAround(LineStyleType.Thin, borderColor:ExcelColors.Black);
        sheet.AllocatedRange.BorderInside(LineStyleType.Thin, borderColor:ExcelColors.Black);
        
        book.SaveToFile(@"C:\Users\Tamal\Desktop\Spire.XLS C#\Report.xlsx", ExcelVersion.Version2013);
        book.Dispose();
        MessageBox.Show("Export complete");
    }

使用輔助方法

        public DataTable GetDgvToTable(DataGridView dgv)
    {
        DataTable dt = new DataTable();

        //Column
        for (int count = 0; count < dgv.Columns.Count; count++)
        {
            DataColumn dc = new DataColumn(dgv.Columns[count].Name.ToString());
            dt.Columns.Add(dc);
        }

        //Row
        for (int count = 0; count < dgv.SelectedRows.Count; count++)
        {
            DataRow dr = dt.NewRow();
            for (int countsub = 0; countsub < dgv.Columns.Count; countsub++)
                //for (int countsub = 0; countsub < dgv.SelectedRows.Count; countsub++)
            {
                dr[countsub] = Convert.ToString(dgv.Rows[count].Cells[countsub].Value);
            }
            dt.Rows.Add(dr);
        }
        decimal total = dataGridView1.SelectedRows.OfType<DataGridViewRow>()
            .Sum(t => Convert.ToDecimal(t.Cells[2].Value));
        dt.Rows.Add(total);
        return dt;
    }

但它沒有顯示我選擇的兩行,並且總和顯示在 excel 的最后一行的第一列。 我怎樣才能得到想要的結果?

此外,如果我多次運行代碼,則數據不應覆蓋,而只是在最后填充的行之后粘貼數據,最好在其間保留一行空白。

下面是 datagridview 的樣子: dgv

請幫忙

您在這里有多個問題。 對於初學者,如果您想將多個選擇添加到同一個工作簿,那么您需要做一些不同的事情......

  1. 檢查文件是否已經存在,如果不存在,則創建一個新文件,如果存在則需要“打開”它。

  2. 如果文件已經存在,那么在打開文件后,您需要檢查“從 gridview 導出”工作表是否存在……如果確實存在,那么您需要找到最后使用的行並開始添加其他行在最后一行之后。

  3. 最后保存文件。

目前,代碼只是簡單地“創建”一個新工作簿,然后代碼覆蓋現有工作簿(如果它已經存在)。 因此,如果您想向“相同”工作簿“添加”其他選擇,則需要添加檢查文件是否存在的代碼,如果存在,則在工作表上找到下一個可用行以將其他項目添加到如上述前 3 個步驟所述。

下面是一個簡單的示例,但它沒有經過很好的測試,我相信您可能需要調整代碼以滿足您的要求。

首先,在GetDgvToTable方法中,似乎代碼在創建表時抓取了錯誤的行……。

for (int count = 0; count < dgv.SelectedRows.Count; count++)
{
  DataRow dr = dt.NewRow();
  for (int countsub = 0; countsub < dgv.Columns.Count; countsub++)
    //for (int countsub = 0; countsub < dgv.SelectedRows.Count; countsub++)
    {
      dr[countsub] = Convert.ToString(dgv.Rows[count].Cells[countsub].Value);
    }
    dt.Rows.Add(dr);
}

上面,代碼循環通過“選定的行數”。 問題出在一線……

dr[countsub] = Convert.ToString(dgv.Rows[count].Cells[countsub].Value);

具體來說,在……

dgv.Rows[count].

這里的代碼忽略了“SELECTED”行。 換句話說,如果“選定”行是從“第一”行 (0) 開始的連續“選定”行,那么它將起作用。 不幸的是,第一個“選定”行不一定是網格中的“第一”行。 代碼錯誤地做出了這個假設。

要解決此問題,我建議您使用foreach循環遍歷網格SelectedRows集合來遍歷“選定”行。 這將確保代碼使用“SELECTED”行。 代碼更改看起來像……

foreach (DataGridViewRow row in dgv.SelectedRows) {
  DataRow dr = dt.NewRow();
  for (int i = 0; i < row.Cells.Count; i++) {
    dr[i] = row.Cells[i].Value.ToString();
  }
  dt.Rows.Add(dr);
}

接下來,您希望將其他選擇添加到同一個工作表中,並且選擇之間有一個空行。 這在前面已經討論過了。 在下面的代碼中,它檢查 Excel 文件是否已經存在,如果存在,則打開該文件。 接下來檢查工作表是否已經存在。 如果它不存在,則創建一個新的。

接下來檢查是否已將任何“先前”選擇添加到工作表中。 我對 Spire 不是很熟悉,但是,我注意到如果您調用該方法......

sheet.LastRow…

它將返回下一個可用行……除非工作表為空。 當工作表為空時,這將返回一個類似 65,570 的值。 我將把這個留給你,以便找出一種更優雅的方式來獲取下一個空行。 在這種情況下,我只是檢查了sheet.LastRow是否超過 60000。如果值超過 60000,那么我假設工作表是空的,只需將下一個可用行設置為 1。我相信有更好的方法來做到這一點.

鑒於這一切,通過將附加選擇添加到先前選擇“下方”的同一工作表中,對這兩種方法的以下更改似乎可以按照您的意願進行。

public DataTable GetDgvToTable(DataGridView dgv) {
  DataTable dt = new DataTable();
  //Column
  for (int count = 0; count < dgv.Columns.Count; count++) {
    DataColumn dc = new DataColumn(dgv.Columns[count].Name.ToString());
    dt.Columns.Add(dc);
  }
  //Row
  foreach (DataGridViewRow row in dgv.SelectedRows) {
    DataRow dr = dt.NewRow();
    for (int i = 0; i < row.Cells.Count; i++) {
      dr[i] = row.Cells[i].Value.ToString();
    }
    dt.Rows.Add(dr);
  }
  decimal total = dataGridView1.SelectedRows.OfType<DataGridViewRow>()
      .Sum(t => Convert.ToDecimal(t.Cells[2].Value));
  dt.Rows.Add("","Total",total);
  return dt;
}

然后更改導出方法。

private void btnExportToExcel_Click(object sender, EventArgs e) {
  Workbook book = new Workbook();
  if (File.Exists(@"pathToFile\Report.xlsx")) {
    book.LoadFromFile(@"pathToFile\Report.xlsx");
  }
  Worksheet sheet = book.Worksheets["Exported from gridview"];
  if (sheet == null) {
    sheet = book.CreateEmptySheet("Exported from gridview");
  }
  //Convert data from datagridview to datatable
  DataTable dt = GetDgvToTable(dataGridView1);
  //Export datatable to excel
  int startRow = sheet.LastRow + 2;
  if (startRow > 60000) {
    startRow = 1;
  }
  sheet.InsertDataTable(dt, true, startRow, 1, -1, -1);
  sheet.Range[1, 1, sheet.LastRow, sheet.LastColumn].AutoFitColumns();
  sheet.AllocatedRange.BorderAround(LineStyleType.Thin, borderColor: ExcelColors.Black);
  sheet.AllocatedRange.BorderInside(LineStyleType.Thin, borderColor: ExcelColors.Black);
  book.SaveToFile(@"pathToFile\Report.xlsx", ExcelVersion.Version2013);
  book.Dispose();
  MessageBox.Show("Export complete");
}

我希望這是有道理的並有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM