NPOI - 在单元格左侧添加单元格注释

NPOI - Adding cell comment to the left of a cell

我目前正在使用此代码显示给定单元格的评论:

public static void AddCellComment(ICell cell, IDrawing patr)
    {
        var commentString = "Something";

        var anchor = new XSSFClientAnchor
        {
            Col1 = cell.ColumnIndex,
            Col2 = cell.ColumnIndex + 2,
            Row1 = cell.RowIndex,
            Row2 = cell.RowIndex + 1
        };

        var comment = patr.CreateCellComment(anchor);
        comment.String = new XSSFRichTextString(commentString);

        cell.CellComment = comment;
    }

这成功地为单元格右侧的给定单元格创建了 2 列乘 1 行宽的注释。我尝试将 cell.ColumnIndex - 2 放在 Col1 或 Col2 中,它要么导致工作簿损坏,其中 none 的评论有效,要么导致评论不可见。有没有办法让评论显示在单元格的左边?

好的,下面是我的实验结果:

首先,如果您希望自己的单元格悬停时可以精确定义评论的位置,您会失望的。

这是不可能的。 Excel.

根本不支持它

将鼠标悬停在有评论的单元格上时,Excel 自行决定将评论放置在何处,并且似乎总是显示在单元格的右侧。您可以尝试在编辑模式下移动评论,当单元格悬停时它仍会显示在同一位置。 (本人亲身体验,在此tutorial link.

得到印证

那么,知道了,你可以控制的是:

  • 评论框的大小。
  • 它的位置,但仅在编辑模式下

这两个特征都受 XSSFClientAnchor 属性支配。根据 npoi source codeCol1Row1Col2Row2 定义两个单元格,这两个单元格依次表示区域(以及仅在编辑模式下的位置)注释:单元格 #1 将包含在该区域中,而单元格 #2 则不会。

  • 第一个单元格必须是评论区的top-left(准确地说,单元格#1的top-left将是top-left评论框)
  • 第二个必须是区域的bottom-right(准确地说,单元格#2的top-left将是bottom-right评论框)

我认为这条规则解释了为什么你的一些尝试以奇怪或空洞的评论结束(我也转载了其中一些):鉴于上述规则,你必须始终拥有:Col2 > Col1Row2 > Row1.虽然我没有测试它,但我也怀疑(绝对)负数的列或行不起作用,因此当从输入单元格的列或行中减去值时,您应该确保结果不会以 < 0.. .

关于 XSSFClientAnchor 的最后一点说明:还有 4 个其他属性可以帮助您微调评论的大小和(仅限版本模式)位置:Dx1Dy1 , Dx2Dy2:这四个属性允许您 add/subtract 一些大小到单元格 x 和 y 坐标。它们以一个奇怪的单位表示:EMU。您可以在一个像素中放置 9525 个 EMU。

利用所有这些知识,我设计了一个简单的测试(基于你的和 npoi 教程的组合)。这是:

private static void Main()
{
    var workbook = new XSSFWorkbook();
    var sheet = workbook.CreateSheet("My sheet");

    var row = sheet.CreateRow(10);
    var cell = row.CreateCell(10);
    cell.SetCellValue("Here");

    var patr = sheet.CreateDrawingPatriarch();
    AddCellComment(cell, patr);

    using var stream = new FileStream(@"c:\temp\test.xlsx", FileMode.Create, FileAccess.Write);
    workbook.Write(stream);
}

private static int PixelsToEmus(int pixels) => pixels * Units.EMU_PER_PIXEL;

private static void AddCellComment(ICell cell, IDrawing patr)
{
    // Let's make a 3x2 cells comment area, then tweak it a bit
    var anchor = new XSSFClientAnchor
    {
        // Top left cell
        Col1 = 5, // 6th column
        Row1 = 5, // 6th row
        // Bottom right cell
        Col2 = 8, // 3 cells wide
        Row2 = 7, // 2 cells high
        // Top left shift
        Dx1 = PixelsToEmus(10), // 10 pixels to the left of 6th column's left border
        Dy1 = PixelsToEmus(10), // 10 pixels to the bottom of 6th row's top border
        // Bottom right shift
        Dx2 = PixelsToEmus(30),  // 30-10=20 pixels wider than 3 columns
        Dy2 = PixelsToEmus(10),  // exactly as high as 2 rows
    };

    var comment = patr.CreateCellComment(anchor);
    comment.String = new XSSFRichTextString("Something");
    cell.CellComment = comment;
}

当 运行 这样做时,我最终得到这些结果(显示悬停位置和编辑模式位置):

为了完整起见,我 double-checked 在生成的 xslx 中写了什么(解压后,我查看了 test\xl\drawings\vmlDrawing1.vml,特别是注释的 <x:Anchor> 标签object 其中我们找到了我们在程序中设置的确切值:

<x:Anchor>5, 10, 5, 10, 8, 30, 7, 10</x:Anchor>

npoi 的源代码帮助我(希望你)了解一切是如何工作的:

PS:对于这些测试,我使用了 .NET Core 3.1 应用程序和 NPOI v2.5.2 Nuget package