Самый быстрый способ записать ячейки в Excel с помощью Office Interop?

Я пишу функцию для экспорта данных в Excel с помощью Office Interop в VB .NET. В настоящее время я пишу ячейки напрямую, используя метод Cells () листа Excel:

worksheet.Cells(rowIndex, colIndex) = data(rowIndex)(colIndex)

Для больших объемов данных это занимает много времени. Есть ли более быстрый способ записать сразу много данных в Excel? Будет ли что-то делать с диапазонами быстрее?


person davidscolgan    schedule 22.06.2010    source источник
comment
У этого почти дубликата есть подробные ответы: stackoverflow.com/questions/3840270/.   -  person Govert    schedule 10.11.2011


Ответы (6)


По возможности следует избегать чтения и записи ячейка за ячейкой. Намного быстрее работать с массивами, а также читать или записывать целые блоки сразу. Некоторое время назад я написал сообщение на чтение с таблиц с использованием C #; в основном тот же код работает наоборот (см. ниже) и будет работать намного быстрее, особенно с большими блоками данных.

  var sheet = (Worksheet)Application.ActiveSheet;
  var range = sheet.get_Range("A1", "B2");
  var data = new string[3,3];
  data[0, 0] = "A1";
  data[0, 1] = "B1";
  data[1, 0] = "A2";
  data[1, 1] = "B2";
  range.Value2 = data;
person Mathias    schedule 23.06.2010
comment
Мне не удалось оставить комментарий в вашем блоге, поэтому позвольте мне написать его здесь. Вы можете создать массив на основе 1 в C # с помощью метода CreateInstance: var arr = (object [,]) Array.CreateInstance (typeof (object), new int [] {2, 3}, new int [] {1, 1}) - person IMil; 04.12.2013

Если вы еще этого не сделали, не забудьте установить Application.ScreenUpdating = false перед тем, как начать вывод данных. Так дела пойдут намного быстрее. Установите его обратно в True, когда вы закончите вывод данных. Необходимость перерисовывать экран при каждом изменении ячейки занимает немало времени, игнорирование этого позволяет сэкономить.

Что касается использования диапазонов, вам все равно нужно будет указать 1 (одну) конкретную ячейку для значения, поэтому я не вижу здесь никакой выгоды. Я не знаю, что делать это быстрее, чем то, что вы делаете в отношении фактического вывода данных.

person Tommy    schedule 22.06.2010

Просто чтобы добавить к ответу Томми.

  • Вы также можете настроить расчет вручную, прежде чем начать писать.

Application.Calculation = xlCalculationManual

И верните его в автоматический режим, когда закончите писать. (если есть вероятность, что исходный режим мог быть чем-то другим, кроме автоматического, вам придется сохранить это значение, прежде чем устанавливать его вручную)

Application.Calculation = xlCalculationAutomatic

  • Вы также можете использовать метод CopyFromRecordset объекта Range.

http://msdn.microsoft.com/de-de/library/microsoft.office.interop.excel.range.copyfromrecordset(office.11).aspx

person potatopeelings    schedule 23.06.2010

Самый быстрый способ записи и чтения значений из диапазонов Excel - Range.get_Value и Range.set_Value.

Способ такой, как показано ниже:

Range filledRange = Worksheet.get_Range("A1:Z678",Missing);
object[,] rngval = (object[,]) filledRange.get_Value (XlRangeValueDataType.xlRangeValueDefault);

Range Destination = Worksheet2.get_Range("A1:Z678",Missing);
destination.set_Value(Missing,rngval);

и да, итерация не требуется. Производительность просто вуаля !!

Надеюсь, поможет !!

person Sunny Sharma    schedule 21.11.2011

Честно говоря, самый быстрый способ написать это с разделителями-запятыми. С помощью метода Join (","). ToString проще написать строку полей, чем пытаться перебирать ячейки. Затем сохраните файл как «.csv». Используя interop, откройте файл как csv, который автоматически обновит ячейку для вас при открытии.

person Josaph    schedule 23.06.2010
comment
Если скорость - это то, что вам нужно, тогда это правильный путь, однако есть подводные камни, особенно со строками и специальными символами. - person David B Heise; 10.09.2010

В случае, если кто-то другой, как я, ищет полное решение, используя метод, предоставленный @Mathias (который, кажется, самый быстрый для загрузки в Excel) с предложением @ IMil для массива.
Вот и все:

'dt (DataTable) is the already populated DataTable
'myExcelWorksheet (Worksheet) is the worksheet we are populating
'rowNum (Integer) is the row we want to start from (usually 1)
Dim misValue As Object = System.Reflection.Missing.Value
Dim arr As Object = DataTableToArray(dt)
'Char 65 is the letter "A"
Dim RangeTopLeft As String = Convert.ToChar(65 + 0).ToString() + rowNum.ToString()
Dim RangeBottomRight As String = Convert.ToChar(65 + dt.Columns.Count - 1).ToString() + (rowNum + dt.Rows.Count - 1).ToString()
Dim Range As String = RangeTopLeft + ":" + RangeBottomRight
myExcelWorksheet.Range(Range, misValue).NumberFormat = "@" 'Include this line to format all cells as type "Text" (optional step)
'Assign to the worksheet
myExcelWorksheet.Range(Range, misValue).Value2 = arr

потом

Function DataTableToArray(dt As DataTable) As Object
    Dim arr As Object = Array.CreateInstance(GetType(Object), New Integer() {dt.Rows.Count, dt.Columns.Count})
    For nRow As Integer = 0 To dt.Rows.Count - 1
        For nCol As Integer = 0 To dt.Columns.Count - 1
            arr(nRow, nCol) = dt.Rows(nRow).Item(nCol).ToString()
        Next
    Next
    Return arr
End Function

Ограничения включают в себя разрешение только 26 столбцов, прежде чем потребуется лучший код для создания букв значений диапазона.

person VenerableAgents    schedule 13.07.2017