2015-05-29 3 views
0

У меня есть excel, у которого есть десятки тысяч строк. Мне нужно вставлять данные случайным образом в пределах этого превосходства. Ниже у меня есть функция, которую я использую сейчас. Основной проблемой является перенос и вставка данных. Мне нужна лучшая идея или метод, который может делать то же самое, что и мой, но быстрее.Эффективно вставлять строки + данные

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

Вот мое:

private void shiftRows(int from, int numberof) 
    { 
     from++; 
     Range r = oXL.get_Range("A" + from.ToString(), "A" + from.ToString()).EntireRow; 

     for (int i = 0; i < numberof; i++) 
      r.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftDown); 
    } 

    public void inputRowData(string[] data, int rds) 
    { 
     int bestRow = getRowByRDS_a(rds); 
     string[] formatedData = formatOutput(bestRow, data); 
     string val = getValueOfCell(bestRow, 6); 
     if (val != null) 
     { 
      shiftRows(bestRow, data.Length); 
      bestRow++; 
     } 
     else 
      shiftRows(bestRow, data.Length - 1); 
     // transform formated data into string[,] 
     string[][] splitedData = formatedData.Select(s => s.Split('\t')).ToArray(); 
     var colCount = splitedData.Max(r => r.Length); 
     var excelData = new string[splitedData.Length, colCount]; 
     for (int i = 0; i < splitedData.Length; i++) 
     { 
      for (int j = 0; j < splitedData[i].Length; j++) 
      { 
       excelData[i, j] = splitedData[i][j]; 
      } 
     } 
     oSheet.get_Range("A" + bestRow.ToString()).Resize[splitedData.Length, colCount].Value = excelData; 
     MainWindow.mainWindowDispacter.BeginInvoke(new System.Action(() => MainWindow.mainWindow.debugTextBox.AppendText("Done with " + rds + " input!" + Environment.NewLine))); 
    } 
+1

Возможно, стоит попробовать: Прочтите все данные из Excel, работайте с ним в своем приложении, а затем напишите все это за один раз. – Raidri

+0

У меня нет большого опыта работы с Interop, но главная причина плохой производительности - это, как правило, использование нескольких диапазонов. Вы должны стремиться получить один относительно большой диапазон (если возможно тот, который представляет весь рабочий лист), а затем выполнить все необходимые операции над ним, а затем повторить его с другим большим диапазоном. –

+0

@ Raidri Я получил usedRange для моего листа, плохо отредактировал этот диапазон в моем коде теперь, каков метод замены листа usedRange с моим новым? –

ответ

0

Мое предположение, что ваш for цикл с r.Insert делает это медленно, потому что ваш numberof велик. Это заставляет Excel перемещать всю электронную таблицу numberof раз, вставляя по одной строке за раз.

Это, вероятно, намного быстрее, если вставить нужное количество строк сразу:

private void shiftRows(int from, int numberof) 
{ 
     // Excel starts at 1 
     from = from+1; 
     // Insert numberof rows at row from 
     oXL.Rows(String.Format("{0}:{1}", from, from+numberof)) 
     .Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftDown); 
} 

Дополнительные вопросы, которые могут помочь:

Как быстро это точно, и как быстро вы хотите это? В какой ситуации это замедляется?

+0

Я бы рекомендовал установить 'Application.EnableAnimations' в FALSE – Seb

0

Чтобы эффективно писать значения на листе, вы не должны напрямую писать на лист непосредственно. Вам нужно объявить массив объектов только для строк или столбцов или двухмерный массив объектов для сетки. Заполните эти объекты необходимыми значениями. Затем объявите объект Range из целевого рабочего листа, затем установите его начальное местоположение (Offset) и измените его размер с длиной (/ s) вашего массива. Напишите в диапазон 1 раз, установив значение диапазона с помощью массива объектов.

public static void Write(
     _Worksheet worksheet, object[,] values, int rowIndex, int columnIndex, ExcelFormatter formatter) 
    { 
     if (worksheet == null) 
     { 
      return; 
     } 

     if (values == null) 
     { 
      return; 
     } 

     var range = (Range)worksheet.Cells.Item[1, 1]; 

     // range = range.get_Offset(rowIndex, columnIndex); // this did not work when cell 1,1 is a merged cell (column wise); offset moves by columns first before rows 
     range = range.Offset[rowIndex, 0]; // this partially solves the problem 
     range = range.Offset[0, columnIndex]; 

     // may need a different algo if cell 1,1 is a merged cell (row wise) 
     range = range.Resize[values.GetLength(0), values.GetLength(1)]; 
     range.set_Value(XlRangeValueDataType.xlRangeValueDefault, values); 
     if (formatter != null) 
     { 
      formatter.Invoke(range); 
     } 

     ReleaseObject(range); 
    } 
Смежные вопросы