使用 C#,是否有直接方法将列表列表(即 List>
)导出到 Excel 2003?
我正在解析大型文本文件并导出到 Excel。 一次写入一个单元格会产生太多的开销。 我选择使用 List
这样我就不必担心指定行数或列数。
目前,我等到文件末尾,然后将 List>
的内容放入二维数组中。 然后可以将该数组设置为 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 而进行创建数组的中间步骤。 有任何想法吗?
Using C#, is there a direct way to export a List of Lists (i.e., List<List<T>>
) to Excel 2003?
I am parsing out large text files and exporting to Excel. Writing one cell at a time creates way too much overhead. I chose to use List<T>
so that I would not have to worry about specifying the number of rows or columns.
Currently, I wait until end of file, then put the contents of my List<List<object>>
into a 2-dimensional array. Then the array can be set as the value of an Excel.Range object. It works, but it seems like I should be able to take my List of Lists, without worrying about the number of rows or columns, and just dump it into a worksheet from A1 to wherever.
Here's a snippet of the code I'd like to replace or improve on:
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;
This works, but I'd rather use the List directly to Excel than having the intermediary step of creating an array just for the sake of Excel. Any ideas?
发布评论
评论(4)
从战略上讲,你做得正确。 正如 Joe 所说,通过一次性传递整个值数组来执行单元格值分配比逐个循环单元格要快得多。
Excel 基于 COM,因此通过 .NET 互操作与 Excel 进行操作。 不幸的是,互操作不了解泛型,因此您不能将 List 传递给它。 或类似的。 二维数组确实是唯一的出路。
也就是说,有几种方法可以清理代码,使其更易于管理。 以下是一些想法:
(1) 如果您使用 .NET 3.0,则可以使用 LINQ 将代码从: 缩短
为单行:
(2) 不要使用
_Worksheet
或_Workbook
接口。 请改用Worksheet
或Workbook
。 请参阅此处的讨论:Excel 互操作:_Worksheet 或 Worksheet?。(3) 考虑使用
Range.Resize
方法,该方法在 C# 中为Range.get_Resize
。 不过,这是一个难以抉择的问题——我实际上喜欢你设置范围大小的方式。 但我认为您可能想了解这一点。 例如,此处的行:可以更改为:
(4) 您不必将
Application.UserControl
设置为true
。 让 Excel 对用户可见就足够了。UserControl
属性没有按照您想象的那样执行。 (请参阅此处的帮助文件)如果您想控制是否无论用户是否可以控制 Excel,您都应该使用工作表保护,或者如果您想锁定用户,您可以设置Application.Interactive = false
。 (这不是一个好主意。)但如果您希望允许用户使用 Excel,那么只需使其可见就足够了。总的来说,考虑到这些,我认为您的代码可能看起来像这样:
希望这有帮助......
迈克
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 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) If you are using .NET 3.0, you can use LINQ to shorten your code from:
to a single line:
(2) Don't use the
_Worksheet
or_Workbook
interfaces. Make use ofWorksheet
orWorkbook
instead. See here for a discussion: Excel interop: _Worksheet or Worksheet?.(3) Consider making use of the
Range.Resize
method, which comes through asRange.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:Could be changed to:
(4) You do not have to set the
Application.UserControl
totrue
. Making Excel visible to the user is enough. TheUserControl
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 setApplication.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:
Hope this helps...
Mike
将二维数组传递到 Excel 比一次更新一个单元格要快得多。
使用列表列表中的值创建一个二维对象数组,将 Excel 范围重新调整为数组的维度,然后调用 range.set_Value,传递二维数组。
It's much faster to pass a two-dimensional array to Excel than to update cells one at a time.
Create a 2-dimensional array of objects with values from your list of lists, redimension the Excel range to the dimensions of your array, and then call range.set_Value, passing your two-dimensional array.
希望这有帮助
,其中
cs.getcompletionreport()
是参考类文件是应用程序的业务层hopes this helps
where
cs.getcompletionreport()
is reference class file is Business Layer for App对于未来的搜索者:确实,如果您想将列表复制到 Excel,则必须粘贴
object[,]
(二维)。 万一有人有一维列表,您可以仅运行一个第二维为 1 的for 循环
:For future searchers: It is true that if you want to copy list to excel you have to paste
object[,]
(2 dimensional). Just in case someone has one dimensional list you can run just onefor loop
with second dimesion 1: