📜 ⬆️ ⬇️

A simple way to prepare reports based on rtf forms

During the practical operation of enterprise-level information systems, especially with an underdeveloped reporting system, it is often necessary to fill in various forms (for example, statements, references, opinions, etc.) or prepare reports for printing on a laser printer, approximately in this form :

Rtf form example
Document Title: PARAM1
Line 1ValuePARAM2
Line 2ValuePARAM3

Document signature: PARAM4

Fig.1 Example of a blank in the form of an rtf file, variables are described in the form of fields of the type “QUOTE” - PARAM1, PARAM2, PARAM3, PARAM4
')


When filling the form with data, the variables PARAM1 ... 4 will have to be replaced with their values.
In this case, the form of the form usually remains constant and unchanged, and the specific fields in the form must be “loaded” from database tables, data files, etc. In Perl terms, hash values ​​whose keys correspond to variable names:
(PARAM1 => ”PARAMETER1”, PARAM1 => ”PARAMETER2”, PARAM1 => ”PARAMETER3”,
PARAM1 => ”PARAMETER4”)
As a result, the form ready for printing on a laser printer will look something like this:

Rtf form example
Document Title: PARAMETER1
Line 1ValuePARAMETER2
Line 2ValuePARAMETER3

Document signature: PARAMETR4

Fig.2. The result of filling the rtf form (Fig. 1) by replacing the “QUOTE” type fields with the values ​​of the corresponding hash keys.


In this case, there is a need to fulfill several difficult-to-meet requirements - the development and correction of the form should be available to the end user (accountant, human resources officer, manager, etc.) and allow the fields to merge data to be arbitrarily arranged, and the preparation of the data extraction procedure - to the programmer or employee support services, that is, it is necessary to separate the presentation of data from the data extraction procedure.

Of course, you can say that this data merging technology has long been used in MS Word, for example, but it has a serious drawback: the merge procedure is rather complicated for an unprepared user (you need to prepare a data file, select a form, start a merge process, deal with the results) .

Another option - using forms in the form of XML files and filling them in accordance with the rules of substitution described in XSLT tables - has the disadvantage that it will be difficult for an unprepared user who is used to working with MS Word to create and edit XML file forms. Any common tool for working with XML, comparable in popularity with MS Word is difficult to find.

The output developed and tested for a number of years when working in a large banking information system was the option of automatically inserting data into rtf forms of reports using a simple script (in this case, perl was used, but you can use any language that supports processing of regular expressions) searching in a text rtf document of descriptors of fields of type “QUOTE” and replacing the symbolic names of these fields with the value of a variable with the same name extracted from the database table, file OF DATA (in terms perl - keyed hash of corresponding symbolic name field).

An example of a script with comments that performs a similar substitution is given at the end of the posting.

Most likely, even a brief explanation of how the script works is not required (a ready-made rtf form with variable substitution made is displayed in a temporary file temp.rtf, prepared for sending to the printer), the only part of interest in it is the regular expression:

$rtf =~ s/\{\\field\b[^{}]*\{\\\*\\fldinst.*?{\\fldrslt\s*\{([^}]+\s)?\s*([^}]+\s) ?\s*([^}]+)\}\s*((?:\{[^{}]+\}\s*)*)\}\s*\}/dosubst($1,$2,$3,$p,$&)/gesx; 


searches the rtf file for field descriptors of the “QUOTE” type and replaces them with the corresponding value from the% p hash returned by the dosubst function. The efficiency of this regular expression is tested on rtf-files prepared by all MS Office packages - from Office 95 to Office 2010.

Of course, this method has some drawbacks, for example, it is rather difficult to output table values ​​in rtf form, especially for long tables (for example, they can be output immediately in finished form by building in a perl script), but it also has serious advantages :

- development of the form and placement of data fields in it can be performed by a regular user familiar with the Word editor (who can insert “QUOTE” type fields into the text), then informing the list of data field names and what it is desirable to place in the programmer or service specialist for substitution support;
- development of a script that uploads data is carried out by a programmer, and later, if cosmetic changes are needed in the form (font, indents, logo, etc.), there is no need to involve a programmer, either the support service or the user can easily do this work the author of the form.

Thus, it is easy to separate the data presentation form, for which the user or the support service is responsible, from the actual data, the extraction procedure of which is developed by the programmer.

 #!/usr/bin/perl # filling rtf-blank # Dim Kobzev, Andrew Sapognikov # 2004 $==1000; #-------------------------filling template file------------------------------- sub dosubst { my ($pfx, $key, $xtrakey, $parm, $str) = @_; if (defined $xtrakey) { $xtrakey =~ s/[{}]//g; $xtrakey =~ s/\\w+//g; $xtrakey =~ s/\s//g; $key .= $xtrakey; } defined ($parm->{$key}) or return "\{$pfx\}"; my $val = $parm->{$key}; $val =~ s/([{}\\])/\\$1/g; $val =~ s/\n/\\line/g; $val =~ s/\r//g; return "\{$pfx$val\}"; } sub template ($$) { #filling $filename with hash $p my ($filename,$p)=@_; my $rtf; local $/, *F; open (F,"< $filename") or die "Cannot open $filename"; $rtf=<F>; close(F); #set win-1251 codepage $rtf =~ s/\\f(5|6)\\fmodern\\fcharset0/\\f$1\\fmodern\\fcharset144/; $rtf =~ s/\{\\field\b[^{}]*\{\\\*\\fldinst.*?{\\fldrslt\s*\{([^}]+\s) ?\s*([^}]+)\}\s*((?:\{[^{}]+\}\s*)*)\}\s*\}/dosubst($1,$2,$3,$p,$&)/gesx; return $rtf; }; #-------------------------main-------------------------------------------------- %p=('PARAM1'=>"1",'PARAM2'=>"2", 'PARAM3'=>"3",'PARAM4'=>"4"); my $tfil='temp.rtf'; open *FILE, "> $tfil" or die "Cannot open temporary file $tfil"; print FILE template("blank.rtf",\%p); close *FILE; #---------------------------------end main------------------------------------- 

Source: https://habr.com/ru/post/156805/


All Articles