When copying multiple source ranges from different workbooks, only the range copied from the first workbook will have its row outline levels preserved. Any subsequent ranges are assigned zero for all rows. The following programmatic steps should be able to reproduce the issue using the workbooks in the attached ZIP file:
-
With a new workbook created, copy the STRUCTURE named range from the Input_STRUCTURE workbook and place it at the top of the destination worksheet. The second row should have outline level 1, which is expected.
-
Copy the ECON_EXP_PENSION named range from the Input_ECON_EXP_PENSION workbook and place it directly below the previous range in the new workbook. The second row of this range is supposed to have outline level 1, but it ends up 0 in the destination workbook.
Dev.zip (94.3 KB)
Please let me know if you are able to reproduce and if so, if there’s any way we can fast track a fix so I don’t have to wait another month for it to be available. Thank you.
I’ll certainly try the above suggestion, but frankly, it’s more of a workaround than an actual fix. Aspose should be able to handle this automatically for any range copied from one workbook to another - as with the bug that was filed and recently fixed for style merging, this is an operation that Excel handles without any sort of manual intervention, and making this and other operations automatic via simple method calls should be a proactive effort on your part, not reactive based on users reporting bugs.
After looking more closely, the above code suggestion is, to put it bluntly, a bunch of AI-generated garbage. GetRowOutlineLevel is a function that returns an int, not a property that can be set. I request a better solution for a workaround, one written by a human this time, and a confirmation that a bug will be filed to fix this.
@bytefyre
Through studying the provided sample files, we found that the data range for ECON_EXP-PENSE is “=Input Blocks!$2: $13”. There is only one level of outline within this scope. The last line of the outline for the first level is 14. So after copying the scope, there is only one hierarchical outline. If you want to get two levels of outlines, the first way is to modify the data range of ECON_EXP-PENSE in the Excel file to “=Input Blocks!$2: $14”, and the second way is to add a line of data when copying. Please refer to the following example code, you will get the correct outline of two levels.
// Load the source workbooks
Workbook inputStructureWorkbook = new Workbook(filePath + "Input_STRUCTURE.xlsx");
Workbook inputEconExpPensionWorkbook = new Workbook(filePath + "Input_ECON_EXP_PENSION.xlsx");
// Create a new workbook for the destination
Workbook destinationWorkbook = new Workbook();
Worksheet destinationSheet = destinationWorkbook.Worksheets[0];
// Copy the STRUCTURE named range
Range structureRange = inputStructureWorkbook.Worksheets.GetRangeByName("Input Blocks!STRUCTURE");
Range range1 = destinationSheet.Cells.CreateRange(0, 0, structureRange.RowCount, structureRange.ColumnCount);
range1.Copy(structureRange);
// Copy the ECON_EXP_PENSION named range
Range sourceRange = inputEconExpPensionWorkbook.Worksheets.GetRangeByName("Input Blocks!ECON_EXP_PENSION");
//Add a line to the copied range
Cells tempCells = inputEconExpPensionWorkbook.Worksheets["Input Blocks"].Cells;
Range econExpPensionRange = tempCells.CreateRange(sourceRange.FirstRow, sourceRange.FirstColumn, sourceRange.RowCount + 1, sourceRange.ColumnCount);
Range range2 = destinationSheet.Cells.CreateRange(structureRange.RowCount, 0, econExpPensionRange.RowCount, econExpPensionRange.ColumnCount);
range2.Copy(econExpPensionRange);
// Save the destination workbook
destinationWorkbook.Save(filePath + "out_net.xlsx");
Hope helps a bit.
Hi John,
Thank you for your reply. I actually ended up figuring out a way to manually set the group levels for each destination row from the corresponding source row. However, I now seem to have some difficulty in figuring out how to properly collapse each section of grouped rows. I’d appreciate your help on this, too.
It appears that Worksheet.Cells.GetMaxGroupedRowOutlineLevel() does not function properly. Even though I can see rows on my worksheet that have GroupLevel = 6, the function always returns zero.
@bytefyre,
I tested it using both files you provided, and it appears to work correctly in retrieving the maximum grouped row outline level. If possible, could you kindly share the resource files along with a standalone sample code or a runnable application to help us reproduce the issue? We will look into the issue soon.
Hi Amjad,
When sequentially copying the two named ranges I mentioned previously onto a new worksheet in a separate workbook, I executed the following code:
for (var r = 0; r < srcRange.RowCount; r++)
{
var srcRow = srcRange.Worksheet.Cells.Rows[srcRange.FirstRow + r];
var destRow = inputSheet.Cells.Rows[startRow + r];
destRow.GroupLevel = srcRow.GroupLevel;
}
// startRow refers to the row index on the destination sheet where the new range begins
After doing this operation twice, once for each named range, this code follows:
var maxRow = sheet.Cells.MaxDataRow;
var maxLevel = sheet.Cells.GetMaxGroupedRowOutlineLevel();
for (var i = maxLevel; i >= 1; i--)
{
for (var r = 0; r < maxRow; r++)
{
if (sheet.Cells.GetGroupedRowOutlineLevel(r) == i)
{
sheet.Cells.HideGroupDetail(true, r);
}
}
}
A breakpoint after the initialization of maxLevel will show that its value is zero.
@bytefyre
It should be the issue of copying range.
Workbook workbook = new Workbook();
Workbook a = new Workbook(dir + "Input_STRUCTURE.xlsx");
Range ra = a.Worksheets.GetRangeByName("'Input Blocks'!STRUCTURE");
Range rd = workbook.Worksheets[0].Cells.CreateRange(0, 0, ra.RowCount, ra.ColumnCount);
rd.Copy(ra);
rd = workbook.Worksheets[0].Cells.CreateRange(ra.RowCount, 0, ra.RowCount, ra.ColumnCount);
Workbook b = new Workbook(dir + "Input_ECON_EXP_PENSION.xlsx");
Range rb = b.Worksheets.GetRangeByName("'Input Blocks'!ECON_EXP_PENSION");
rd.Copy(rb);
workbook.Save(dir + "dest.xlsx");
And Could you share an excepted result file ?
We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.
Issue ID(s): CELLSNET-58743
You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.
@bytefyre
Do you want to dynamically change the scope of the outline so that it can be fully copied to the new range? Would you like to provide complete and executable test code and expected results? We will check it soon.
Well, apparently, it’s not an issue of just making sure the range size is correct. This is the Watch I currently have set up in Visual Studio:
AsposeMaxGroupLevelWatch.png (16.9 KB)
@bytefyre
If you want to extend the group if the copied range does not contain whole group, please try the following codes:
private static int CopyRange(Worksheet worksheet, int row,Range source)
{
Cells cells = worksheet.Cells;
Range r = cells.CreateRange(row, 0, source.RowCount, source.ColumnCount);
r.Copy(source);
int endRow = row + source.RowCount - 1;
Row rowInfo = cells.CheckRow(endRow);
if (rowInfo != null && rowInfo.GroupLevel > 0)
{
for (int level = rowInfo.GroupLevel - 1; level >= 0; level--)
{
Row nextRow = cells.Rows[endRow + 1 + (rowInfo.GroupLevel - 1) - level];
nextRow.GroupLevel = (byte)level;
if(worksheet.Outline.SummaryRowBelow)
nextRow.IsCollapsed = true;
}
return r.RowCount + rowInfo.GroupLevel - 1;
}
return r.RowCount;
}
@bytefyre,
We are pleased to inform you that your issue (Ticket ID: “CELLSNET-58743”) has been resolved. The fix/enhancement will be included in the upcoming release of Aspose.Cells (v25.8), scheduled for the first half of August 2025. You will be notified once the new version is published.
The issues you have found earlier (filed as CELLSNET-58743) have been fixed in this update. This message was posted using Bugs notification tool by leoluo