IRange.Copy создает исключение InvalidOperationException для объединенных ячеек - PullRequest
0 голосов
/ 17 октября 2019

Я использую метод ниже, чтобы скопировать значение без формулы из диапазона Excel в тот же диапазон (в основном удаление формулы). В этом диапазоне 7 ячеек, но они объединены.

void Copy(IRange destination, PasteType pasteType, PasteOperation pasteOperation, bool skipBlanks, bool transpose);

Я получаю исключение InvalidOperationException с сообщением «Операция недопустима для частично объединенной ячейки.»

SpreadsheetGear.Core Версия - 8.0. 63.102

Это хорошо работает с одной ячейкой, но не с объединенными ячейками.

sourceRange.Copy(targetRange, SpreadsheetGear.PasteType.Values, SpreadsheetGear.PasteOperation.None, false, false);

1 Ответ

0 голосов
/ 17 октября 2019

Такое поведение является заданным, поскольку SpreadsheetGear не позволяет вставлять в диапазон, который включает частично объединенные ячейки. Вместо этого вам нужно будет каким-то образом адаптировать операцию вставки, чтобы диапазон назначения полностью включал все ячейки, которые являются частью объединенного диапазона. В интерфейсе IRange есть несколько API, которые могут помочь вам определить, является ли данный IRange частью объединенного диапазона, и вернуть отрегулированные IRange для учета этого:

  • IRange. MergeCells - Получает или задает свойство, которое указывает, будет ли объединена верхняя левая ячейка этого IRange.
  • IRange. MergeCellsDefined - Возвращает true, если свойство MergeCells всех ячеекпредставленный этим IRange имеет значение false или если все ячейки, представленные этим IRange, содержатся в одной и той же объединенной области ячеек, в противном случае возвращается false.
  • IRange. MergeArea - Возвращает IRange, представляющий объединенноеобласть ячейки, если ячейка, представленная этой одиночной ячейкой IRange, является частью диапазона объединенной ячейки, в противном случае возвращается исходный IRange.
  • IRange. CompleteMergeArea - Возвращает IRange, представляющий областьтекущий IRange, который итеративно растет по мере необходимости, пока он не включает в себя частично объединенные ячейки.

Ниже приведен пример кода, демонстрирующий, как вы можете использовать некоторые из перечисленных выше API для работы с вашим делом. Обратите внимание, что в зависимости от диапазонов, используемых в операции копирования (одна ячейка против нескольких ячеек), подход может отличаться.

// Setup a workbook with some test data and a merged range.
IWorkbook workbook = Factory.GetWorkbook();
IRange cells = workbook.ActiveWorksheet.Cells;
cells["A1:B2"].Formula = "=ROW()+COLUMN()";
cells["A1:A7"].Merge();

//For a single cell copy operation
{
    IRange copyPasteRange = cells["A1"];

    // If IRange.MergeCells is true, A1 will be part of a larger merged range, so we 
    // should use the IRange.MergeArea property to expand A1 to include the entire 
    // merged range
    if (copyPasteRange.MergeCells)
        copyPasteRange = copyPasteRange.MergeArea;
    copyPasteRange.Copy(copyPasteRange, PasteType.Values, PasteOperation.None, false, false);
}

// For a multi-cell copy operation.  
{
    // Note in this case that A1 is part of merged range A1:A7 but B2 is not merged.  
    // How you deal with this depends on your requirements.  
    IRange copyPasteRange = cells["A1:B2"];

    // One way is to use IRange.EntireMergeArea which will iteratively grow the specified 
    // IRange until it fully includes all merged ranges, so in this case A1:B7.  
    // Obviously, this means B2:B7 will be copied as a side-effect, but this is what 
    // would happen if you tried to copy this range in Excel's UI (i.e., when attempting 
    // to select A1:B1 in Excel, they will always expand the selected range to A1:B7), 
    // so might be acceptable in some cases.
    if (copyPasteRange.Address != copyPasteRange.EntireMergeArea.Address)
        copyPasteRange = copyPasteRange.EntireMergeArea; // A1:B7
    copyPasteRange.Copy(copyPasteRange, PasteType.Values, PasteOperation.None, false, false);

    // Alternatively, you could loop through each cell in the originalCopyPaste 
    // range and copy each cell as needed.  I leave it up to you to flesh this out if 
    // it is necessary for your requirements.
    if (copyPasteRange.Address != copyPasteRange.EntireMergeArea.Address)
    {
        foreach (IRange cell in copyPasteRange)
        {
            // Paste by value for each cell, taking into account merged cells however you 
            // see fit.
        }
    }
}
...