【问题标题】:Range returning a wrong set of Cells范围返回一组错误的单元格
【发布时间】:2020-05-25 21:04:43
【问题描述】:

我正在使用 Excel 互操作,并试图返回与我从工作表中获得的第一个单元格范围相关的单元格范围。问题是范围的第二次获取它没有给我预期的单元格。代码如下:

Range cells = xlWorkSheet.Range[
    xlWorkSheet.Cells[5, 5],
    xlWorkSheet.Cells[9, 9]
];

Range cells2 = cells.Range[cells[2, 2], cells[3, 3]];

在第二个 Range 调用中,我期望将 Cells 从 [6, 6] 到 [7, 7] (相对于工作表)。相反,我将 [10, 10] 变为 [11, 11]。

如果我单独得到一个单元格,我会得到预期的单元格:

Range c1 = cells.Cells[2, 2];

这将返回 [6, 6] 单元格。关于我为什么会出现这种行为的任何想法?

【问题讨论】:

  • cells.Range["B2"].Resize[2,2]
  • 试试Range cells2 = cells.Range[cells.Cells[2, 2], cells.Cells[3, 3]];
  • @JohnyL Resize 完成了这项工作。谢谢你,但你知道为什么范围方法不起作用吗?
  • @SrinikaPinnaduwage 我已经尝试过(使用 .Cells),但它仍然给了我在问题中提到的相同范围。
  • 我已经发布了答案。请让我知道它是否解决了您的问题。 ??????

标签: c# excel-interop


【解决方案1】:

这里解释了为什么你没有得到你需要的结果。

enum ColorConstants 
{
    vbYellow = 65535,
    vbRed = 255
}

Excel.Application excel = new Excel.Application
{ 
    Visible = true, 
    WindowState = Excel.XlWindowState.xlMaximized 
};
Excel.Workbook book = excel.Workbooks.Add();
Excel.Worksheet sheet = book.Sheets[1] as Excel.Worksheet;

// We have initial range "E5:I9"
Excel.Range cells = sheet.Range[sheet.Cells[5, 5], sheet.Cells[9, 9]];
cells.Interior.Color = ColorConstants.vbYellow; //Color the range

// Now your goal is to get range "F6:G7" (relative to the sheet),
// which is range "B2:C2" (relative to "cells" range)

// Let's dissect why this isn't the result you need

// You try to achieve your goal with this code:
Excel.Range cells2 = cells.Range[cells.Cells[2, 2], cells.Cells[3, 3]];
cells2.Interior.Color = ColorConstants.vbRed;

// However, the result is incorrect:
// it gives you "J10:K11" range:
string addr = cells2.Address[0, 0]; //=> J10:K11

// Let's see why this happens.
// The thing is that the cell, returned by Cells,
// is relative to SHEET - and not to YOUR RANGE.

// Start cell (top-left): its address is "F6"
Excel.Range cell_start = cells.Cells[2, 2];

// End cell (bottom-rigth): its address is "G7"
Excel.Range cell_end = cells.Cells[3, 3];

// So, we have "F6:G7" address.
// Now we must imagine that our initial range "E5:I9" - and namely "E5" - is the start cell of the sheet.
// When you do it, our "F6:G7" relatively to "E5:I9" will be "J10:K11",
// because "F6:G7" goes OUTSIDE the boundaries of "E5:I9".
// If you calculate correctly, it will be our incorrect "J10:K11" range.
// This is why you get incorrect result.

// To calculate the offset correctly,
// you must imagine your range as a small worksheet.
// For instance, for our range "E5:I9":
// • "E5" (statrt cell) can be referred to as:
//    1) cells.Cells[1]
//    2) cells.Cells[1, 1]
//    2) cells.Cells[1, "A"]
//    3) cells.Cells["A1"]
// • "F6" (end cell) can be referred to as:
//    1) cells.Cells[7]
//    2) cells.Cells[2, 2]
//    3) cells.Cells[2, "B"]
//    4) cells.Range["B2"]

// Thus, we need another approach:
cells2 = cells.Range["B2"].Resize[2, 2];
cells2 = cells.Cells[2, 2].Resize[2, 2];
cells2 = cells.Range["B2:C3"];
cells2.Interior.Color = ColorConstants.vbRed; //Color the range

【讨论】:

  • 我现在明白了,很好的解释。不过,还有一个问题:当我们调用调整大小时,我们在做什么?
  • @Leone 当您调用Resize 时,您重新定义了您的范围,起点是原始单元格的左上角单元格。 :)
  • 只是名称似乎不适合我想要做的事情。似乎我们正在选择一个单元格并对其进行多个副本,直到我们填充由我们传递给调整大小索引器的参数指定的范围。但无论如何,它有效,它解决了我的问题,所以谢谢你的帮助和详细的解释。
  • @LeonelB。我看到了你的担心。将Resize 视为乐高砖墙。当你需要改变这面墙的大小时,你只留下这面墙的左上角的砖块,然后再把砖块放回你需要的大小。这就像破坏和重建。 ?
【解决方案2】:

是的,在您的情况下,cells.Parent 是 xlWorkSheet 对象。

为了完整起见,请注意,您可以使用以下任何一种方法,您将获得与您希望看到的相同的成功结果:

Range cells2 = cells.Parent.Range[cells.Cells[2, 2], cells.Cells[3, 3]];

Range cells2 = xlWorkSheet.Range[cells.Cells[2, 2], cells.Cells[3, 3]];

Range cells2 = cells.Range[xlWorkSheet.Cells[2, 2], xlWorkSheet.Cells[3, 3]];

【讨论】:

  • 您的意思是 Range cells2 = cells[cells.Cells[2, 2], cells.Cells[3, 3]];?它返回单元格 [4,4]。
  • 抱歉,试试修改后的版本。谢谢。
  • 它确实有效,但是调用 Parent 如何使范围相对于当前范围而不是工作表表现?本次通话中的家长是谁?不是工作表吗?
  • 请看我的扩展答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 2022-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多