c#中怎样实现多页打印及预览

用C#的printdocument画了一个表格,表格有31排,里面需要填入数据,数据的长短不定,有的没有超过31排,有的超过31排。
没有超过31排的,显示没有问题。
超过31排,也就是数据超过一页的,就不能正常显示了
也看到有人说用e.HasMorePages = true来解决,但是自己理解的不是很透彻,如果内容超过了31排,也就是超过了一页,用了e.HasMorePages = true后,显示的内容不仅填入到第一页的表格外面,而且也没有第二页的内容显示出来,代码如下:

  if (totalpages == 1)
            {
                for (int i = 0; i < r; i++)
                {
                    g.DrawString(arr[i], myfont1, mybrush, x + 615, y + 215 + i * 18);
                }
            }
            if (totalpages == 2)
            {
                for (int i = 0; i < 31; i++)
                {
                    g.DrawString(arr[i], myfont1, mybrush, x + 615, y + 215 + i * 18);
                }
                e.HasMorePages = true;
                for (int i = 31; i < r; i++)
                {
                    g.DrawString(arr[i], myfont1, mybrush, x + 615, y + 215 + i * 18);
                }
                e.HasMorePages = false;
            }

你需要在打印文档的PrintPage事件处理函数中进行分页处理。具体来说,需要使用PrintPageEventArgs.HasMorePages属性来指示是否还有更多的页面要打印。

每当需要打印新的一页时,应该将HasMorePages设置为true,并绘制该页的内容。接下来,在下一次调用PrintPage事件处理函数时,可以继续绘制下一页的内容。当不需要再打印更多页面时,将HasMorePages设置为false。

例如,可以这样实现分页处理:

private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
    // 定义变量表示当前页的编号、每页的行数和当前已经打印的行数
    int page = 1;
    int rowsPerPage = 31;
    int rowsPrinted = 0;

    // 创建用于绘制文本的字体
    Font font = new Font("Arial", 10);

    // 计算总页数
    int totalPages = (int)Math.Ceiling((double)arr.Length / rowsPerPage);

    // 绘制当前页的内容
    while (rowsPrinted < rowsPerPage && page <= totalPages)
    {
        for (int i = rowsPrinted; i < arr.Length; i++)
        {
            e.Graphics.DrawString(arr[i], font, Brushes.Black, new PointF(615, 215 + i * 18));
            rowsPrinted++;
        }
        page++;

        // 如果还有更多的页面要打印,设置HasMorePages为true
        if (page <= totalPages)
        {
            e.HasMorePages = true;
        }
        else
        {
            e.HasMorePages = false;
        }
    }
}

以下是在你的代码的基础上进行修改的代码:

private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
    // 定义变量表示当前页的编号、每页的行数和当前已经打印的行数
    int page = 1;
    int rowsPerPage = 31;
    int rowsPrinted = 0;

    // 创建用于绘制文本的字体
    Font font = new Font("Arial", 10);

    // 计算总页数
    int totalPages = (int)Math.Ceiling((double)arr.Length / rowsPerPage);

    // 循环打印每一页
    while (page <= totalPages)
    {
        // 绘制当前页的内容
        for (int i = rowsPrinted; i < arr.Length; i++)
        {
            e.Graphics.DrawString(arr[i], font, Brushes.Black, new PointF(615, 215 + i * 18));
            rowsPrinted++;

            // 如果已经绘制的行数达到了每页的行数,跳出循环
            if (rowsPrinted >= rowsPerPage)
            {
                break;
            }
        }
        page++;

        // 如果还有更多的页面要打印,设置HasMorePages为true
        if (page <= totalPages)
        {
            e.HasMorePages = true;
        }
        else
        {
            e.HasMorePages = false;
        }
    }
}

在这个代码中,我们使用了一个循环来打印所有的页面,并在每一页中绘制行的内容。每当绘制完每一页的内容后,我们将页码加1,并检查是否还有更多的页面要打印。如果有,我们将HasMorePages设置为true,否则设置为false。

当设置了e.HasMorePages = true,会触发PrintPage事件,然后PrintDocument会继续调用PrintPage事件处理函数。需要在这个事件处理函数中处理打印的下一页内容。

代码中,当totalpages==2时,在绘制了前31行后,立即设置e.HasMorePages = true,然后再继续绘制后面的行,这样是错误的。应该将e.HasMorePages设置为false,然后在下一次的PrintPage事件中,绘制剩余的行。

