我正在尝试使用printdocument从数据库中打印数据,但我将其打印到指定范围内的数据打印位置,但是仍然有2处出错
仍然无法按预期工作的是
在打印时,如果一页纸几乎被用完,它将添加一个空白页,并且只打印页眉
如果页面已满,则下一页将再次从范围的第一项开始(通过使用多个列表进行固定,因为我无法弄清楚如何创建带有子列表的列表)
这是我必须调用printdocument的代码
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); }
}
这是printdocument的代码
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 + " "; }
}
最佳答案
您写道您使用了网络资源,我想它表明了这一点。我们都这样做,但是对它们的质量相当怀疑确实很重要。当然,将两种来源相结合很可能根本行不通。
我将首先讨论代码的几个问题,然后为您提供一个示例,说明如何在多个页面上从数据库打印项目。
请帮自己一个忙,并谨慎选择变量的名称!是的,相信我,这会花更长的时间,但是会付出代价。 (并且,如果您无法提出令人信服的任何内容,请退后!这通常表明您对问题的理解不够充分。)
让我们看一些:有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()
方法中的循环好得多!现在让我们看看您的特定问题:
一旦我们使用了足以使人真正理解而无需学习它们的名称的变量,在工作结束时页面为空的变量就会消失。
另一个问题是设置数据库读取的方式:您需要在开始打印的位置而不是在
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);
}
}