2009-02-11 14 views
45

ich zur Zeit versucht, Daten aus einem Array von Objekten zu einem Bereich in Excel mit dem folgenden Code zu schreiben, wo objData nur ein Array von Strings ist:schreiben Array Excel-Bereich

private object m = System.Type.Missing; 
object[] objData = getDataIWantToWrite(); 

Range rn_Temp; 
rn_Temp = (Range)XlApp.get_Range(RangeName, m); 
rn_Temp = rn_Temp.get_Resize(objData.GetUpperBound(), 1); 
rn_Temp.value2 = objData; 

Diese fast funktioniert, das Problem ist, dass der Bereich gefüllt wird, aber jede Zelle erhält den Wert des ersten Elements in objData.

Die inverse arbeitet, das heißt

private object m = System.Type.Missing; 
object[] objData = new object[x,y] 

Range rn_Temp; 
rn_Temp = (Range)XlApp.get_Range(RangeName, m); 
rn_Temp = rn_Temp.get_Resize(objData.GetUpperBound(), 1); 
objData = (object[])rn_Temp.value2; 

würde ein Array zurück alle Werte aus dem Arbeitsblatt enthält, also bin ich nicht sicher, warum das Lesen und Zuordnung arbeiten anders.

Hat jemand das jemals erfolgreich gemacht? Ich schreibe derzeit das Array Zelle für Zelle, aber es muss mit vielen (> 50.000) Zeilen fertig werden und das ist daher sehr zeitaufwendig.

+7

Die gewählte Antwort macht es nicht sofort offensichtlich, so dass, wenn jemand anderes jemals dieses Problem hat, kurz gesagt, die Lösung dass Sie ein 2D-Array ('object [,]') zuweisen müssen, obwohl Ihre Daten auf nur eine Dimension passen könnten. – zneak

+1

