I pasted your code into a new Windows-Forms-Project, added a DataGridView and a PrintDocument to the Form and it worked for me. The only issue I had was that initially my DataGridView had less than six columns, so I got an exception where the row-cells are being accessed. So I would suggest you double-check that. If your DataGridView does have 6 or more columns, then the cause for trouble must be somewhere outside your posted code.
Apart from that, you should use graphics objects (like Font and SolidBrush) in a
using
-Block (because they're
IDisposable[
^]) and re-use that one instance wherever needed. I did that for you here - it should be ready as a drop-in replacement for your code:
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
try
{
Graphics graphic = e.Graphics;
using (Font courier12 = new Font("Courier New", 12))
using (SolidBrush blackBrush = new SolidBrush(Color.Black))
{
int startX = 12;
int startY = 12;
int offset = 40;
graphic.DrawString("\t Shop Name \n \t Address \n \t Phone Number\n", courier12, blackBrush, startX, startY);
string underline = "\t \n \n\n --------------------------------------\n";
graphic.DrawString(underline, courier12, blackBrush, startX, startY + offset);
int noOfRows = dataGridView1.Rows.Count;
string a = dataGridView1.Rows[0].Cells[0].Value.ToString();
string cusname = "\n\n\n\nCustomer Name:\t " + a + "\n";
graphic.DrawString(cusname, courier12, blackBrush, startX, startY + offset);
string headings = "\t\n \n\n\n\n\n\n\n Item Name\t Price \t Quantity \t Total \n ";
graphic.DrawString(headings, courier12, blackBrush, startX, startY + offset);
for (int i = 0; i < noOfRows - 1; i++)
{
DataGridViewRow row = dataGridView1.Rows[i];
string b = row.Cells[2].Value.ToString();
string c = "\t" + row.Cells[3].Value.ToString();
string d = "\t" + row.Cells[4].Value.ToString();
string f = "\t" + row.Cells[5].Value.ToString();
string g = "\n\n\n\n\n\n\n\n \n\n" + b + "\t" + c + "\t" + d + "\t" + f + "\t" + "\n";
graphic.DrawString(g, courier12, blackBrush, startX, startY + offset);
offset = offset + 20;
}
graphic.DrawString("\t\n\n\n\t\n\n\n\t\n\n\n\nSoftware by Softcare\n", courier12, blackBrush, startX, startY + offset);
}
}
catch (Exception ex)
{
MessageBox.Show("Error is : " + ex);
}
}
Edit after comments:
It's not completely obvious to me how this is causing the issue, but:
Disposable objects (e.g. DbConnection, DbCommand, DbDataReader, Form) should always be properly disposed when they go out of scope (when you stop using them). Not doing this can have all sorts of strange effects and somehow this fired back on you here.
This Google-query shows you several articles here on CodeProject that explain what IDisposable is about and how it's properly dealt with. Have a look at one or two to get the idea:
https://www.google.com/search?q=idisposable+codeproject&ie=utf-8&oe=utf-8[
^]
There would be more ways to deal with this but the simplest one would be to not declare your connection-object as a class member but to create (and dispose) it in the method where you use it, like so:
private void login_button_Click(object sender, EventArgs e)
{
using (var connection = new OleDbConnection())
using (var command = new OleDbCommand())
{
command.Connection = connection;
command.CommandText = "Select * from Login where Username='" + username_text.Text+ "' and Pass='"+ pass_text.Text+"' ";
using (var reader = command.ExecuteReader())
{
int count = 0;
while (reader.Read())
{
count++;
}
}
}
if (count == 1)
{
MessageBox.Show("Username and Password are Correct");
this.Hide();
Main_Form mf = new Main_Form();
mf.ShowDialog();
this.Close();
}
else if (count > 1)
{
MessageBox.Show("Dublicate Username and Password ");
}
else
{
MessageBox.Show("Username and Password are not Correct");
}
}
Also I would strongly suggest you to use SQL-Parameters instead of concatenating your query-criteria into the query-string. Here's a good example:
http://www.dotnetperls.com/sqlparameter[
^]