将gridview导出为ex​​cel时缺少最后一个数据

时间:2013-08-14 08:04:05

标签: c# winforms sql-server-2008

当我将gridview导出到excel时,丢失的数据是最后一个。 这是我导出数据的代码。

private void ToCsV(DataGridView dGV, string filename)
    {
        string stOutput = "";
        // Export titles:
        string sHeaders = "";

        for (int j = 0; j < dGV.Columns.Count; j++)
            sHeaders = sHeaders.ToString() + Convert.ToString(dGV.Columns[j].HeaderText) + "\t";
        stOutput += sHeaders + "\r\n";
        // Export data.
        for (int i = 0; i < dGV.RowCount - 1; i++)
        {
            string stLine = "";
            for (int j = 1; j < dGV.Rows[i].Cells.Count; j++)
                stLine = stLine.ToString() + Convert.ToString(dGV.Rows[i].Cells[j].Value) + "\t";
            stOutput += stLine + "\r\n";
        }
        Encoding utf16 = Encoding.GetEncoding(1254);
        byte[] output = utf16.GetBytes(stOutput);
        FileStream fs = new FileStream(filename, FileMode.Create);
        BinaryWriter bw = new BinaryWriter(fs);
        bw.Write(output, 0, output.Length); //write the encoded file
        bw.Flush();
        bw.Close();
        fs.Close();
    }

这是按钮的代码。

SaveFileDialog sfd = new SaveFileDialog();
        sfd.Filter = "Excel Documents  (.xls)|*.xls";
        sfd.FileName = "";
        if (sfd.ShowDialog() == DialogResult.OK)
        {
            //ToCsV(dataGridView1, @"c:\export.xls");
            ToCsV(gvHistory, sfd.FileName); // Here dataGridview1 is your grid view name 
        }

3 个答案:

答案 0 :(得分:3)

你有

for (int i = 0; i < dGV.RowCount - 1; i++)
{
  ...
}

因此,您明确地从导出中排除最后一行 将i < dGV.RowCount - 1更改为i < dGV.RowCount


此外,代码:

string stLine = "";
for (int j = 1; j < dGV.Rows[i].Cells.Count; j++)
  stLine = stLine.ToString() + Convert.ToString(dGV.Rows[i].Cells[j].Value) + "\t";
stOutput += stLine + "\r\n";

基本上是使用StringBuilder代替string的示例。随着您获得更多行,它将逐渐变慢。更好的版本是:

StringBuilder sbOutput = new StringBuilder();

for (int j = 0; j < dGV.Columns.Count; j++)
   sbOutput.AppendLine(Convert.ToString(dGV.Columns[j].HeaderText) + "\t");
for (int i = 0; i < dGV.RowCount - 1; i++)
{
  for (int j = 1; j < dGV.Rows[i].Cells.Count; j++)
    sbOutput.Append(Convert.ToString(dGV.Rows[i].Cells[j].Value) + "\t");
  sbOutput.AppendLine();
}
Encoding utf16 = Encoding.GetEncoding(1254);
byte[] output = utf16.GetBytes(sbOutput.ToString());

接下来,当迭代集合时,您可以使用for(int i=0; i < length; i++)模式,但通常最好只使用foreach。这样你就可以确定循环所有行 - 这就是foreach根据定义所做的事情。额外的好处是循环变量具有更好的名称,即row而不是dGV.Rows[i]。所以代码将是:

foreach(var column in dGV.Columns)
   sbOutput.AppendLine(Convert.ToString(column.HeaderText) + "\t");

foreach (var row in dGV.Rows)
{
  foreach (var cell in row.Cells)
    sbOutput.Append(Convert.ToString(cell.Value) + "\t");
  sbOutput.AppendLine();
}
Encoding utf16 = Encoding.GetEncoding(1254);
byte[] output = utf16.GetBytes(sbOutput.ToString());

这种方式更具可读性,更不容易出现愚蠢的“一对一”错误。


最后,一个挑剔点:该方法称为ToCsv,但这些值不是以逗号分隔,而是以制表符分隔的值。这并不是一种冒犯,因为,不知何故,术语“CSV”已经演变为任何行在单独的行上的格式,并且行中的值以某种方式分开,但仍然,tab - 分离值是一件事。

答案 1 :(得分:0)

尝试在循环中使用<=而不是<

答案 2 :(得分:0)

看起来你正在切断dGV中的最后一项。

    // Export data.
    for (int i = 0; i < dGV.RowCount - 1; i++)

应该是

    // Export data.
    for (int i = 0; i < dGV.RowCount; i++)