c# - 将 C# 列表列表导出到 Excel

标签 c# .net excel list generic-list

使用 C#,是否有直接的方法将列表的列表(即 List<List<T>>)导出到 Excel 2003?

我正在解析大型文本文件并导出到 Excel。一次写一个单元格会产生太多的开销。我选择使用 List<T>这样我就不必担心指定行数或列数。

目前,我等到文件结束,然后放入我的 List<List<object>> 的内容成一个二维数组。然后可以将该数组设置为 Excel.Range 对象的值。它有效,但似乎我应该能够使用我的列表列表,而不用担心行数或列数,然后将它转储到工作表中,从 A1 到任何地方。

这是我想替换或改进的代码片段:

object oOpt = System.Reflection.Missing.Value; //for optional arguments
Excel.Application oXL = new Excel.Application();
Excel.Workbooks oWBs = oXL.Workbooks;
Excel._Workbook oWB = oWBs.Add(Excel.XlWBATemplate.xlWBATWorksheet);
Excel._Worksheet oSheet = (Excel._Worksheet)oWB.ActiveSheet;

int numberOfRows = outputRows.Count;
int numberOfColumns = int.MinValue;

//outputRows is a List<List<object>>
foreach (List<object> outputColumns in outputRows)
{
        if (numberOfColumns < outputColumns.Count)
        { numberOfColumns = outputColumns.Count; }
}

Excel.Range oRng = oSheet.get_Range("A1", oSheet.Cells[numberOfRows,numberOfColumns]);

object[,] outputArray = new object[numberOfRows,numberOfColumns];

for (int row = 0; row < numberOfRows; row++)
{
        for (int col = 0; col < outputRows[row].Count; col++)
        {
                outputArray[row, col] = outputRows[row][col];
        }
}

oRng.set_Value(oOpt, outputArray);

oXL.Visible = true;
oXL.UserControl = true;

这行得通,但我宁愿直接在 Excel 中使用列表,而不是为了 Excel 而进行创建数组的中间步骤。有什么想法吗?

最佳答案

从战略上讲,您的做法是正确的。正如 Joe 所说,通过一次传递整个值数组而不是逐个循环遍历单元格来执行单元格值分配要快得多。

Excel 是基于 COM 的,因此通过 .NET 互操作与 Excel 一起运行。不幸的是,互操作不了解泛型,因此您不能将 List 或类似的传递给它。二维数组确实是唯一的出路。

也就是说,有几种方法可以清理您的代码,使其更易于管理。以下是一些想法:

(1) 如果您使用的是 .NET 3.0,您可以使用 LINQ 来缩短您的代码:

int numberOfColumns = int.MinValue;

foreach (List<object> outputColumns in outputRows)
{
        if (numberOfColumns < outputColumns.Count)
        { numberOfColumns = outputColumns.Count; }
}

单行:

int numberOfColumns = outputRows.Max(list => list.Count);

(2) 不要使用_Worksheet_Workbook 接口(interface)。请改用 WorksheetWorkbook。请参阅此处进行讨论:Excel interop: _Worksheet or Worksheet? .

(3) 考虑使用 Range.Resize 方法,它在 C# 中作为 Range.get_Resize 出现。不过这是一个折腾——我实际上喜欢你设置范围大小的方式。但这是我认为你可能想知道的事情。例如,您在此处的行:

Excel.Range oRng = oSheet.get_Range("A1", oSheet.Cells[numberOfRows,numberOfColumns]);

可以改为:

Excel.Range oRng = 
    oSheet.get_Range("A1", Type.Missing)
        .get_Resize(numberOfRows, numberOfColumns);

(4) 您不必将 Application.UserControl 设置为 true。使 Excel 对用户可见就足够了。 UserControl 属性没有按照您的预期进行操作。 (参见帮助文件 here)如果你想控制用户是否可以控制 Excel,你应该使用工作表保护,或者你可以设置 Application.Interactive = false 如果你想锁定你的用户。 (很少是个好主意。)但如果您想让用户使用 Excel,那么只需使其可见就足够了。

总的来说,考虑到这些,我认为您的代码可能如下所示:

object oOpt = System.Reflection.Missing.Value; //for optional arguments
Excel.Application oXL = new Excel.Application();
Excel.Workbooks oWBs = oXL.Workbooks;
Excel.Workbook oWB = oWBs.Add(Excel.XlWBATemplate.xlWBATWorksheet);
Excel.Worksheet oSheet = (Excel.Worksheet)oWB.ActiveSheet;

//outputRows is a List<List<object>>
int numberOfRows = outputRows.Count;
int numberOfColumns = outputRows.Max(list => list.Count);

Excel.Range oRng = 
    oSheet.get_Range("A1", oOpt)
        .get_Resize(numberOfRows, numberOfColumns);

object[,] outputArray = new object[numberOfRows, numberOfColumns];

for (int row = 0; row < numberOfRows; row++)
{
    for (int col = 0; col < outputRows[row].Count; col++)
    {
        outputArray[row, col] = outputRows[row][col];
    }
}

oRng.set_Value(oOpt, outputArray);

oXL.Visible = true;

希望这有助于...

迈克

关于c# - 将 C# 列表列表导出到 Excel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1059951/

相关文章:

C# 从千位分隔符转换回 int

.net - 将 Sql-Server (express) 从命名实例更改为 localhost?

c# - 从 AuthorizeAttribute 继承的属性不起作用

vba - 根据 2 个不同的字符串值删除行

c# - 如何从 hibernate.cfg.xml 文件中获取连接字符串值?

c# - 将我的 DateTime 转换为 UTC 时遇到问题

.net - 从哪里获得 .net 的 apache poi 端口

css - 如何使用 Excel VBA 单击 Web CSS 按钮?

excel - 循环遍历每个单元格,如果匹配,则获取值并添加到列表/数组中,以便将其用于自动过滤

c# - 使用Lock来停止并发执行不起作用?