[sehr nützlich] (http://blogs.msdn.com/b/eric_carter/archive/2004/05/04/126190.aspx) –

Antwort

77

Dies ist ein Auszug aus meiner Methode, die eine DataTable (die dt-Variable) in ein Array konvertiert und dann das Array in einen Bereich auf einem Arbeitsblatt (wsh var) schreibt. Sie können die topRow-Variable auch in die Zeile ändern, in der das Array mit den Strings platziert werden soll.

 object[,] arr = new object[dt.Rows.Count, dt.Columns.Count]; 
     for (int r = 0; r < dt.Rows.Count; r++) 
     { 
      DataRow dr = dt.Rows[r]; 
      for (int c = 0; c < dt.Columns.Count; c++) 
      { 
       arr[r, c] = dr[c]; 
      } 
     } 

     Excel.Range c1 = (Excel.Range)wsh.Cells[topRow, 1]; 
     Excel.Range c2 = (Excel.Range)wsh.Cells[topRow + dt.Rows.Count - 1, dt.Columns.Count]; 
     Excel.Range range = wsh.get_Range(c1, c2); 

     range.Value = arr; 

Natürlich brauchen Sie nicht einen Zwischendatatable zu verwenden, wie ich es tat, ist der Code Auszug nur zu zeigen, wie ein Array geschrieben werden kann in einzelnen Aufruf zum Arbeitsblatt.

+0

Interessant - das ist genau das, was ich tun möchte, aber ich kann nicht auf die Value-Eigenschaft des Bereichsobjekts zugreifen - ich kann nur auf Value2 zugreifen, und ich denke, dass das Problem sein kann. Irgendeine Idee, wie ich auf die Value-Eigenschaft zugreifen kann? Welche Interops benutzen Sie? –

+0

Importiert aus der Excel-Typ-Bibliothek (passiert in meinem Fall Office 2003). Das heißt, ich verwende nicht die primären Interop-Baugruppen. Ich habe gerade den Verweis auf Excel COM tlb in VS hinzugefügt. Jetzt kann ich mich nicht mehr an den genauen Grund erinnern, warum ich die PIAs nicht benutzt habe. –

+2

Ich verwende den range.set_Value (Missing.Value, objectArray); Sie müssen sicherstellen, dass das Array die gleiche Größe wie der Bereich hat. –

4

Sie könnten Ihre Daten in ein Recordset setzen und Excel's CopyFromRecordset Method verwenden - es ist viel schneller als das Zellen-für-Zelle-Füllen.

Sie können ein Recordset aus einem Dataset mit this code erstellen. Sie müssen einige Versuche durchführen, um zu sehen, ob die Verwendung dieser Methode schneller ist als das, was Sie gerade tun.

+0

Dies kann eine dumme Frage sein, aber wo finde ich eine Recordset-Klasse in C# ? Oder wissen Sie zufällig, ob es noch eine andere Klasse gibt, die ich weitergeben kann? Danke vielmals! –

+1

Referenz zur Baugruppe ADODB Version 7.0.3300.0 hinzufügen. mit ADODB; ADODB hat den Typ "Recordset" –

9

Danke für die Zeiger Jungs - das Value vs Value2 Argument hat mir eine andere Reihe von Suchergebnissen, die mir geholfen, zu erkennen, was die Antwort ist. Übrigens ist die Value-Eigenschaft eine parametrisierte Eigenschaft, auf die über einen Accessor in C# zugegriffen werden muss. Diese heißen get_Value und set_Value und haben einen optionalen Enum-Wert. Wenn jemand interessiert ist, this explains it nicely.

Es ist jedoch möglich, die Zuweisung über die Value2-Eigenschaft vorzunehmen. Dies ist vorzuziehen, da die Interop-Dokumentation aus Gründen, die ich nicht verstehe, die Verwendung der Methoden get_Value und set_Value empfiehlt.

Der Schlüssel scheint die Dimension der Anordnung der Objekte zu sein. Damit der Aufruf ausgeführt werden kann, muss das Array als zweidimensional deklariert werden, auch wenn Sie nur eindimensionale Daten zuweisen.

Ich deklarierte meine Daten-Array als object[NumberofRows,1] und der Zuweisung Aufruf funktionierte.

+0

danke, es sieht aus wie ein 1D-Array gegeben, es wird es immer horizontal schreiben (sogar mit einem vertikalen Bereich, in diesem Fall schreibt es das erste Element wiederholt). Um ein Array vertikal zu schreiben, müssen Sie tun, was Sie gesagt haben, und es zu einem '[n, 1]' Array machen. Vielen Dank, denn ich hätte das wahrscheinlich nie selbst entdeckt. –

0

Aus irgendeinem Grund funktionierte die Konvertierung in ein zweidimensionales Array nicht für mich.Aber die folgende Vorgehensweise tat

public void SetRow(Range range, string[] data) 
{ 
    range.get_Resize(1, data.Length).Value2 = data; 
} 
1

Die Art der Array-Definition scheint den Schlüssel: In meinem Fall ist es eine eine Dimension Array von 17 Elementen, die zu einem zweidimensionalen Array konvertieren

Defintion für Spalten: Objekt [,] Array = neues Objekt [17, 1];

Definition für Zeilen Objekt [,] Array = neues Objekt [1,17];

Der Code für Wert2 ist in beiden Fällen gleich Excel.Range Zelle = activeWorksheet.get_Range (Range); Zelle.Wert2 = Array;

LG Georg

1

In meinem Fall fragt das Programm die Datenbank, die eine Datagridview zurück. Ich kopiere das dann in ein Array. Ich erhalte die Größe des gerade erstellten Arrays und schreibe das Array dann in eine Excel-Tabelle. Dieser Code gibt mehr als 5000 Datenzeilen in ungefähr zwei Sekunden aus.

//private System.Windows.Forms.DataGridView dgvResults; 
dgvResults.DataSource = DB.getReport(); 

Microsoft.Office.Interop.Excel.Application oXL; 
Microsoft.Office.Interop.Excel._Workbook oWB; 
Microsoft.Office.Interop.Excel._Worksheet oSheet; 
try 
{ 
    //Start Excel and get Application object. 
    oXL = new Microsoft.Office.Interop.Excel.Application(); 
    oXL.Visible = true; 

    oWB = (Microsoft.Office.Interop.Excel._Workbook)(oXL.Workbooks.Add("")); 
    oSheet = (Microsoft.Office.Interop.Excel._Worksheet)oWB.ActiveSheet; 

    var dgArray = new object[dgvResults.RowCount, dgvResults.ColumnCount+1]; 
    foreach (DataGridViewRow i in dgvResults.Rows) 
    { 
     if (i.IsNewRow) continue; 
     foreach (DataGridViewCell j in i.Cells) 
     { 
      dgArray[j.RowIndex, j.ColumnIndex] = j.Value.ToString(); 
     } 
    } 

    Microsoft.Office.Interop.Excel.Range chartRange; 

    int rowCount = dgArray.GetLength(0); 
    int columnCount = dgArray.GetLength(1); 
    chartRange = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[2, 1]; //I have header info on row 1, so start row 2 
    chartRange = chartRange.get_Resize(rowCount, columnCount); 
    chartRange.set_Value(Microsoft.Office.Interop.Excel.XlRangeValueDataType.xlRangeValueDefault, dgArray); 


    oXL.Visible = false; 
    oXL.UserControl = false; 
    string outputFile = "Output_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xlsx"; 

    oWB.SaveAs("c:\\temp\\"+outputFile, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault, Type.Missing, Type.Missing, 
     false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, 
     Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); 

    oWB.Close(); 
} 
catch (Exception ex) 
{ 
    //... 
} 
0

, wenn Sie ein 1D-Array in einer Excel-Tabelle schreiben möchten Sie es umsetzen müssen und Sie müssen nicht ein 2D-Array mit 1 Spalte erstellen ([n, 1]) als Ich lese oben! Hier ist ein Beispiel für den Code ein:

wSheet.Cells(RowIndex, colIndex).Resize(RowsCount,).Value = _excel.Application.transpose(My1DArray) 

einen guten Tag, Gilles

Verwandte Themen