且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将C#列表导出到Excel

更新时间:2023-02-04 16:03:25

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

Strategically, you are doing it correctly. As Joe says, it is massively faster to execute cell value assignments by passing an entire array of values in one shot rather than by looping through the cells one by one.

Excel是基于COM,因此通过.NET互操作与Excel一起运行。不幸的是,interop对泛型是无知的,所以你不能传递一个List< T>或类似物。二维数组真的是唯一的办法。

Excel is COM based and so operates with Excel via the .NET interop. The interop is ignorant of generics, unfortunately, so you cannot pass it a List<T> or the like. A two dimensional array really is the only way to go.

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

That said, there are a few ways to clean up your code to make it a bit more manageable. Here are some thoughts:

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

(1) If you are using .NET 3.0, you can use LINQ to shorten your code from:

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 接口。使用工作表工作簿。请参阅此处进行讨论: Excel interop:_Worksheet或Worksheet?

(2) Don't use the _Worksheet or _Workbook interfaces. Make use of Worksheet or Workbook instead. See here for a discussion: Excel interop: _Worksheet or Worksheet?.

(3)考虑利用 Range.Resize 方法,通过 Range.get_Resize C#中的。这是一个折腾 - 虽然我实际上喜欢你设置范围大小的方式。但这是我以为你可能想知道的东西。例如,您的行在这里:

(3) Consider making use of the Range.Resize method, which comes through as Range.get_Resize in C#. This is a toss-up though -- I actually like the way you are setting your range size. But it's something that I thought that you might want to know about. For example, your line here:

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,那么只要让它可见就可以了。

(4) You do not have to set the Application.UserControl to true. Making Excel visible to the user is enough. The UserControl property is not doing what you think it does. (See the help files here) If you want to control whether the user can control Excel or not, you should utilze Worksheet protection, or you could set Application.Interactive = false if you want to lock out your users. (Rarely a good idea.) But if you want to allow the user to use Excel, then simply making it visible is enough.

总的来说,考虑到这些,认为你的代码看起来像这样:

Overall, with these in mind, I think that your code could look something like this:

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;

希望这有帮助...

迈克