Imports System.Data.OleDb
Public Class Form1
Dim con As OleDbConnection
Dim cmd As OleDbCommand
Dim da As OleDbDataAdapter
Dim dt As New DataTable
Private _titleFont As Font
Private _detailFont As Font
Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint
_titleFont = New Font(FontFamily.GenericSerif, 16, FontStyle.Bold, GraphicsUnit.Point)
_detailFont = New Font(FontFamily.GenericSerif, 12, FontStyle.Bold, GraphicsUnit.Point)
End Sub
Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim xPos As Single = 120
Dim yPos As Single = 120
Dim i As Integer = 0
Dim y As Integer = 0
Dim myArray() As Integer = {0, 0, 0, 0}
For i = 0 To dt.Rows.Count - 1
For y = 0 To dt.Columns.Count - 1
If myArray(y) < e.Graphics.MeasureString(dt.Rows(i).Item(y).ToString, _detailFont).Width + 150 Then
myArray(y) = e.Graphics.MeasureString(dt.Rows(i).Item(y).ToString, _detailFont).Width + 150
End If
Next
Next
Dim counter As Integer = 0
For Each c As DataColumn In dt.Columns
e.Graphics.DrawString(c.ColumnName, _titleFont, Brushes.Black, xPos, yPos)
xPos += myArray(counter)
counter += 1
Next
xPos = 120
yPos += 50
For i = 0 To dt.Rows.Count - 1
For y = 0 To dt.Columns.Count - 1
e.Graphics.DrawString(dt.Rows(i).Item(y).ToString, _detailFont, Brushes.Black, xPos, yPos)
xPos += myArray(y)
Next
xPos = 120
yPos += 50
Next
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
con = New OleDbConnection("Provider=Microsoft.Jet.Oledb.4.0;Data Source=db1.mdb")
con.Open()
cmd = New OleDbCommand("Select * from Table1", con)
da = New OleDbDataAdapter(cmd)
da.Fill(dt)
PrintPreviewControl1.Document = PrintDocument1
End Sub
Private Sub PrintToolStripButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintToolStripButton.Click
If PrintDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
PrintDocument1.Print()
End If
End Sub
Private Sub ToolStripButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton1.Click
PageSetupDialog1.PageSettings = PrintDocument1.DefaultPageSettings
If PageSetupDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
PrintDocument1.DefaultPageSettings = PageSetupDialog1.PageSettings
Else
Exit Sub
End If
End Sub
End Class
i did this code and i am having problem with the tootstripbutton1 click....
i clicked the button,then a pagesetupdialog appears,then i changed from portrait to landscape and clicked ok but the preview of the document does not changes in the PringPreiewcontrol from landscape to Portrait........
Please stop bumping your thread. If have nothing new to add then you shouldn't be posting.
Just so you know, I've never printed anything from a .NET app. All I know about printing is pretty much what I've read in the documentation.
So, you call Print on your PrintDocument and the preview is displayed in your PrintPreviewControl. If you change some printing parameters, the preview won't spontaneously update. You have to call Print on the PrintDocument again so that a new preview is drawn. When you do your printing, i.e. in the PrintPage event handler, if you want the printing to look different depending on the page orientation then obviously you would have to determine what the page orientation is in the PrintPage event handler. You will then have to write the code in the PrintPage event handler to make use of that information.
So, go to the MSDN documentation and read about the PrintPage event. Take note of what type the 'e' parameter is and follow the link to read the documentation for that. Once you know what members it has you can work out from that how to get the information you need, following more links and reading more documentation if necessary. I don't know the exact solution you need, i.e. the exact code to get your printed output the way you want, but if I had to do this, that's exactly what I'd do. I would make use of the information I found and employ a certain amount of trial and error until I found the final solution.
You might also check out Merrion's intro to .NET printing in the VB.NET CodeBank forum. He's the printing expert around here. It won't provide you with a final solution but I'm sure it contains useful information.
i think i should wirte some code in the querypagesettings event tht is raised by the printdocument1.print() since this event is used to set the orientation (landscape or portrait), the paper size, paper source, and so on but i cant write the exact code to do the needful.......any help?
From what I can see, the idea of the QueryPageSettings event is to allow you to change the page settings from the document default for the following page. That's not what you want. You want the same page settings for the entire document. Whether or not you change the page settings in the QueryPageSettings event handler, you still have to read those page settings in the PrintPage event handler. That's where you do the printing so that's where you have to read the page settings to determine how to do the printing.
In the PrintPage event handler, the 'e' parameter is type PrintPageEventArgs. That object has a PageBounds property to give you the bounds of the printed page, which will tell you how wide to print a line and how many lines to print. It also has a PageSettings property, from which you can get ALL the page settings you need to determine how to print.
You are handling the PrintPage event to print a page. As with all events, the 'e' parameter of the event handler contains the information for the event. Now we go straight to MSDN and the documentation for the PrintPage event. The documentation says that the event's type is PrintPageEventHandler, so we click the link and go to the documentation for that type. That documentation says that the 'e' parameter is type PrintPageEventArgs, so we click the link and read the documentation for that type. The very first line of the Remarks section of that topic says:
The MarginBounds property retrieves the rectangular area that represents the portion of the page between the margins.
Doesn't that sound useful? Isn't that basically what you want: to know where you can and should print? So, we click the link and read the documentation for that property. That topic says that the MarginBounds property is type Rectangle. If you don't know how to use a Rectangle then you click the link and read that documentation too. As you can see, using the MSDN documentation is simple and systematic.
So, you now know exactly how to get a Rectangle that describes the printable area within the PrintPage event handler. As you know from reading the documentation, the Rectangle structure has Left and Top properties, which give you a reference point from which to offset your printing. It also Width and Height properties, which give you an area outside of which you must not print. From there it's simple mathematics.
but again the problem is the same..in this case also i am using the absolute positioning jmc....
the left and top is (50,50) which is ok but the width and height portion will differ if i change the change the page settings from portrait to landscape.......
so simply i cant use the integers to draw a border or something like that in the printing page.....
i was thinking that if the page width(either landscape or portrait) is known then i would subtract 5 from all sides of the page to get the work done......
i was thinking that if the page width(either landscape or portrait) is known
The width of the page IS known:
Originally Posted by jmcilhinney
So, you now know exactly how to get a Rectangle that describes the printable area within the PrintPage event handler. As you know from reading the documentation, the Rectangle structure has Left and Top properties, which give you a reference point from which to offset your printing. It also has Width and Height properties, which give you an area outside of which you must not print. From there it's simple mathematics.
when i started this printing code then it was very interesting but day by day it is becoming very frustrating to me ....even i cant find the expert merrion online.....
in the third and fourth parameters i am setting the width and the height but how can i get the width and height of the page on which i will be printing
You seem to have disregarded posts #8 and #11. I don't see anywhere that you've used the MarginBounds and some maths. You say that the problem is that you're using absolute values. You're correct. I've told you what you need to do but you are yet to do it. Here's a simple example:
1. Create a new WinForms application project.
2. Add two Buttons to the form.
3. Change the Text of Button1 to "Portrait".
4. Change the Text of Button2 to "Landscape".
5. Add a PrintDocument and a PrintPreviewDialog to the form.
6. Assign the PrintDocument to the PrintPreviewDialog's Document property.
7. Add the following code:
Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Print in portrait.
Me.PrintDocument1.DefaultPageSettings.Landscape = False
'Display a preview.
Me.PrintPreviewDialog1.ShowDialog()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'Print in landscape.
Me.PrintDocument1.DefaultPageSettings.Landscape = True
'Display a preview.
Me.PrintPreviewDialog1.ShowDialog()
End Sub
Private Sub PrintDocument1_PrintPage(ByVal sender As Object, _
ByVal e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim text As String = "Hello World"
'Get the printable area.
Dim bounds As Rectangle = e.MarginBounds
'Get the size of the text.
Dim textSize As SizeF = e.Graphics.MeasureString(text, Me.Font, bounds.Width)
'Calculate the top left corner of the text for it to be centred.
Dim textX As Single = bounds.Left + (bounds.Width - textSize.Width) / 2
Dim textY As Single = bounds.Top + (bounds.Height - textSize.Height) / 2
'Print the text.
e.Graphics.DrawString(text, Me.Font, Brushes.Black, textX, textY)
End Sub
8. Run the project.
9. Click the Portrait button and observe the result.
10. Click the Landscape button and observe the result.
As you can see, you don't have to care about whether you're printing in Portrait or Landscape in the PrintPage event handler. All you have to do is what I said: get the printable area from the e.MarginBounds property and then apply some mathematics to decide where to print relative to that.
that works well even in this code when i used the printpreviewdailog earlier:
Code:
Imports System.Data.OleDb
Public Class Form1
Dim con As OleDbConnection
Dim cmd As OleDbCommand
Dim da As OleDbDataAdapter
Private _titleFont As Font
Private _detailFont As Font
Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint
'set the data pointers (if any) to the start position
'initialise any page number variables you might have
_titleFont = New Font(FontFamily.GenericSerif, 16, FontStyle.Bold, GraphicsUnit.Point)
_detailFont = New Font(FontFamily.GenericSerif, 12, FontStyle.Bold, GraphicsUnit.Point)
End Sub
Private Sub PrintDocument1_EndPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.EndPrint
'You can use this event handler to clear up any objects that you have created for the print job
End Sub
Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
'All of the actual printing on a page is done in the PrintPage event handler
'This event is raised for each page that is printed
'the drawing and text commands that you code in this event handler control what is printed on the page itself
e.Graphics.DrawLine(Pens.Black, 50, 50, 800, 50)
e.Graphics.DrawLine(Pens.Black, 50, 50, 50, 1050)
e.Graphics.DrawLine(Pens.Black, 50, 1050, 800, 1050)
e.Graphics.DrawLine(Pens.Black, 800, 50, 800, 1050)
e.Graphics.DrawLine(Pens.Black, 100, 110, 750, 110)
e.Graphics.DrawLine(Pens.Black, 100, 150, 750, 150)
e.Graphics.DrawLine(Pens.Black, 100, 1000, 750, 1000)
Dim xPos As Single = 120
Dim yPos As Single = 120
Dim i As Integer = 0
Dim y As Integer = 0
Dim myArray() As Integer = {0, 0, 0, 0}
For i = 0 To dt.Rows.Count - 1
For y = 0 To dt.Columns.Count - 1
If myArray(y) < e.Graphics.MeasureString(dt.Rows(i).Item(y).ToString, _detailFont).Width + 150 Then
myArray(y) = e.Graphics.MeasureString(dt.Rows(i).Item(y).ToString, _detailFont).Width + 150
End If
Next
Next
Dim counter As Integer = 0
For Each c As DataColumn In dt.Columns
e.Graphics.DrawString(c.ColumnName, _titleFont, Brushes.Black, xPos, yPos)
xPos += myArray(counter)
counter += 1
Next
xPos = 120
yPos += 50
For i = 0 To dt.Rows.Count - 1
For y = 0 To dt.Columns.Count - 1
e.Graphics.DrawString(dt.Rows(i).Item(y).ToString, _detailFont, Brushes.Black, xPos, yPos)
xPos += myArray(y)
Next
xPos = 120
yPos += 50
Next
End Sub
'if there are more pages to print, set the e.HasMorePages property to True
'and the QueryPageSettings and PrintPage events will be triggered again
'the same event handler is used, so if you want to print different pages
'you need to keep track of which page you are on and code your PrintPage event handler accordingly
Dim dt As New DataTable
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If PrintDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
PrintDocument1.Print()
End If
End Sub
Private Sub PrintDocument1_QueryPageSettings(ByVal sender As Object, ByVal e As System.Drawing.Printing.QueryPageSettingsEventArgs) Handles PrintDocument1.QueryPageSettings
'raised before each and every page that is printed
'use this event to set any page settings for the next page to be printed
'set the orientation (landscape or portrait), the paper size, paper source, and so on
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
PrintPreviewDialog1.Document = PrintDocument1
PrintPreviewDialog1.ShowDialog()
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
con = New OleDbConnection("Provider=Microsoft.Jet.Oledb.4.0;Data Source=db1.mdb")
con.Open()
cmd = New OleDbCommand("Select * from Table1", con)
da = New OleDbDataAdapter(cmd)
da.Fill(dt)
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
PageSetupDialog1.PageSettings = PrintDocument1.DefaultPageSettings
If PageSetupDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
PrintDocument1.DefaultPageSettings = PageSetupDialog1.PageSettings
Else
Exit Sub
End If
End Sub
End Class
but when i used the printpreviewcontrol then i am having the problem:
the code is shown in #1
I've never used a PrintPreviewControl myself but I don't really see what difference it would make. The PrintPreviewDialog itself contains a PrintPreviewControl and simply passes through the PrintDocument.
ok i solved the portrait/landscape problem by this code:
Code:
Private Sub ToolStripButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton1.Click
PageSetupDialog1.PageSettings = PrintDocument1.DefaultPageSettings
If PageSetupDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
PrintDocument1.DefaultPageSettings = PageSetupDialog1.PageSettings
Me.PrintPreviewControl1.InvalidatePreview()
Else
Exit Sub
End If
Now after having a close look at your code,i am also able to understand the logic of how to remove absolute positioning and implement the positioning using the marginbounds and pagebounds....very soon i am going to implement it in my code All it needs is some simple calculations......if you would not have helped me so far then i would have been dieing today thanks a lot jmc.....
one request...please have a look at the project i uploaded in my #19 or #20....there is an printDialog associated with it;now if the user wants to print more than one pages at a time then how to do this?
I had a look at merrions submission and i found that i need to set e.HasMorePages to True to raise the PrintPage event again but i cant implement it properly in my above codes......Please help
If e.HasMorePages = True Then
PrintDocument1.Print()
End If
is it ok?
All you need to do is set e.HasMorePages to True. If you do then the PrintPage event will be automatically raised again and you'll print another page. As soon as a PrintPage event handler completes with e.HasMorePages set to False, which is the default value, the current print run stops, i.e. PrintPage is not raised again.
Obviously, if you're printing multiple pages on multiple PrintPage events, you need a way to determine what page you're supposed to be printing inside the PrintPage event handler. For that you'd use either a Static or member variable to store some sort of counter. It might contain a page number, record number or whatever's appropriate for your scenario.
Static counter As Integer = 1
If counter = 1 Then
'Print the string
e.HasMorePages = True
Exit Sub
End If
If counter = 2 Then
'Print the string
e.HasMorePages = False
End If
but this will unfortunately print only two pages
I cant understand how to set the upper limit of the counter since the user will select at the runtime how many pages he want to print in the PrintDialog......
Please help
If the user enters the number of pages into the PrintDialog then that's where you get the number of pages from. EVERYTHING you need can either be obtained from the 'e' parameter or the 'sender' parameter, which is the PrintDocument itself. ALL the printer settings and page settings are in there.
Static counter As Integer = 1
If counter <= e.HasMorePages Then
counter+=1
e.HasMorePages = True
Else
e.HasMorePages = False
End If
is it ok?
How can 'counter' be less than e.HasMorePages? Look at you own code. e.HasMorePages is either True or False, so how can you compare it to a page number?
EVERYTHING you need can either be obtained from the 'e' parameter or the 'sender' parameter, which is the PrintDocument itself. ALL the printer settings and page settings are in there.
If you look into those objects you'll find the information you need. The fourth paragraph in post #4 explains how to do that. The reason I'm pushing you to find it for yourself is that, if I just give you the answer this time, you'll just come back and ask the next time too. If you look for yourself you will learn how to find information for yourself, which you can use next time, and you will most likely find other information that will be useful either now or in the future. That is EXACTLY how I learned when I was a beginner. If I can do it, you can do it.
i really feel sorry jmc that you have been helping me throughout but i cant help myself but i tried
i had a look at this: http://msdn.microsoft.com/en-us/libr...morepages.aspx
and a few more msdn sites but i cant help myself
even in this:
i cant see a way wherefrom i can get the number of pages set by the user in the print dialog
please help
Nowhere did I say that you should be able to simply get it property value from the 'e' parameter. I said that all the information you need is stored in the 'sender', i.e. the PrintDocument, or 'e', i.e. the PrintPageEventArgs. I've explained how you can use the documentation. Here's what you need to do:
1. Opened the documentation for the PrintDocument class.
2. Gone to the member listing topic.
3. Read the description of each member.
4. Clicked the link for any member that looked like it might have been relevant.
5. Read the documentation for that member.
6. Clicked the link for that member's type.
7. Read the documentation for that type.
8. Clicked the link for the type's member listing.
9. Etc.
If you had done that you would have found what you were looking for. I said that you should explore the PrintDocument type. It has a PrinterSettings property. Start there.
please done take it the other way but i am not able to find data in the msdn since it is very huge and i get confused with it most of the time about which way to go.....
you find them because you have got the experience of working with you but i can bet that for guys like me they cant find out the data for themselves in the msdn and hence they love vbforums.......
Looking at your post, I see that the second link is for the PrinterSettings class. Did you check what members the PrinterSettings class has? You can't just look at a class overview and expect to know everything about that class. You have to look at the member listing to see what properties and methods it has. I said that back in post #4:
Once you know what members it has you can work out from that how to get the information you need
Why do you need sample code? It's simple maths. You've got two numbers: the page count and the last page number. You simply set HasMorePages to True or False depending on whether one is greater than the other or not.
That said, I'm not convinced you even need the page range. I haven't really done any .NET printing so I'm not sure but, it seems to me, it may be the case that you simply send everything and then it's up to the printer to decide which pages to actually create a hard copy of. I'm not sure but that's somehting to consider. It shouldn't be hard to test to find out for sure. If my theory is correct then the only consideration for setting HasMorePages is whether or not you have more data to print.
Static a As Integer = 1
Dim m As Integer = PrintDocument1.PrinterSettings.ToPage
If a <= m Then
e.HasMorePages = True
a += 1
Exit Sub
Else
e.HasMorePages = False
End If
How about, instead of meaningless variable names like 'a' and 'm' you use meaningful names like currentPageNumber and lastPageNumber? You can then look at something like this yourself:
Code:
If currentPageNumber <= lastPageNumber Then
e.HasMorePages = True
and it should be fairly obvious that that doesn't make sense. If the current page number is equal to the last page number then we just printed the last page, so are there any more pages to print?
i quit.....
please help me with the code so that i can learn something at least by having a look at the code like i did the last time by having a look at the code that you did with the portrait/landscape
please help
It is elementary logic. If the current page is the last page then there are no more pages, otherwise there are more pages. I think that you're quite capable of putting that logic into code. You almost had it earlier but, again, you didn't actually read the words I posted.
If the current page number is equal to the last page number then we just printed the last page, so are there any more pages to print?
That is all that was really wrong with your previous code so all you had to do was address that one thing.