【问题标题】:NPOI - Adding cell comment to the left of a cellNPOI - 在单元格左侧添加单元格注释
【发布时间】:2020-09-07 13:05:43
【问题描述】:

我目前正在使用此代码来显示给定单元格的注释:

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 列 x 1 行宽的注释。我尝试将cell.ColumnIndex - 2 放在 Col1 或 Col2 中,这会导致工作簿损坏,其中所有 cmets 都不起作用或出现不可见的评论。有没有办法让评论显示在单元格的左侧?

【问题讨论】:

    标签: c# excel comments cell npoi


    【解决方案1】:

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

    首先,如果您希望在其所属单元格悬停时能够精确定义评论的位置,您会失望的。

    这是不可能的。 Excel 根本不支持它。

    当悬停有注释的单元格时,Excel 会自行决定将注释放置在何处,并且似乎总是将其显示在单元格的右侧。您可以尝试在编辑模式下移动评论,当单元格悬停时它仍然会显示在同一位置。 (我自己亲身经历过,在这个tutorial link得到了确认。

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

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

    这两个特征都由XSSFClientAnchor 属性控制。根据npoi source codeCol1Row1Col2Row2 定义两个单元格,它们依次代表评论的区域(以及仅在编辑模式下的位置):单元格 #1 将包含在区域,而单元格 #2 不会。

    • 第一个单元格必须是评论区的左上角(确切地说,单元格#1 的左上角将是评论框的左上角)
    • 第二个必须是该区域的右下角(准确地说,单元格#2 的左上角将是评论框的右下角)

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

    关于 XSSFClientAnchor 的最后一点说明:还有 4 个其他属性可以帮助您微调评论的大小和(仅限编辑模式)位置:Dx1Dy1Dx2Dy2 :这四个属性允许您为单元格 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;
    }
    

    运行此程序时,我最终得到以下结果(显示悬停位置和编辑模式位置):

    为了完整起见,我仔细检查了生成的 xslx 中写入的内容(解压缩后,我查看了 test\xl\drawings\vmlDrawing1.vml,特别是 Note 对象的 <x:Anchor> 标记,我们在其中找到了我们的确切值在程序中设置:

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

    npoi 的源代码帮助我(希望你)了解 averything 的工作原理:

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

    【讨论】:

    • 不是我希望的答案,但你为我提供了巨大的服务,谢谢!