我正在尝试使用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,所有这些都是可怕的!它们要么完全不清楚,要么甚至具有误导性!
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值为Display1/100英寸。如果您愿意,我建议以代码形式编写以对其进行记录。该单元将在整个布局过程中使用,因此它应该在代码中可见!我个人更喜欢毫米。还有其他几个单位..选择您的单位,但要记录下来!
GraphicsUnit
Display
您还应该研究的另一件事是String.Format()and string.PadLeft()。它们比方法中的循环好得多tostring()!
String.Format()
string.PadLeft()
tostring()
现在,让我们看一下您的特定问题:
一旦我们使用了足以使人真正理解而无需学习它们的名称的变量,在工作结束时页面为空的变量就会消失。
另一个问题是设置DB读取的方式:您需要在开始打印而不是PrintPage循环的地方设置读取器。注意:实际上,这是 两个 循环:一个是可见的while (...reader.Read() ),另一个是 隐式的 :外部PrintPage事件是整个循环本身。
PrintPage
while (...reader.Read() )
首先让我们看一下range()代码。我已经将它变成一个返回最大记录数的函数。第一步,我获取了计数。然后,我DataReader为实际阅读设置了,这将在PrintPage事件中发生:我枚举了字段,因此我可以控制它们的顺序,并且不要放入不需要的东西。
range()
DataReader
请注意,我正在使用,MySql但是类几乎相同,只是带有MySQl-prefix。我没有在此处包含连接代码。当然,我是从我自己的数据库中读取的。
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呼叫中创建的!
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); } }