Continued: Using XML to implement universal web report printing (implementation)
Summary:
This article combines the code in detail the implementation and expansion process of "Using XML Realization General Web Report" (hereinafter referred to as "" profit ""). This article is the sequel of "Library", and the code examples raised in the article are written in C # language.
After the publication of "Lis", a large number of readers sent E-mail to me, showing me that the program is very interested, and also ask how specific resolution and print details of the report format and request the source code of the program. The enthusiasm of the reader makes me not, although I will answer the source, but I feel sorry and regret, because of the relationship between time and energy, I can't make a very detailed detail for each letter. The answer, and the source code I wrote is also very messy. In fact, I spent two hours, I spent two hours (the original procedure was destroyed because the hard disk fault was destroyed), not only did not have any annotations and not perfect, including some The label has not been implemented yet.
In order to make up for the previous shortcomings, I spent some time to improve the structure of the program, rewrite all source code, realize all the labels, and start to explain the design and encoding process of the program, before reading this article It is highly recommended that you read the "Le" one by reading the concept. If there is a clear explanation in this article, this article will no longer introduce, here will only explain the "profit" text does not mention or introduce it. It is unclear that the readers let me know the most part of the part.
Software principle:
The principle of this software is actually very simple, that is, it is to facilitate parsing the defined XML format tag, interpret the parameter definition of the tag in the file, and finally restore this information to the printer output graphic format.
In order to express complex report styles, we need to define some tags, attach specific style information in these tags, and act similar to HTML tags, and our resolution program is equivalent to IE browser, the difference is IE The graph is output to the screen, and we are output to the printer, because the printer relative to the specialty of the display (such as paging), we cannot print directly with the web browser's label parsing function, need to be a need to meet the needs "Print Browser".
For most reports, I only define two format tags: text (TEXT) and tables, their specific attribute definitions and other settings of label definition, please refer to "Le" text, here again A structural diagram helps readers understand. As follows:
Structural design:
To describe all style markers, I first define a abstract base class Printelement, which has a virtual method DRAW, then corresponds to the table and text, derived two subclasses from Printelement, which is Table and Text, I also created a Parser The class is used to parse different styles tags and create a corresponding object, which has a static method CreateElement that creates a corresponding object based on different format tags. The structure is shown below:
The readers who have read "design patterns" must have already seen, which applies a very famous model in design mode: Abstract Factory. The advantage of using this mode is that the label objects and parsers are independent, reducing the system coupling degree, which is advantageous to increase other format labels in the future (hereinafter will give an instance) and convenient Replace different user interfaces (the client represents a Windows application or a web plugin). Code:
First, create a new project of "Windows Control Library", write Remoteprint at the project name, as shown below:
Then put the default UserControl1 class in the new project, and its constructor name and file name are changed to PrintControl. Set it back to white, add three press, and set their enable properties to false, the Anchor property is set to Bottom, Right, add a Label control to display program status, its Anchor property Set to Left. As shown below:
Then drag in three print objects from the control bar: PrintDocument, PagesetupDialog, PrintPreviewDialog, as shown below:
All Document properties of PageSetupDialog1 and PrintPreviewDialog1 are set to PrintDocument1.
Then add a new class of Printelement to the project, the code is as follows:
Using system;
USING SYSTEM.XML;
Using system.drawing;
Namespace Remoteprint
{
Public Class Printelement
{
Public Printelement ()
{
}
Public Virtual Bool Draw (Graphics G)
{
Return False;
}
}
}
There is only one virtual method DRAW in this class, pay attention to it specifies that a BOOL value needs to be returned. This value is used to indicate whether the label is printed in the page.
Then add a Table new class, the code is as follows:
Using system;
USING SYSTEM.XML;
Using system.drawing;
Namespace Remoteprint
{
Public Class Table: Printelement
{
Private XMLnode Table;
Public static int count = 0, PC = 1;
Public Table (XMLNode Table)
{
Table = Table;
}
Public Override Bool Draw (Graphics G)
{
// Table coordinates
INT TABLEX = INT.PARS (Table.Attributes ["X"]. innerText);
Int Tabley = int.parse (Table.Attributes ["y"]. innerText);
INT x = TABLEX, Y = Tabley;
DrawTopline (G, Table); // Painting Top Line
Pen Pen = New Pen (color.fromname (Table.Attributes ["BorderColor"]. InnerText),
The Table class will be independently parsed by the Table tag, all of which are completed internally in the class, so that we are directly handed over to the Table class when we are in parsing the top label, do not need to care Implement details. Add another Text class, the code is as follows:
Using system;
USING SYSTEM.XML;
Using system.drawing;
Namespace Remoteprint
{
Public class text: Printelement
{
Private XMLNode Text = NULL;
Public text (XMLNode Text)
{
TEXT = TEXT;
}
Public Override Bool Draw (Graphics G)
{
Font font = new font (text.attributes ["fontname"]. InnerText,
Like the Table class, the Text class completes parsing and printing of the Text tag, but because of the simplicity of Text, it has a lot less code. Both them inherit from Printelement, which is heavy as the implementation of the DRAW method.
Finally, we also need a parser to parse the top layer label and generate the corresponding object, and its role in this mode is a "factory class", which is responsible for producing the "product" required by the user. code show as below:
Using system;
USING SYSTEM.XML;
Namespace Remoteprint
{
Public Class Parser
{
Public Parser ()
{
}
Public Static Printelement CreateElement (XMLNode Element)
{
Printelement Printelement = NULL;
Switch (Element.name)
{
Case "text":
Printelement = new text (element);
Break;
Case "Table":
Printelement = New Table (Element);
Break;
DEFAULT:
Printelement = new printelement ();
Break;
}
Return printelement;
}
}
}
Ok, the core analysis and the specific print method of the label have been completed, and now we go back to PrintControl to write some code to test our results.
First, you need to reference two namespaces to be used:
USING SYSTEM.XML;
Using system.drawing.printing;
Then, before printing, you need to set the pages of the printer according to the PageSetting tag in the XML file, so we write a method to set the printer. Add a private method in the PrintControl class: Private Void Settingprinter (XMLNode PS)
Please note that we only put a local test data file (written for this file ", in fact, you can change the static or dynamic XML files anywhere on the load network, such as the above Doc.Load ("http://localhost/report.xml") can be rewritten:
Ok, our print control is all done here, choose to generate a release version, then copy the generated printControl.dll file to the IIS in the project directory, then create a RemotePrint.htm HTML Format file, plus:
Open the browser, type: http://localhost/remoteprint.htm, if you have already made an XML report data file like me, you can see the effect shown below.
Please note: All the data in the illustration sample is the author's casual virtual. The table data and print data in the web page are not from the same data source, nor deliberately goes right, just to demonstrate the effect, so the webpage shows the report and print There are some new reports in the preview. In practical applications, web display data can be identical to printout data.
Program expansion:
A part of the readers asked how to print some special forms of charts. The "Lee" article has been mentioned that the program can be very convenient to define the label you need, in theory, the special chart of any style can be printed . Therefore, this article intends to detail the specific process of adding your own defined label expansion printing format.
First assume that our customers are basically satisfied after watching the printed effect, but there is still a little short, if you need to print some charts? For example, a line diagram, a K-line diagram, a pie chart, a histogram, and the like. With our existing tags, we must first expand our label library to make it more expressive. Here, I will only plan to let our print control learn to draw simple line charts, I hope the reader can give an anti-three to create other various printing effects.
The most basic line diagram is composed of a line connected by the X coordinate axis, Y coordinate axis, and a series of points, so I defined the following tags:
1. Linechart: Like the Table, the Text Tag, for the pattern root label.
Property: None
2. Coordinate: coordinates.
Property: None
3. XCoordinate: X-axis coordinate line
Attributes:
# x: starting point X coordinate value
# y: The starting point Y coordinate value
# Length: Length value
# stroke: thick
# color: Color
# arrow: Is there an arrow?
4. Ycoordinate: Y-axis coordinate line
Attribute: with XCoordinate.
5. Scale: Turning
Tag content: text displayed on the scale
Attributes:
# Length: Distance Point Length Value
# hT: Tariff Highness
# width: Turning Width
# color: Color
# fontsize: Font size 6. Chart: chart root
Property: None
7. Lines: line segment
Attribute value:
# stroke: thick
# color: Color
8. Point: Point
Attribute value:
# x: x coordinate value
# y: y coordinate value
# RADIUS: radius
# color: Color
The structure is shown below:
Below is an XML line diagram example of the label just defined:
100 scale>
200 scale>
300 scale>
400 scale>
500 scale>
600 scale>
700 scale>
xcoordinate>
100 scale>
200 scale>
300 scale>
ycoordinate>
CORDINATE>
lines>
lines>
charT>
linechart>
Complete the definition of the label, the next step is to modify our program, let him "read" these labels.
First, we will add a new class of LineChart to the project, just like the Table, Text class, which is also inherited from the Printelement class, which also overloads the Draw virtual method. code show as below:
Int stroke = int.parse (lines.attributes ["stroke"]. innerText);
Point [] Points = new point [lines.childnodes.count];
Color LineColor = color.fromname (Lines.attributes ["color"]. Innertext);
For (int i = 0; i
{
XMLNode node = lines.childnodes [i];
Points [i] = new point
INT.PARSE (Node.attributes ["X"]. Innertext),
INT.PARSE (Node.attributes ["Y"]. Innertext));
Int radius = int.parse (Node.attributes ["RADIUS"]. InnerText);
Color PointColor = color.fromname (node.attributes ["color"]. Innertext);
IF (Radius! = 0) // Draw points
{
G.fillellipse (New Solidbrush (PointColor),
Points [i] .x - Radius,
Points [i] .y - radius,
RADIUS * 2,
RADIUS * 2);
}
}
Pen Pen = New Pen (LineColor);
g.drawlines (Pen, Points); / / Picture
}
}
}
Then, add a small CASE for the CreateElement method of the Parser class, the code is as follows:
Switch (Element.name)
{
Case "text":
Printelement = new text (element);
Break;
Case "Table":
Printelement = New Table (Element);
Break;
Case "linechart": // Added LineChart
Printelement = new linechart (element);
Break;
DEFAULT:
Printelement = new printelement ();
Break;
}
Replace the Table tag in the original XML file and its child tags to the next paragraph, then compile the program, the effect is as follows:
Now, our print control can print the drawline map, because we use the Abstract Factory design mode, divide the resolution of the prints and formats of the report so that this program has a very convenient expansion capability, if you need a new new The formal chart, then you need to define the label, write a parsing class, and add a CASE to this class in PASER to get it, the code inside the PrintControl does not need to be rewritten.
to sum up:
The above is how to make a detailed introduction of print controls, basically answers most of the problems in the reader letter, and there are several questions that have been asked here to answer the answer here:
Q: Whether this plan must be needed to have .NET FRAMEWORK?
A: Yes, this is also a defect in this program. But I can be sure, in the near future, Microsoft will definitely install .NET Framework in the form of an upgrade or patch to most of our Windows or even Linux operating systems. At that time, there would be no current regrets now.
Q: I use the form of WinForm applications, then is there a problem with a deployment? For example, I add a new chart format, so all print clients need to upgrade to a new version?
A: Yes, but theoretically use .NET Remoting design to avoid this problem: TEXT, CHART, etc.) and factory class (PASER) are placed on the server side to provide remote calling methods through Remoting, and only put print control (printControl) on the client, then when we add charts, you can do not need Any upgrade for the client. Q: Open the web control will not run, only display a white box, what should I do?
A: This is because you have installed .NET Framework SP1 or SP2, the default security policy is not allowed to run, then you need to make the following modifications: Open Microsoft .NET Framework Wizards, in "program", you can also Find it in the Administration Tool, click "Adjust .NET Security", as shown below:
Set the security level of the Internet area to "Full Trust", as shown below:
It is more introduced throughout the program. If you have any questions in use, please email nluyan@msn.com, nluyan@163.net, or to Microsoft's Chinese DOTNET news group to discuss. Thank you!