web-dev-qa-db-ja.com

Excel範囲への配列の書き込み

現在、次のコードを使用して、オブジェクトの配列からExcelの範囲にデータを書き込もうとしています。ここで、objDataは単なる文字列の配列です。

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;

これはほとんど機能します。問題は、範囲がいっぱいになるが、すべてのセルがobjDataの最初の項目の値を取得することです。

逆の動作、つまり.

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;

ワークシートのすべての値を含む配列を返すため、読み取りと割り当てが異なる理由はわかりません。

誰もこれをうまくやったことがありますか?現在、セルごとに配列を記述していますが、多数(> 50,000)の行に対応する必要があるため、非常に時間がかかります。

50
Jon Artus

これは私のメソッドからの抜粋で、DataTable(dt変数)を配列に変換してから、ワークシート(wsh var)のRangeに配列を書き込みます。 topRow変数を、文字列の配列を配置する行に変更することもできます。

        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;

もちろん、私が行ったように中間のDataTableを使用する必要はありません。コードの抜粋は、1回の呼び出しでワークシートに配列を書き込む方法を示すためのものです。

86
petr k.

ポインターの皆さんに感謝します-Value vs Value2引数は、答えが何であるかを理解するのに役立つ検索結果の異なるセットを私に与えました。ちなみに、Valueプロパティはパラメーター化されたプロパティであり、C#のアクセサーを介してアクセスする必要があります。これらはget_Valueおよびset_Valueと呼ばれ、オプションの列挙値を取ります。誰かが興味を持っている場合は、 これはうまく説明します .

ただし、Value2プロパティを介して割り当てを行うことは可能です。これは、理解できない理由から、相互運用ドキュメントでget_Valueメソッドとset_Valueメソッドの使用を推奨しているためです。

キーはオブジェクトの配列の次元のようです。呼び出しが機能するには、1次元データのみを割り当てる場合でも、配列を2次元として宣言する必要があります。

データ配列をobject[NumberofRows,1]として宣言し、割り当て呼び出しが機能しました。

9
Jon Artus

データをレコードセットに入れて ExcelのCopyFromRecordsetメソッド を使用できます。これは、セルごとに入力するよりもはるかに高速です。

このコード を使用して、データセットからレコードセットを作成できます。この方法を使用すると、現在実行している方法よりも高速かどうかを確認するために、いくつかの試行を行う必要があります。

4
Galwegian

私の場合、プログラムはDataGridViewを返すデータベースを照会します。それを配列にコピーします。作成したばかりの配列のサイズを取得し、Excelスプレッドシートに配列を書き込みます。このコードは、約2秒で5000行を超えるデータを出力します。

//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)
{
    //...
}
3
Crazy Cat

excelシートに1D配列を書き込みたい場合、転置する必要がありますおよびありません上記で読んだように、1列([n、1])で2D配列を作成します!コードの例を次に示します。

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

良い一日を

2
Gilles5678

配列定義の種類が重要なようです:私の場合は、17項目の1次元配列であり、2次元配列に変換する必要があります

列の定義:object [、] Array = new object [17、1];

行の定義object [、] Array = new object [1,17];

Value2のコードは、どちらの場合も同じExcel.Range cell = activeWorksheet.get_Range(Range);です。 cell.Value2 =配列;

LG Georg

1
Georg

何らかの理由で、2次元配列への変換はうまくいきませんでした。しかし、次のアプローチはそうでした:

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