将ListView项目导出到Excel(自动宽度列,第一行中的标题,隐藏某些行)

时间:2014-04-01 19:43:34

标签: c# .net listview export-to-excel excel-interop

我有一个小应用程序,我试图在按钮点击时添加一个增强功能,将表单列表视图中的所有数据导出到Excel工作表。经过大量的搜索,我在DaniWeb找到了this解决方案做得很好,但是我试图扩展它。

Excel.Application app = new Excel.Application();
app.Visible = true;
Excel.Workbook wb = app.Workbooks.Add(1);
Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets[1];
int i = 1;
int i2 = 1;
foreach (ListViewItem lvi in lvData.Items)
{
    i = 1;
    foreach (ListViewItem.ListViewSubItem lvs in lvi.SubItems)
    {
        ws.Cells[i2, i] = lvs.Text;
        i++;
    }
    i2++;
}

Excel.Range rng = null;
rng = Excel.Range("A1:Z" + lvData.Items.Count); // Error: Microsoft.Office.InterOp.Excel.Range is a 'type', which is not valid in the given context.
rng.Columns.AutoFit();

// RANGE COPY IN WORD INTEROP
// oWord.ActiveDocument.Sections[cnt].Range.Copy();
// Set focus to the New Word Doc instance
// oNewWord.Activate();
// Paste copied range to New Word Doc
// oNewWord.ActiveDocument.Range(0, 0).Paste();

MessageBox.Show("Export Completed", "Export to Excel", MessageBoxButtons.OK, MessageBoxIcon.Information);

我也想:

  1. 自动将所有单元格宽度设置为数据宽度。
  2. 将ListView列标题的值放入Excel的第一行。
  3. 我的listview中总共有26列,但实际上我只需要向用户输出大约10个(我从前端的用户视图中隐藏了许多这些列,然后在后端使用它们来获取其他功能处理)。
  4. 我还在寻找,但尚未找到任何解决方案。我有从Excel / Access到.Txt的经验,同样,但还没有完成ListView到Excel。任何人都有关于如何实现上述目标的想法?

    谢谢!

    修改

    使用Derek的建议现在所有列的宽度都会在处理结束时自动设置为列中最大单元格内容的大小。使用Miles建议,我做了一些玩弄,并设法凑齐了一些代码,将ColumnHeader值插入第​​一个Excel行。

    现在只想弄清楚如何隐藏某些不需要的列或不导出特定的列。

                    // http://www.daniweb.com/software-development/csharp/threads/192620/listview-to-excel
                    Excel.Application app = new Excel.Application();
                    app.Visible = true;
                    Excel.Workbook wb = app.Workbooks.Add(1);
                    Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets[1];
                    int i = 1;
                    int i2 = 2;
                    int x = 1;
                    int x2 = 1;
                    int j = 0;
                    int colNum = lvData.Columns.Count;
    
                    // Set first ROW as Column Headers Text
                    foreach (ColumnHeader ch in lvData.Columns)
                    {
                            ws.Cells[x2, x] = ch.Text;
                            x++;
                    }
    
                    foreach (ListViewItem lvi in lvData.Items)
                    {
                        i = 1;
                        foreach (ListViewItem.ListViewSubItem lvs in lvi.SubItems)
                        {
                            ws.Cells[i2, i] = lvs.Text;
                            i++;
                        }
                        i2++;
                    }
    
                    // AutoSet Cell Widths to Content Size
                    ws.Cells.Select();
                    ws.Cells.EntireColumn.AutoFit();
    
                    MessageBox.Show("Export Completed", "Export to Excel", MessageBoxButtons.OK, MessageBoxIcon.Information);
    

    EDIT2

    我在另一个使用编写器的程序中做了一些事情,在那里我查看了特定的索引。如果它不是最后一个indice(列),我将一个值附加到一个长字符串的末尾。如果它是最后一个值(列),我将整个字符串写入文件。通过这种方式,我可以将ListView中的值导出到(!)分隔的.Txt文件中。我在这里为#3尝试类似的东西,但它还没有完成:

                    // indices is used to designate which columns in the ListView we want
                    var indices = new int[] { 0, 1, 2, 8, 9, 15, 19, 22, 23, 24, 25 };
                    foreach (ListViewItem lvi in lvData.Items)
                    {
                        i = 1;
                        foreach (int id in indices)
                        {
                            ws.Cells[i2, i] = lvi.SubItems.ToString();
                            i++;
                        }
    
                        //foreach (ListViewItem.ListViewSubItem lvs in lvi.SubItems)
                        //{
                        //    ws.Cells[i2, i] = lvs.Text;
                        //    i++;
                        //}
                        i2++;
                    }
    

3 个答案:

答案 0 :(得分:1)

对于第一部分,看起来你可以这样做:

    ws.Cells[i, j].ColumnWidth = lvs.Text.Length;

查看此页面:http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.range_members.aspx

对于第二和第三部分,我有点困惑这个问题是什么。您是否可以遍历ListView并将这些列值写入第一行?

答案 1 :(得分:1)

对于自动调整:

  //make all columns autofit
  workSheet.Cells.Select();
  workSheet.Cells.EntireColumn.AutoFit();
列标题的

(使用Linq):

(可能需要调整指数,但我认为不是)

  foreach ( ColumnHeader column in lv.Columns.OfType<ColumnHeader>() )
  {
     workSheet.Cells[ 1, column.Index + 1 ] = column.Name;
  }

然后您可能需要调整代码的下一位。我循环浏览ListViewItems并单独设置单元格。

您可以通过listviewitems处理循环,只执行您想要的循环。例如前十名。我只是做workheet.Cells [rowIndex,columnIndex] = ...来设置所有值。

其中一个技巧。
SubItems实际上从第二列开始。

listViewItem.Name为您提供第一列

这样:

循环遍历listViewItems ......

worksheet.Cells[ rowIndex, 1 ] = listViewItem.Name;
j = 2;

foreach (ListViewItem.ListViewSubItem lvs in lvi.SubItems)
{
   ws.Cells[rowIndex, j] = lvs.Text;
   j++;
 }
 j++;

答案 2 :(得分:0)

兄弟,答案已经在您的代码中了。我不知道你是否注意到了。你创建了一个整数数组,现在使用它。像:

            var indices = new int[] { 0, 1, 2, 8, 9, 15, 19, 22, 23, 24, 25 };

            foreach (ListViewItem lvi in lvData.Items)
            {
                i = 1;
                int bol = lvi.SubItems.Count;

                foreach (int id in indices)
                { 
                    if (bol > 0)
                    {
                       ws.Cells[i2, i] = lvi.SubItems[id].Text;
                       i++;
                       bol--;
                    }
                }
                i2++;
            }

这对我来说是最简单的方法。但如果你想要更漂亮的东西,那就好运!我保证你的确有效!

PD:如果我写的是为了防止错误,请随意做其他事情。但是通过这种方式它起作用,相信我。