可以将代码修改为如下的形式:

int currentRow = 0;

private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
    Graphics g = e.Graphics;

    if (totalpages == 1)
    {
        for (int i = currentRow; i < r; i++)
        {
            g.DrawString(arr[i], myfont1, mybrush, x + 615, y + 215 + i * 18);
            currentRow++;
        }
    }
    if (totalpages == 2)
    {
        for (int i = currentRow; i < 31; i++)
        {
            g.DrawString(arr[i], myfont1, mybrush, x + 615, y + 215 + i * 18);
            currentRow++;
        }
        e.HasMorePages = true;
    }
}

private void printDocument1_EndPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
    currentRow = 0;
}

这样在PrintPage事件中,可以从currentRow开始绘制剩余的行,而不是从0开始。然后当处理完所有的行后,设置e.HasMorePages为false,告诉PrintDocument打印已经结束。

在这里,可以使用PrintDocument的EndPrint事件来将currentRow的值设置回0,以便下一次打印
仅供参考,望采纳,谢谢。

在 C# 中,你可以使用 .NET Framework 中的 PrintDocument 类来实现多页打印和预览。

首先,你需要创建一个 PrintDocument 对象,并设置它的 PrintPage 事件,这个事件会在每一页打印时触发。在这个事件的处理函数中,你可以使用 e.Graphics 对象的绘图方法来绘制你的页面内容。你还需要设置 PrintDocument 对象的 DefaultPageSettings 属性,以指定打印机的纸张大小和方向等信息。

下面是一个简单的例子,展示了如何使用 PrintDocument 类实现一个简单的打印预览功能:

using System.Drawing.Printing;

// ...

PrintDocument printDocument = new PrintDocument();
printDocument.DefaultPageSettings.Landscape = true;
printDocument.DefaultPageSettings.PaperSize = new PaperSize("A4", 827, 1170);

printDocument.PrintPage += PrintPage;

PrintPreviewDialog printPreviewDialog = new PrintPreviewDialog();
printPreviewDialog.Document = printDocument;
printPreviewDialog.ShowDialog();

// ...

private void PrintPage(object sender, PrintPageEventArgs e)
{
    e.Graphics.DrawString("Hello, World!", new Font("Arial", 12), Brushes.Black, new PointF(0, 0));
}

在这个例子中,我们创建了一个 PrintDocument 对象,并设置了它的打印方向和纸张大小。然后我们使用 PrintPage 事件来绘制页面内容,在这个事件的处理函数中,我们可以使用 e.Graphics 对象的绘图方法来绘制文本。最后,我们使用 PrintPreviewDialog 类来显示打印预览
如果你想要实现多页打印,你需要在 PrintPage 事件的处理函数中设置 e.HasMorePages 属性,以指示是否还有其他页需要打印。

例如,假设你想要打印一个包含多个字符串的列表,你可以这样实现:

private List<string> stringsToPrint = new List<string> { "Hello,", "World!", "This", "is", "a", "multi-page", "print", "example." };
private int currentStringIndex = 0;

private void PrintPage(object sender, PrintPageEventArgs e)
{
    float yPos = 0f;
    float leftMargin = e.MarginBounds.Left;
    float topMargin = e.MarginBounds.Top;
    string line = null;
    Font printFont = new Font("Arial", 12);
    SolidBrush brush = new SolidBrush(Color.Black);

    // 字符循环,一个个打印
    while (currentStringIndex < stringsToPrint.Count)
    {
        line = stringsToPrint[currentStringIndex];
        yPos = topMargin + (currentStringIndex * printFont.GetHeight(e.Graphics));
        e.Graphics.DrawString(line, printFont, brush, leftMargin, yPos, new StringFormat());
        currentStringIndex++;
    }

    // 检查是否有多页需要打印
    if (currentStringIndex < stringsToPrint.Count)
    {
        e.HasMorePages = true;
    }
    else
    {
        e.HasMorePages = false;
    }
}

在这个例子中,我们使用一个循环来逐个打印字符串列表中的字符串,并在每一次循环之后检查是否还有更多的字符串需要打印。如果还有,我们就将 e.HasMorePages 设置为 true,以便在下一次调用 PrintPage 事件时继续打印剩余的内容。
希望能帮助到你!

推荐使用html to pdf 的方式,这样设置更加灵活,具体参考下面的文章