好的,下面是我的实验结果:
首先,如果您希望在其所属单元格悬停时能够精确定义评论的位置,您会失望的。
这是不可能的。 Excel 根本不支持它。
当悬停有注释的单元格时,Excel 会自行决定将注释放置在何处,并且似乎总是将其显示在单元格的右侧。您可以尝试在编辑模式下移动评论,当单元格悬停时它仍然会显示在同一位置。 (我自己亲身经历过,在这个tutorial link得到了确认。
那么,知道了,你可以控制的是:
这两个特征都由XSSFClientAnchor 属性控制。根据npoi source code、Col1、Row1 和Col2、Row2 定义两个单元格,它们依次代表评论的区域(以及仅在编辑模式下的位置):单元格 #1 将包含在区域,而单元格 #2 不会。
- 第一个单元格必须是评论区的左上角(确切地说,单元格#1 的左上角将是评论框的左上角)
- 第二个必须是该区域的右下角(准确地说,单元格#2 的左上角将是评论框的右下角)
我认为这条规则解释了为什么你的一些尝试以奇怪或空的 cmets 结束(我也复制了其中一些):鉴于上述规则,你必须始终拥有:Col2 > Col1 和 Row2 > Row1。虽然我没有测试它,但我也怀疑(绝对)负列或行不起作用,因此当从输入单元格的列或行中减去值时,您应该确保结果不会以
关于 XSSFClientAnchor 的最后一点说明:还有 4 个其他属性可以帮助您微调评论的大小和(仅限编辑模式)位置:Dx1、Dy1、Dx2 和 Dy2 :这四个属性允许您为单元格 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