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

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

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

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

Ответы

Ответ 1

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

  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;

Ответ 2

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

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

Ответ 3

Просто добавлю к ответу Томми.

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

Application.Calculation = xlCalculationManual

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

Application.Calculation = xlCalculationAutomatic

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

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

Ответ 4

Самый быстрый способ записи и чтения значений из диапазонов 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);

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

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

Ответ 5

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

Ответ 6

В случае, если кто-то еще приходит, как и я, ища полное решение, используя метод @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 столбцов, прежде чем ему понадобится более качественный код для появления букв значений диапазона.