如何移除MigraDoc表格分页处底部的多余边框?
装箱单PDF多余边框问题解决(MigraDoc/PDFSharp)
问题背景
我在Visual Studio 2015中使用MigraDoc(v1.50.5147)和.NET Framework 4.5.2制作装箱单PDF,文档包含带重复表头的单表格:
- “容器行”带边框,下方“零件行”无边框
- 容器行与零件行不允许跨页拆分
当前问题:分页前每页底部会出现由容器行边框导致的多余边框,但需要保留容器行的正常边框。
最小复现代码
static void Main(string[] args) { Document document = new Document(); Section section = document.AddSection(); section.PageSetup = document.DefaultPageSetup.Clone(); Unit sectionWidth = section.PageSetup.PageWidth - section.PageSetup.LeftMargin - section.PageSetup.RightMargin; Table table = section.AddTable(); table.TopPadding = "0.5mm"; table.BottomPadding = "0.5mm"; Column column = table.AddColumn(sectionWidth * 0.10); column = table.AddColumn(sectionWidth * 0.20); column = table.AddColumn(sectionWidth * 0.7); Row row = table.AddRow(); // 表头行 row.Borders.Width = "1pt"; Paragraph paragraph = row.Cells[0].AddParagraph(); paragraph.AddFormattedText("QTY", TextFormat.Bold); paragraph = row.Cells[1].AddParagraph(); paragraph.AddFormattedText("UNIT", TextFormat.Bold); paragraph = row.Cells[2].AddParagraph(); paragraph.AddFormattedText("NUMBER", TextFormat.Bold); row.HeadingFormat = true; // 分页重复表头 row.KeepWith = 1; // 表头与下方空白行保持同页 row = table.AddRow(); // 空白行 for (int i = 1; i <= 50; i++) // 重复生成容器+零件行 { row = table.AddRow(); // 容器行 table.SetEdge(0, row.Index, 3, 1, Edge.Box, BorderStyle.Single, "1pt"); // 此设置导致页尾多余边框 row.Cells[0].AddParagraph("1"); row.Cells[1].AddParagraph("BOX"); row.Cells[2].AddParagraph("BOX NUMBER"); row.KeepWith = 2; // 容器行与下方2行零件行保持同页 row = table.AddRow(); // 零件行1 row.Cells[0].AddParagraph("3"); row.Cells[1].AddParagraph("PCS"); row.Cells[2].AddParagraph("PART NUMBER"); row = table.AddRow(); // 零件行2 row.Cells[0].AddParagraph("3"); row.Cells[1].AddParagraph("PCS"); row.Cells[2].AddParagraph("PART NUMBER\n\n"); } PdfDocumentRenderer renderer = new PdfDocumentRenderer(); renderer.Document = document; renderer.RenderDocument(); renderer.Save("document.pdf"); }
问题现象
分页前的页面底部会出现一条额外的水平边框,该边框由容器行的底部边框在分页时异常渲染导致。
解决方案
方案一:MigraDoc原生调整(推荐)
问题根源是KeepWith属性与容器行边框结合时,MigraDoc会在分页时强制渲染容器行的底部边框,即使该行被推至下一页。通过拆分边框设置逻辑可以解决:
- 不为容器行设置完整的
Edge.Box边框,仅保留顶部、左侧、右侧边框 - 将容器行的底部边框转移到下一行零件的顶部边框,避免页尾单独渲染
修改后的核心代码片段:
for (int i = 1; i <= 50; i++) { row = table.AddRow(); // 容器行 // 仅设置上、左、右边框,不设置底部边框 table.SetEdge(0, row.Index, 3, 1, Edge.Top | Edge.Left | Edge.Right, BorderStyle.Single, "1pt"); row.Cells[0].AddParagraph("1"); row.Cells[1].AddParagraph("BOX"); row.Cells[2].AddParagraph("BOX NUMBER"); row.KeepWith = 2; // 零件行1 row = table.AddRow(); row.Cells[0].AddParagraph("3"); row.Cells[1].AddParagraph("PCS"); row.Cells[2].AddParagraph("PART NUMBER"); // 零件行2:用顶部边框替代容器行的底部边框 row = table.AddRow(); table.SetEdge(0, row.Index, 3, 1, Edge.Top, BorderStyle.Single, "1pt"); row.Cells[0].AddParagraph("3"); row.Cells[1].AddParagraph("PCS"); row.Cells[2].AddParagraph("PART NUMBER\n\n"); }
方案二:PDFSharp后处理移除多余边框
如果原生调整无法满足需求,可通过PDFSharp直接修改生成的PDF文档,定位并删除页尾的多余边框:
// 先完成MigraDoc渲染 PdfDocumentRenderer renderer = new PdfDocumentRenderer(); renderer.Document = document; renderer.RenderDocument(); // 使用PDFSharp处理生成的PDF PdfDocument pdfDoc = renderer.PdfDocument; foreach (PdfPage page in pdfDoc.Pages) { PdfDictionary resources = page.Elements.GetDictionary("/Resources"); if (resources != null) { PdfDictionary xObjects = resources.Elements.GetDictionary("/XObject"); if (xObjects != null) { foreach (PdfItem item in xObjects.Elements.Values) { PdfReference reference = item as PdfReference; if (reference != null) { PdfDictionary xObject = reference.Value as PdfDictionary; if (xObject != null && xObject.Elements.GetString("/Subtype") == "/Form") { // 解析内容流 PdfContentParser parser = new PdfContentParser(xObject); List<PdfContent> contents = parser.ParseContent(); // 过滤并删除页尾多余水平边框(需根据实际页面尺寸调整坐标阈值) for (int j = contents.Count - 1; j >= 0; j--) { if (contents[j] is PdfPath path && path.Points.Count == 2) { double yPos = path.Points[0].Y; // 假设页尾区域Y坐标低于20(需根据实际页面设置调整) if (yPos <= 20) { contents.RemoveAt(j); } } } // 写回修改后的内容 xObject.Elements.SetValue("/Contents", PdfContentWriter.WriteContent(contents)); } } } } } } pdfDoc.Save("document_fixed.pdf");
注意:需根据实际页面尺寸调整坐标判断阈值,确保仅删除多余的页尾边框。
内容的提问来源于stack exchange,提问作者user18463824
相关产品推荐
相关产品推荐

