Najszybszy sposób zapisu komórek do Excela za pomocą Office Interop?

Piszę funkcję do eksportu danych do Excela za pomocą pakietu Office Interop w VB. NET. obecnie piszę komórki bezpośrednio za pomocą metody Cells() arkusza Excela:

worksheet.Cells(rowIndex, colIndex) = data(rowIndex)(colIndex)
To zajmuje dużo czasu dla dużych ilości danych. Czy istnieje szybszy sposób na zapisanie wielu danych do Excela na raz? Czy zrobienie czegoś z zakresami byłoby szybsze?
Author: davidscolgan, 2010-06-22

6 answers

Powinieneś unikać czytania i pisania komórka po komórce, jeśli możesz. Znacznie szybsza jest praca z tablicami i odczyt lub zapis całych bloków naraz. Napisałem post jakiś czas temu na Czytanie z arkuszy roboczych przy użyciu C#; zasadniczo ten sam kod działa na odwrót( patrz poniżej) i będzie działał znacznie szybciej, zwłaszcza przy większych blokach danych.

  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;
 29
Author: Mathias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-23 05:30:44

Jeśli jeszcze tego nie zrobiłeś, upewnij się, że ustawiłeś Application.ScreenUpdating = false przed rozpoczęciem wysyłania danych. To sprawi, że wszystko pójdzie znacznie szybciej. Ustaw go z powrotem na True po zakończeniu wysyłania danych. Konieczność przerysowania ekranu przy każdej zmianie komórki zajmuje sporo czasu, omijając to oszczędza to.

Jeśli chodzi o używanie zakresów, nadal będziesz musiał kierować 1 (jedną) konkretną komórkę dla wartości, więc nie widzę tutaj żadnych korzyści. Nie jestem świadomy, że robisz to szybciej niż to, co robisz w odniesieniu aby faktycznie wysyłać dane.

 10
Author: Tommy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-01 15:23:13

Żeby dodać do odpowiedzi Tommy ' ego.

  • Możesz również ustawić obliczenia na ręczne przed rozpoczęciem pisania.

Zastosowanie.Obliczenie = xlCalculationManual

I ustaw go z powrotem na automatyczny, gdy skończysz pisać. (jeśli istnieje szansa, że oryginalny tryb mógł być czymś innym niż automatyczny, musisz zapisać tę wartość przed ustawieniem go na ręczny)

Zastosowanie.Obliczenie = xlCalculationAutomatic

  • można również użyć metody CopyFromRecordset obiektu Range.

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

 5
Author: potatopeelings,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-23 07:05:35

Najszybszym sposobem zapisu i odczytu wartości z zakresów Excela są Range.get_Value i Range.set_Value.

Droga jest jak poniżej:

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);

I tak, nie wymaga iteracji. Wydajność jest po prostu voila!!

Mam nadzieję, że to pomoże !!
 3
Author: Sunny Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-21 11:12:24

Szczerze mówiąc, najszybszym sposobem na napisanie tego jest rozdzielacz przecinków. Łatwiej jest napisać linię pól za pomocą Join(",").Metoda ToString zamiast próbować iteracji przez komórki. Następnie zapisz plik jako ".csv". Używając interop, otwórz plik jako plik csv, który automatycznie wykona aktualizację komórki po otwarciu.

 2
Author: Josaph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-23 19:18:50

Na wypadek, gdyby pojawił się ktoś inny, jak ja, szukający pełnego rozwiązania przy użyciu metody podanej przez @Mathias (która wydaje się być najszybsza do ładowania do Excela) z sugestią @IMil na tablicy.
Proszę bardzo:

'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

Then

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

Ograniczenia obejmują zezwalanie tylko na 26 kolumn, zanim będzie potrzebował lepszego kodu do wymyślania liter wartości zakresu.

 0
Author: VenerableAgents,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-13 17:11:52