printdocument 添加空白页
Posted
技术标签:
【中文标题】printdocument 添加空白页【英文标题】:printdocument adds blank page 【发布时间】:2015-04-21 21:27:38 【问题描述】:我正在尝试使用 printdocument 打印数据库中的数据,我将其打印到指定范围内的数据打印位置,但仍有 2 件事出错
仍然无法按预期工作的事情是
在打印时,如果页面几乎已用完,它会添加一个仅打印页眉的空白页 如果页面已满,则下一页再次从范围的第一项开始(通过使用多个列表进行修复,因为我无法弄清楚如何使用子列表制作列表)这是我必须调用打印文档的代码
private void button3_Click(object sender, EventArgs e)//print
range();
try
if (artikel == true)
itemperpage = totalnumber = 0;
printPreviewDialog1.Document = printDocument1;
print = true;
printDocument1.Print();
// this.Close();
catch (Exception q) MessageBox.Show("" + q);
这是打印文档的代码
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
if (artikel == true)
Font messageFont = new Font("Arial", 14, System.Drawing.GraphicsUnit.Point);
float currentY = 10;// declare one variable for height measurement
e.Graphics.DrawString(" I N K O O P A R T I K E L E N ", DefaultFont, Brushes.Black, 10, currentY);//this will print one heading/title in every page of the document
currentY += 15;
SqlCommand artprint = new SqlCommand("select * from ART WHERE ART BETWEEN @range AND @range2 ORDER BY ART ASC", Connectie.connMEVO_ART);
if (comboBox1.SelectedIndex <= comboBox2.SelectedIndex)
artprint.Parameters.Add("@range", SqlDbType.VarChar).Value = comboBox1.SelectedItem;
artprint.Parameters.Add("@range2", SqlDbType.VarChar).Value = comboBox2.SelectedItem;
else if (comboBox2.SelectedIndex <= comboBox1.SelectedIndex)
artprint.Parameters.Add("@range", SqlDbType.VarChar).Value = comboBox2.SelectedItem;
artprint.Parameters.Add("@range2", SqlDbType.VarChar).Value = comboBox1.SelectedItem;
drART = artprint.ExecuteReader();
try
while (totalnumber <= amount - 1 && drART.Read())
// check the number of items
tostring();//SQL data to string
row = row + Environment.NewLine + "ART LEV LTD MVRD SGR INK CRNI " + " VALUTA KOR ";
row = row + Environment.NewLine + aa + " " + a + " " + b + " " + c + " " + d + " " + m + " " + f + " " + g + " " + h;
row = row + Environment.NewLine + "EH2 EH1 EF OMS ";
row = row + Environment.NewLine + j + " " + k + " " + l + " " + i;
row = row + Environment.NewLine;
e.Graphics.DrawString(row, DefaultFont, Brushes.Black, 50, currentY);//print each item
Debug.WriteLine("" + row);
row = "";
currentY += 80; // set a gap between every item
totalnumber += 1; //increment count by 1
if (itemperpage <= 12)
itemperpage += 1; // increment itemperpage by 1
e.HasMorePages = false; // set the HasMorePages property to false , so that no other page will not be added
else // if the number of item(per page) is more than 12 then add one page
itemperpage = 0; //initiate itemperpage to 0 .
e.HasMorePages = true; //e.HasMorePages raised the PrintPage event once per page .
return;//It will call PrintPage event again
catch (Exception ef)
MessageBox.Show("" + ef);
artprint.Dispose();
private void tostring()
aa = drART["ART"].ToString();
for (int ss = aa.Length; ss < 8; ss++) aa = aa + " ";
a = drART["LEV"].ToString();
for (int ss = a.Length; ss < 10; ss++) a = a + " ";
b = drART["LTD"].ToString();
for (int ss = b.Length; ss < 10; ss++) b = b + " ";
c = drART["MVRD"].ToString();
for (int ss = c.Length; ss < 10; ss++) c = c + " ";
d = drART["SGR"].ToString();
for (int ss = d.Length; ss < 10; ss++) d = d + " ";
m = drART["INK"].ToString();
for (int ss = m.Length; ss < 10; ss++) m = m + " ";
f = drART["CRNI"].ToString();
for (int ss = f.Length; ss < 10; ss++) f = f + " ";
g = drART["VALUTA"].ToString();
for (int ss = g.Length; ss < 3; ss++) g = g + " ";
h = drART["KOR"].ToString();
for (int ss = h.Length; ss < 10; ss++) h = h + " ";
i = drART["OMS"].ToString();
j = drART["EH2"].ToString();
for (int ss = j.Length; ss < 3; ss++) j = j + " ";
k = drART["EH1"].ToString();
for (int ss = k.Length; ss < 3; ss++) k = k + " ";
l = drART["EF"].ToString();
for (int ss = l.Length; ss < 10; ss++) l = l + " ";
【问题讨论】:
您总是在每次进入 PagePrint 时重新从数据库读取。 - 您的数字有冲突:if (itemperpage 仅供参考,PrintDocument 不是 C# 的一部分。它是 .NET Framework 的一部分。 @JohnSaunders 我猜你知道的越多。但我想它对标签等很有用,所以谢谢 @TaW 我对某些部分使用了在线教程,这就是教程中的内容,所以我不太知道如何更改它,所以它确实将所有项目构成了范围,并且评论是有点老,所以生病看看其他人,看看是否有更多冲突或没有意义 【参考方案1】:您写道,您使用了来自网络的资源,我猜它显示了。我们都这样做,但对它们的质量持怀疑态度非常重要。当然,结合两个来源很可能根本行不通..
我将首先讨论您的代码的几个问题,然后向您展示如何在多个页面上打印数据库中的项目的示例。
请帮自己一个忙,小心选择变量的名称!是的,这需要更长的时间,但它会付出代价的,相信我。 (如果你想不出任何令人信服的东西,就退后一步!这通常表明你对问题的理解不够好......)
我们看一些:有currentY
,还不错。还有itemperpage
、totalnumber
和amount
,都太可怕了!它们要么完全不清楚,要么甚至具有误导性!
让我们设置几个更好的名字:
// layout variables
int itemsPerPage = 40; // how many items fit on one page
int itemHeight = 25; // height of one item in the chosen unit
// print job variables
int totalNumber = -1; // total number of records/items coming from the dbms
int itemsToPrint = 75; // total number of items we want to print
// print progress variables
int itemsPrinted = 0; // number of items printed so far
int pagesPrinted = 0; // number of pages printed
另一个问题是您选择的单位,或者准确地说是缺乏选择。默认GraphicsUnit
是Display
,用于打印的大小为 1/100 英寸。如果你喜欢,我建议用代码编写它来记录它。这个单元将在整个布局过程中使用,因此它应该在代码中可见!我个人更喜欢毫米。还有其他几个单位..选择你的,但记录下来!
您应该研究的另一件事是String.Format()
和string.PadLeft()
。它们比 tostring()
方法中的循环要好得多!
现在让我们看看你的具体问题:
一旦我们使用足够多的变量名称,无需学习就可以真正理解。
另一个问题是您设置 DB 读取的方式:您需要在开始打印的位置设置阅读器,而不是在 PrintPage
循环中。注意:这实际上是两个循环:一个可见为while (...reader.Read() )
,另一个外部循环是隐式:整个PrintPage
事件本身就是循环体.
首先让我们看一下range()
代码。我已经把它变成了一个返回最大记录数的函数。我在第一步中获取计数。然后我设置DataReader
进行真正的阅读,这将发生在PrintPage
事件中:我列举了字段,所以我可以控制它们的顺序并且不拉入我不需要的东西。
请注意,我使用的是mysql
,但类几乎相同,只是带有MySQl
-前缀。我在这里不包括连接代码。当然,我是从我自己的数据库中读取的..
MySqlConnection DBC = new MySqlConnection("");
MySqlCommand CMD = null;
MySqlDataReader DR = null;
int range ()
CMD = new MySqlCommand("select count(0) from test.artists ", DBC);
var count = CMD.ExecuteScalar();
int counter = Convert.ToInt32(count);
CMD = new MySqlCommand("select artist_ID, artist, genres from test.artists ", DBC);
DR = CMD.ExecuteReader();
return (int)counter;
现在让我们看看打印命令,使用上面的变量:
private void cb_print_Click(object sender, EventArgs e)
totalNumber = range();
try
if (DBC.State == ConnectionState.Open)
pagesPrinted = 0;
printPreviewDlg.Document = printDocument1;
printPreviewDlg.ShowDialog();
catch (Exception q) MessageBox.Show("" + q);
DR.Dispose();
注意Reader
是在range
调用中创建的!
最后是PrintPage
事件:
private void printDocument1_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
// my page unit
e.Graphics.PageUnit = GraphicsUnit.Millimeter;
// starting a new page
int itemsOnPage = 0;
pagesPrinted++;
float currentY = 12;
e.Graphics.DrawString(String.Format(
"HEADER - printing 0 items of 1 - Page 2",
itemsToPrint, totalNumber, pagesPrinted),
Font, Brushes.Black, 1, currentY);
currentY += 30; // header height
try
// page is not full and we want to print more items
while (itemsOnPage < itemsPerPage && itemsPrinted < itemsToPrint - 1
&& DR.Read())
string row = String.Format("0,5:000 Artist: 1,20 (2) ",
DR[0], DR[1], DR[2]);
e.Graphics.DrawString(row, DefaultFont, Brushes.Black, 50, currentY);
// Console.WriteLine("" + row);
currentY += itemHeight;
itemsPrinted++;
itemsOnPage++;
// we want to print more items but now the page is full
if ( itemsPrinted < itemsToPrint && itemsOnPage >= itemsPerPage)
itemsOnPage = 0;
e.HasMorePages = true;
return;
else
// this will only be used after all data are printed
e.HasMorePages = false;
catch (Exception ef)
MessageBox.Show("" + ef);
【讨论】:
查看您的代码和您提供的提示之后。我试过你的代码,但我无法让它为我工作。但我确实觉得这对我很有帮助,因为最后我确实更改了一些变量名,并且我了解了一些以后可以派上用场的方法。在添加一些示例代码时付出了一些额外的努力后,我让它按我想要的方式工作,谢谢 TaW。【参考方案2】:也有这个问题。在我的情况下,原因是事件处理程序void PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
中有一行e.HasMorePages = true;
(e 是 PrintPageEventArgs)。每次您声明e.HasMorePages = true;
时,都会为打印准备一个新页面。所以,我的正确代码是:
private void PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
if (currentPagePrinting <= maxPagePrinting)
//...
// do some drawing on e.Graphics as you like
//...
currentPagePrinting++;
e.HasMorePages = (currentPagePrinting <= maxPagePrinting);
else
e.HasMorePages = false;
// also set this value to 1 in PrintDoc_BeginPrint event handler (declare it)
currentPagePrinting = 1;
【讨论】:
以上是关于printdocument 添加空白页的主要内容,如果未能解决你的问题,请参考以下文章