You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL数据库分页打印问题求助:重复打印前15行无法实现正确分页

SQL数据库分页打印问题求助:重复打印前15行无法实现正确分页

兄弟,我瞅你这分页打印的问题,根源在于每次触发新页面打印时,DataReader都会重新从头读取数据,结果第二页又重复打前15条了!咱们得换个思路,先把要打印的数据一次性缓存到内存里,这样就能精准控制每一页该打印哪部分内容了。

我给你捋个解决方案,分两步走:

第一步:先把所有要打印的数据缓存起来

DataReader是向前只读的,没法跳转到指定位置继续读取,所以咱们先把数据库里的数据全读出来存到集合里,比如用自定义实体类或者字典,这样后续分页打印时直接从内存里取就行,不用再反复查数据库。

示例代码(用实体类更规范):

// 全局变量:缓存打印数据+记录当前打印到哪一条
private List<PrintItem> _printItems = new List<PrintItem>();
private int _currentPrintIndex = 0;
private readonly int _itemsPerPage = 15; // 每页15条

// 打印前先加载数据的方法
private void LoadPrintData()
{
    // 替换成你的数据库连接字符串
    using (var conn = new SqlConnection("你的数据库连接字符串"))
    {
        conn.Open();
        string sql = "SELECT cCode, cName, cShortAddress, cPhone FROM 你的表名";
        using (var cmd = new SqlCommand(sql, conn))
        {
            using (var rdr = cmd.ExecuteReader())
            {
                while (rdr.Read())
                {
                    _printItems.Add(new PrintItem
                    {
                        Code = rdr["cCode"].ToString(),
                        Name = rdr["cName"].ToString(),
                        ShortAddress = rdr["cShortAddress"].ToString(),
                        Phone = rdr["cPhone"].ToString()
                    });
                }
            }
        }
    }
}

// 自定义实体类,用来存每条打印数据
public class PrintItem
{
    public string Code { get; set; }
    public string Name { get; set; }
    public string ShortAddress { get; set; }
    public string Phone { get; set; }
}

如果不想写实体类,用字典也可以,把上面的PrintItem换成Dictionary<string, string>就行,加载数据时往字典里存对应字段。

第二步:修改打印事件逻辑,精准控制分页

在打印事件里,咱们从_currentPrintIndex开始打印,每打一条就更新这个索引,满15条就标记还有下一页,直到所有数据打完。

示例打印事件代码:

private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
{
    int yPos = 182;
    int itemsPrinted = 0;

    // 从当前索引开始,打印满一页或者数据打完为止
    while (_currentPrintIndex < _printItems.Count && itemsPrinted < _itemsPerPage)
    {
        var currentItem = _printItems[_currentPrintIndex];
        
        // 绘制内容,和你原来的逻辑一致
        e.Graphics.DrawString(currentItem.Code, new Font("Arial", 11, FontStyle.Regular), Brushes.Black, new Point(60, yPos));
        e.Graphics.DrawString(currentItem.Name, new Font("Arial", 11, FontStyle.Regular), Brushes.Black, new Point(120, yPos));
        e.Graphics.DrawString(currentItem.ShortAddress, new Font("Arial", 11, FontStyle.Regular), Brushes.Black, new Point(310, yPos));
        e.Graphics.DrawString(currentItem.Phone, new Font("Arial", 11, FontStyle.Regular), Brushes.Black, new Point(580, yPos));

        yPos += 22;
        itemsPrinted++;
        _currentPrintIndex++;
    }

    // 判断是否还有未打印的数据,标记是否需要下一页
    e.HasMorePages = _currentPrintIndex < _printItems.Count;

    // 打印完所有数据后重置索引,方便下次打印
    if (!e.HasMorePages)
    {
        _currentPrintIndex = 0;
    }
}

为啥这样能解决问题?

  1. 数据缓存到内存后,不用每次分页都重新读数据库,避免了DataReader从头开始的问题;
  2. _currentPrintIndex记录了当前打印到哪一条,下一页直接从这个位置继续,不会重复打印前15条;
  3. 逻辑更清晰,也方便后续调整每页打印条数或者修改打印格式。

你可以试试这个方案,应该能解决你的分页重复问题!

备注:内容来源于stack exchange,提问作者Minhaz Tuhin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.16 07:35:32