Запись массива в диапазон 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) строк, и это занимает много времени.

7 ответов


Это выдержка из моего метода, который преобразует DataTable (переменную dt) в массив, а затем записывает массив в диапазон на листе (wsh var). Вы также можете изменить переменную 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 как я сделал, выдержка кода просто продемонстрировать, как массив может быть записан на лист в одном вызове.


Спасибо за указатели, ребята-аргумент Value vs Value2 дал мне другой набор результатов поиска,который помог мне понять, что ответ. Кстати, свойство Value является параметризованным свойством, доступ к которому должен осуществляться через метод доступа в C#. Их называют число и значение, и дополнительно значение enum. Если кто-то заинтересован,это объясняет, это красиво.

можно сделать назначение через свойство Value2, однако, которое предпочтительнее, поскольку документация взаимодействия рекомендует не использовать методы get_Value и set_Value по причинам, выходящим за рамки моего понимания.

ключ вроде бы размерность массива объектов. Для вызова для работы массив должен быть объявлен как двумерный, даже если вы назначаете только одномерные данные.

Я объявил свой массив данных как object[NumberofRows,1] и вызов назначения сработал.


вы можете поместить ваши данные в набор записей и использовать метод CopyFromRecordset Excel - это намного быстрее, чем заполнение ячеек.

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


в моем случае, программа запрашивает базу данных, которая возвращает элемент. Затем я копирую это в массив. Я получаю размер только что созданного массива, а затем записываю массив в электронную таблицу 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)
{
    //...
}

по какой-то причине преобразование в 2-мерный массив не сработало для меня. Но следующий подход:

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

вид определения массива кажется ключом: В моем случае это массив одного измерения из 17 элементов, которые должны быть преобразованы в массив двух измерений

данные для столбцов: object [,] Array = новый объект[17, 1];

определение строки object [,] Array= новый объект[1,17];

код для value2 в обоих случаях один и тот же Превосходить.Диапазон ячеек = activeWorksheet.get_Range(диапазон); клетка.Значение2 = Массив;

LG Georg


когда вы хотите написать массив 1D в листе Excel вы должны перенести ее и вам не нужно создавать 2D-массив с 1 столбцом ([n, 1]) как я читал выше! Вот пример кода :

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

хорошего дня, Жиль!--6-->