Стратегически вы делаете это правильно. Как говорит Джо, гораздо быстрее выполнить присвоение значений ячейки, передавая целый массив значений за один снимок, а не циклически перебирая ячейки одну за другой.
Excel основан на COM и работает с Excel через взаимодействие .NET. К сожалению, взаимодействие не знает обобщений, поэтому вы не можете передать ему 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
. Вместо этого используйте Worksheet
или Workbook
. Для обсуждения см. Здесь: Взаимодействие Excel: _Worksheet или Worksheet? .
(3) Подумайте об использовании метода Range.Resize
, который обозначается как Range.get_Resize
в C #. Это бросок вверх - мне действительно нравится, как вы устанавливаете размер диапазона. Но это то, о чем я подумала, вы можете захотеть узнать Например, ваша строка здесь:
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
не делает то, что вы думаете, оно делает. (См. Файлы справки здесь ) Если вы хотите контролировать, может ли пользователь контролировать 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;
Надеюсь, это поможет ...
Mike