将数组写入Excel范围

Jon*_*tus 51 c# excel interop

我目前正在尝试使用以下代码将对象数组中的数据写入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;
Run Code Online (Sandbox Code Playgroud)

这几乎可以工作,问题是范围被填满但是每个单元格都获得了第一个项目的值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;
Run Code Online (Sandbox Code Playgroud)

将返回一个包含工作表中所有值的数组,所以我不确定为什么阅读和赋值的工作方式不同.

有没有人成功地做过这件事?我目前正逐个单元地编写阵列,但它需要处理很多(> 50,000)行,因此非常耗时.

pet*_* k. 90

这是我的方法的摘录,它将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;
Run Code Online (Sandbox Code Playgroud)

当然,您不需要像我一样使用中间DataTable,代码摘录只是为了演示如何在单个调用中将数组写入工作表.

  • 我使用range.set_Value(Missing.Value,objectArray); 您需要确保该数组与范围大小相同. (2认同)

Jon*_*tus 10

感谢指点人 - Value vs Value2参数让我得到了一组不同的搜索结果,这帮助我意识到答案是什么.顺便提一下,Value属性是一个参数化属性,必须通过C#中的访问器访问.这些称为get_Value和set_Value,并采用可选的枚举值.如果有人感兴趣,这很好地解释了.

但是,可以通过Value2属性进行赋值,这是优选的,因为互操作文档建议不要使用get_Value和set_Value方法,这是出于我理解的原因.

关键似乎是对象数组的维度.对于工作调用,即使您只分配一维数据,也必须将数组声明为二维数组.

我将我的数据数组声明为object[NumberofRows,1]并且赋值调用有效.


Cra*_*Cat 5

就我而言,程序查询数据库并返回 DataGridView。然后我将其复制到一个数组中。我获取刚刚创建的数组的大小,然后将该数组写入 Excel 电子表格。这段代码在大约两秒内输出了 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)
{
    //...
}
Run Code Online (Sandbox Code Playgroud)