C# Исключение Excel OutOfMemory, вызванное вставкой в ​​диапазон - PullRequest
0 голосов
/ 02 марта 2020

Я работал над довольно сложным C# проектом VSTO, который делает много разных вещей в Excel. Однако недавно я наткнулся на проблему, которую не знаю, как решить. Я боюсь, что размещение всего проекта здесь усложнит мой вопрос и запутает всех, так что это часть проблемы:

//this is a simplified version of Range declaration which I am 100% confident in
Range range = worksheet.Range[firstCell, lastCell] 

range.Formula = array; 
//where array is a object[,] which basically contains only strings and also works perfeclty fine

Последняя строка, которая должна вставить массив [,] в Диапазон Excel раньше работал для небольших книг Excel, но теперь вылетает для больших книг с System.OutOfMemoryException: Insufficient memory to continue the execution of the program, и я понятия не имею, почему, потому что раньше он работал с массивами длиной более 500 элементов для одного из своих измерений, тогда как теперь он падает для массива с менее чем 400 элементами. Кроме того, на момент использования cra sh объем используемой оперативной памяти составляет около 1,2 ГБ, и я знаю, что этот проект способен прекрасно работать с использованием оперативной памяти ~ 3 ГБ.

Я пробовал следующие вещи: вставка этот массив строка за строкой, затем вставляя его ячейка за ячейкой, вызывая G C .Collect () перед каждой вставкой строки или ячейки, но он, тем не менее, обработает sh с System.OutOfMemoryException.

Поэтому я был бы признателен за любую помощь в решении этой проблемы или определении того, где ошибка может скрываться, потому что я не могу понять, почему она отказывается работать с массивами меньшей длины (но, возможно, с небольшой большее содержание) при уровне использования ОЗУ 1,2 ГБ, что составляет 1/3 от того, что он использовал для обработки. Спасибо!

РЕДАКТИРОВАТЬ

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

List<object[][]> controlsList = new List<object[][]>();
// this list is filled with a quite long method calling a lot of other functions
// if other parts look fine, I guess I'll have to investigate it

int totalRows = 1;

foreach (var control in controlsList)
{
    if (control.Length == 0)
        continue;

    var range = worksheet.GetRange(totalRows + 1, 1, totalRows += control.Length, 11);
    //control is an object[n][11] so normally there are no index issues with inserting
    range.Formula = control.To2dArray();
}

//GetRange and To2dArray are extension methods
public static Range GetRange(this Worksheet sheet, int firstRow, int firstColumn, int lastRow, int lastColumn)
{
    var firstCell = sheet.GetRange(firstRow, firstColumn);
    var lastCell = sheet.GetRange(lastRow, lastColumn);

    return (Range)sheet.Range[firstCell, lastCell];
}

public static Range GetRange(this Worksheet sheet, int row, int col) => (Range)sheet.CheckIsPositive(row, col).Cells[row, col];

public static T CheckIsPositive<T>(this T returnedValue, params int[] vals)
{
    if (vals.Any(x => x <= 0))
        throw new ArgumentException("Values must be positive");

    return returnedValue;
}

public static T[,] To2dArray<T>(this T[][] source)
{
    if (source == null)
        throw new ArgumentNullException();

    int l1 = source.Length;
    int l2 = source[0].Length(1);

    T[,] result = new T[l1, l2];

    for (int i = 0; i < l1; ++i)
        for (int j = 0; j < l2; ++j)
            result[i, j] = source[i][j];

    return result;
}

1 Ответ

0 голосов
/ 04 марта 2020

Я не уверен на 100%, что все правильно понял, но похоже, что проблема заключается в ограничениях Interop.Excel / Excel и длине формул, которые я пытаюсь вставить: всякий раз, когда длина приближается к 8 тыс. Символов, близко к пределу Excel для содержания формулы, System.OutOfMemoryException выскакивает. Когда я решил оставить длинные формулы, программа начала работать нормально.

...