PDF页数计算算法优化请求:解决多算一页问题
改进PDF页数计算算法的思路
原算法用于计算生成PDF所需的总页数,以便在页面底部显示分页信息(如“当前页码 / 总页数”),但在部分场景下会出现多计算一页的问题,以下是问题分析和改进思路:
原算法代码
int idx, pckIdx, totalPages; bool increment; foreach (MyObject item in result.OrderBy(x => x.Name)) { idx = 0; increment = false; itemsGrouped = item.Lines.GroupBy(grp => grp.Order); foreach (var itemLineGrp in itemsGrouped.OrderBy(r => r.Key)) { pckIdx = 1; foreach (MyObjectLine itemLine in itemLineGrp) { if (idx % rowsPerPage == 0 && idx != 0) { totalPages++; idx = 0; } idx++; increment = true; } if (idx % rowsPerPage == 0 && idx != 0) { totalPages++; idx = 0; } } totalPages++; } public class MyObject { public string Name { get; set; } public IList<MyObjectLine> Lines { get; set; } // Other props } public class MyObjectLine { public int Order { get; set; } // Other props }
原算法的问题点
- 每个
MyObject末尾强制加页:无论该对象的内容是否已经被完全计算页数,都会执行totalPages++,这会导致当对象内容刚好占满整数页时,额外多算一页。 - 重复的分页判断:在分组内的行循环结束后,又重复判断一次分页条件,和行循环内的判断逻辑重叠,可能导致重复计数。
- 未处理空内容边界:如果某个
MyObject没有Lines数据,或者分组后没有内容,依然会强制加一页,造成无效计数。
改进思路与优化代码
核心优化方向
- 移除强制加页逻辑:删除每个
MyObject循环末尾的totalPages++,页数完全由实际内容的行数决定。 - 用向上取整统一计算页数:对于每个对象的总行数,使用
(总行数 + rowsPerPage - 1) / rowsPerPage的公式快速计算所需页数,避免逐行计数的误差。 - 增加空内容判断:当对象没有有效行数据时,不计算页数。
优化后的示例代码
int totalPages = 0; int rowsPerPage = // 你的每页行数配置 foreach (MyObject item in result.OrderBy(x => x.Name)) { // 先获取当前对象的所有有效行数 int totalLines = item.Lines?.Count ?? 0; if (totalLines == 0) { continue; // 空内容跳过,不计算页数 } // 计算当前对象需要的页数:向上取整 int pagesForItem = (totalLines + rowsPerPage - 1) / rowsPerPage; totalPages += pagesForItem; } // 类定义保持不变 public class MyObject { public string Name { get; set; } public IList<MyObjectLine> Lines { get; set; } // Other props } public class MyObjectLine { public int Order { get; set; } // Other props }
若需保留分组分页逻辑(比如分组间强制分页)
如果你的业务要求每个Order分组必须单独分页(即不同分组不能在同一页),可以调整为按分组计算页数:
int totalPages = 0; int rowsPerPage = // 你的每页行数配置 foreach (MyObject item in result.OrderBy(x => x.Name)) { if (item.Lines == null || !item.Lines.Any()) { continue; } var itemsGrouped = item.Lines.GroupBy(grp => grp.Order).OrderBy(r => r.Key); foreach (var group in itemsGrouped) { int groupLineCount = group.Count(); // 每个分组的页数向上取整 int pagesForGroup = (groupLineCount + rowsPerPage - 1) / rowsPerPage; totalPages += pagesForGroup; } }
内容的提问来源于stack exchange,提问作者Antônio MFA
相关产品推荐
相关产品推荐

