繁体   English   中英

使用 C# 和 WinForms 应用程序的 PrintDocument 进行嵌套循环打印的棘手问题

[英]Tricky issue with nested loop printing using C# and PrintDocument for WinForms application

我正在我的 C# WinForms 应用程序中处理 function,它允许我将仓库拣货单打印到 PrintDocument,如下所示:

样品拣货单

我正在使用以下 c# 代码来生成它:

        private void pdPick_PrintPage(object sender, PrintPageEventArgs ev) {

            pdPick.DefaultPageSettings.Landscape = true;
            pdPick.DefaultPageSettings.Margins = new Margins ( 50, 50, 50, 50 );
            pdPick.PrinterSettings.DefaultPageSettings.Margins = new Margins ( 50, 50, 50, 50 );

            float yPos;
            count = 0;
            int leftMargin = (int)ev.MarginBounds.Left;
            int rightMargin = (int)ev.MarginBounds.Right;   
            int topMargin = (int)ev.MarginBounds.Top;
            int bottomMargin = (int)ev.MarginBounds.Bottom;
            float linesPerPage;
            bool moreRecs = true;
            int lPos;

            // If this is the first page, print a report header
            if (pageCounter == 1) {
                /* PRINT A REPORT HEADER HERE */
            }
            else {      // if this is a subsequent page, print an abbreviated header
                /* PRINT A PAGE HEADER HERE */
            }
            linesPerPage = ( ev.MarginBounds.Height - yPos ) / ( printFont.GetHeight ( ev.Graphics ) + 3 );

            // Cycle through items
            while ( curCount < boxCount && count < linesPerPage ) {
                // PRINT ITEM DETAIL INFO FIRST...

                // Now we cycle through the pick bins for the item...

                foreach (PickItem record in pickItems) {
                                    /*
                     * 
                     * The issue is that I need to check inside this loop to see if I hit the bottom of the page, 
                     * and if so, I need to start a new page and continue printing whatever remains inside this loop.
                     * 
                     * 
                     */
                }
                
                yPos += 10;
                count++;
                curCount++;
                moreRecs = count < boxItems.Count;
                if ( moreRecs ) {
                    pageCounter++;
                    ev.HasMorePages = true;
                }
                else {
            
                    pageCounter = 1;
                    curCount = 0;
                    yPos += headerFont.Height + 10;
                    ev.HasMorePages = false;
                    return;
                }
            } 
        }

编辑我删除了打印细节以澄清问题并解决有关重构的评论。

问题是这样的:从代码中可以看出,打印序列有两个循环。 第一个循环获取拣选订单中的产品列表,我从中打印标题、UPC 代码和要为该项目拣选的总单位数。 该循环内是另一个循环,我在其中获取位置列表以从中选择项目,因此可能有多个位置需要从中检索产品以完成该订单项。 现在,只要我 go 不超出一页,一切都很好。 挑战在于此。 显然,如果我有更多适合一页的产品,我需要分页。 问题是,我也需要检查我在第二个循环内的页面中的位置,如果是这样,我需要开始一个新页面并从我离开的地方开始。 例如,对于列表中的第三个产品,如所附屏幕截图所示,如果我打印第一个 bin 位置然后用完页面空间,我需要弹出页面,打印新页面 header,然后继续打印 rest该产品的库位置,然后继续处理订单中的任何剩余产品。

从我能找到的一切来看,我不能简单地做一个ev.HasMorePages=true; 在内循环中,因为这会导致整个打印序列重新开始,而这不是我想要的——它只会导致无限循环。 我无法找到任何关于使用嵌套循环打印到 PrintDocument 的示例或 SO 帖子。

谁能帮助我了解如何解决这个问题?

如果您让每个组的PickItem对象排队等待打印,这将不是一个棘手的问题。 在这种情况下,您需要做的就是:

  1. 打印当前组并将其项目排入Queue<PickItem>类型的 class 字段中。
  2. 循环队列以打印每个项目并将其从集合中出列,同时Y position 保留在MarginBounds内。
  3. 在绘制组和项目时,如果Y position 加上固定/可变行高(您对组和项目的行/行计算)超过e.MarginBounds.Bottom值,则请求新页面。

例子

public partial class SomeForm : Form
{
    private readonly Queue<PickItem> pickItemsQueue;
    private int pageNumber;
    private int curGroup;

    public SomeForm()
    {
        InitializeComponent();
    
        pickItemsQueue = new Queue<PickItem>();
        pdPick.DefaultPageSettings.Landscape = true;
        pdPick.DefaultPageSettings.Margins = new Margins(50, 50, 50, 50);
        pdPick.PrinterSettings.DefaultPageSettings.Margins = new Margins(50, 50, 50, 50);
    }

    private void PrintCaller()
    {
        pageNumber = 0;
        curGroup = 0;
        pickItemsQueue.Clear();
        using (var d = new PrintPreviewDialog())
        {
            d.Document = pdPick;
            d.ShowDialog(this);
        }
    }

    private void pdPick_PrintPage(object sender, PrintPageEventArgs e)
    {
        var lineHeight = (int)Font.GetHeight(e.Graphics) + 10;
        int ypos = e.MarginBounds.Y;

        pageNumber++;

        // If this is the first page, print a report header
        if (pageNumber == 1) {
            /* PRINT A REPORT HEADER HERE */
        }
        else {      
            // if this is a subsequent page, print an abbreviated header
        }

        while (curGroup < groups.Count)
        {
            if (ypos + lineHeight > e.MarginBounds.Bottom)
            {
                e.HasMorePages = true;
                return;
            }                

            if (!pickItemsQueue.Any())
            {
                // PRINT ITEM DETAIL INFO FIRST...
                // Adjust the ypos as you like...
                ypos += lineHeight;

                // Create a new queue or add the pickItems to the current instance...
                pickItemsQueue = new Queue<PickItem>(pickItems);
            }

            while (pickItemsQueue.Count > 0)
            {
                if (ypos + lineHeight > e.MarginBounds.Bottom)
                {
                    e.HasMorePages = true;
                    return;
                }

                var item = pickItemsQueue.Dequeue();

                // Print it and update the ypos...

                ypos += lineHeight;
            }

            curGroup++;
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM