Записать массив в диапазон Excel - PullRequest
50 голосов
/ 11 февраля 2009

В настоящее время я пытаюсь записать данные из массива объектов в диапазон в 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 ]

84 голосов
/ 11 февраля 2009

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

9 голосов
/ 11 февраля 2009

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

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

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

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

4 голосов
/ 11 февраля 2009

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

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

3 голосов
/ 13 июля 2017

В моем случае программа запрашивает базу данных, которая возвращает 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)
{
    //...
}
2 голосов
/ 23 августа 2017

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

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

Хорошего дня, Жиль

1 голос
/ 09 декабря 2016

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

Определение для столбцов: object [,] Array = new object [17, 1];

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

Код для value2 в обоих случаях одинаков Excel.Range cell = activeWorksheet.get_Range (Range); cell.Value2 = Array;

LG Georg

1 голос
/ 02 ноября 2015

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

public void SetRow(Range range, string[] data)
{
    range.get_Resize(1, data.Length).Value2 = data;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...