├── src ├── resources │ ├── .gitkeep │ ├── subreport.jasper │ ├── subreport2.jasper │ ├── subreport.jrxml │ └── subreport2.jrxml ├── output │ └── .gitignore ├── compiled │ └── .gitignore ├── data_files │ ├── contacts.json │ ├── CancelAck.xml │ └── sub_reports_bd.sql ├── input │ ├── hello_world.jrxml │ ├── Master.jrxml │ ├── json.jrxml │ ├── hello_world_params.jrxml │ └── CancelAck.jrxml └── Examples.php ├── .gitignore ├── composer.json ├── docker-compose.yml ├── index.php ├── README.md └── composer.lock /src/resources/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/output/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /src/compiled/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /vendor 3 | src/compiled/* 4 | src/output/* -------------------------------------------------------------------------------- /src/resources/subreport.jasper: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPJasper/examples/HEAD/src/resources/subreport.jasper -------------------------------------------------------------------------------- /src/resources/subreport2.jasper: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPJasper/examples/HEAD/src/resources/subreport2.jasper -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phpjasper/examples", 3 | "description": "PHPJasper Examples", 4 | "license": "MIT", 5 | "keywords": [ 6 | "reports", 7 | "php-reports", 8 | "pdf" 9 | ], 10 | "authors": [ 11 | { 12 | "name": "Daniel Rodrigues Lima", 13 | "email": "danielrodrigues-ti@hotmail.com" 14 | } 15 | ], 16 | "require": { 17 | "php": "^7.2|^8.0", 18 | "geekcom/phpjasper": "^3.4.0" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "Examples\\": "src/" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | mysql: 4 | image: mysql 5 | command: --default-authentication-plugin=mysql_native_password 6 | restart: always 7 | container_name: phpjasperExampleDb 8 | ports: 9 | - "3307:3306" 10 | environment: 11 | - MYSQL_ROOT_PASSWORD=phpjasper 12 | - MYSQL_DATABASE=sub_reports 13 | - MYSQL_USER=phpjasper 14 | - MYSQL_PASSWORD=phpjasper 15 | php: 16 | image: geekcom/phpjasper:latest 17 | container_name: phpjasperExample 18 | volumes: 19 | - .:/var/www/app 20 | tty: true 21 | links: 22 | - mysql 23 | -------------------------------------------------------------------------------- /src/data_files/contacts.json: -------------------------------------------------------------------------------- 1 | { 2 | "contacts": { 3 | "person": [ 4 | { 5 | "name": "Vittor Mattos (vitormattos)", 6 | "street": "Street 1", 7 | "city": "Fairfax", 8 | "phone": "+1 (415) 111-1111" 9 | }, 10 | { 11 | "name": "Daniel Rodrigues (geekcom)", 12 | "street": "Street 2", 13 | "city": "San Francisco", 14 | "phone": "+1 (415) 222-2222" 15 | }, 16 | { 17 | "name": "Rafael Queiroz (rafaelqueiroz)", 18 | "street": "Street 2", 19 | "city": "Paradise City", 20 | "phone": "+1 (415) 333-3333" 21 | } 22 | ] 23 | } 24 | } -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | compileExample(); 14 | 15 | //Process file .jrxml or .jasper 16 | $examples->processExample(); 17 | 18 | //List Parameters-> .jrxml or .jasper 19 | $examples->listParametersExample(); 20 | 21 | //Generate reports from XML file 22 | $examples->XMLExample(); 23 | 24 | //Generate reports from a JSON file 25 | $examples->JsonExample(); 26 | 27 | //Generate reports from a database 28 | //$examples->DbExample(); 29 | 30 | //Generate reports from a database with subreports 31 | //$examples->DbExampleWithSubReport(); 32 | -------------------------------------------------------------------------------- /src/data_files/CancelAck.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1361E3F3-B493-4F5C-9A2D-67C7CC151907201 5 | 136F0E14-3C92-4506-991D-0DB2FB45E0A9201 6 | 13741D6D-574A-458E-8112-4943929D3DFA201 7 | 137A252B-4F8B-48CB-A5FE-219FE149CC1F201 8 | 138665F0-3935-4880-B125-3C0D03218CA8201 9 | 10 | cqOD3A20ku9vHI3MGI18HkSsljYcURr6fSjyk9I+MRghG9T2/EXpiqZahCSYCBr0JwFV/rCWbP6kvdk7eYGerg== 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHPJasper Examples 2 | 3 | ### How to use 4 | _Do you need Docker and Docker Compose installed in your machine_ 5 | 6 | * Clone or download the repository; 7 | * Run the commands into the path `/examples`: 8 | * `docker-compose up -d`; 9 | * `docker exec -it phpjasperExample composer install`. 10 | * `docker exec -it phpjasperExample sudo apk add ttf-dejavu` 11 | --- 12 | 13 | ### Examples 14 | _Use the command `docker exec -it phpjasperExample php index.php` to run examples_ 15 | 16 | **Compile jrxml into .jasper** 17 | 18 | ` 19 | $examples->compileExample(); 20 | ` 21 | 22 | **Process file .jrxml or .jasper** 23 | 24 | `$examples->processExample();` 25 | 26 | **List Parameters-> .jrxml or .jasper** 27 | 28 | `$examples->listParametersExample();` 29 | 30 | **Generate reports from a database** 31 | 32 | `$examples->DbExample();` 33 | 34 | **Generate reports from a database with sub reports** 35 | 36 | `$examples->DbExampleWithSubReport();` 37 | 38 | **Generate reports from an XML file** 39 | 40 | `$examples->XMLExample();` 41 | 42 | **Generate reports from a JSON file** 43 | 44 | `$examples->JsonExample();` 45 | 46 | ### Folder structure 47 | 48 | * compiled: Compiled .jasper files will be in this folder; 49 | * data_files: Contains data sources for examples; 50 | * input: Contains the reports `.jrxml` files; 51 | * output: Will have the results of the examples; 52 | * resources: Contains other files. 53 | -------------------------------------------------------------------------------- /src/data_files/sub_reports_bd.sql: -------------------------------------------------------------------------------- 1 | create DATABASE sub_reports; 2 | 3 | create table PERSONS ( 4 | ID int primary key, 5 | NAME varchar(30), 6 | CITY varchar(30) ); 7 | 8 | insert into PERSONS values(1, 'ETHAN', 'NEW YORK'); 9 | insert into PERSONS values(2, 'CALEB', 'SAN FRANCISCO'); 10 | insert into PERSONS values(3, 'WILLIAM', 'LONDON'); 11 | 12 | create table EMAIL_ADDRESSES ( 13 | ID int primary key, 14 | ID_PERSON varchar(30), 15 | EMAIL varchar(100) ); 16 | 17 | insert into EMAIL_ADDRESSES values(1, 1, 'ethan@yahoo.com'); 18 | insert into EMAIL_ADDRESSES values(2, 1, 'ethan@gmail.com'); 19 | insert into EMAIL_ADDRESSES values(3, 2, 'caleb@yahoo.com'); 20 | insert into EMAIL_ADDRESSES values(4, 2, 'caleb2@linux.com'); 21 | insert into EMAIL_ADDRESSES values(5, 2, 'cccleb@jaspersoft.com'); 22 | insert into EMAIL_ADDRESSES values(6, 3, 'wlm@somedomain.co.uk'); 23 | insert into EMAIL_ADDRESSES values(7, 3, 'william@someemail.eu'); 24 | insert into EMAIL_ADDRESSES values(8, 3, 'willy@myemail.org'); 25 | 26 | create table PHONE_NUMBERS ( 27 | ID int primary key, 28 | ID_PERSON varchar(30), 29 | PHONE varchar(100) ); 30 | 31 | insert into PHONE_NUMBERS values(1, 1, '1(111) 111-1111'); 32 | insert into PHONE_NUMBERS values(2, 1, '1(222) 222-2222'); 33 | insert into PHONE_NUMBERS values(3, 1, '1(333) 333-3333'); 34 | insert into PHONE_NUMBERS values(4, 2, '1(444) 444-4444'); 35 | insert into PHONE_NUMBERS values(5, 3, '1(555) 555-5555'); 36 | insert into PHONE_NUMBERS values(6, 3, '1(666) 666-6666'); -------------------------------------------------------------------------------- /src/resources/subreport.jrxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/resources/subreport2.jrxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "b2d14ea43c356a0dc2349f1e41af88c6", 8 | "packages": [ 9 | { 10 | "name": "geekcom/phpjasper", 11 | "version": "3.4.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/PHPJasper/phpjasper.git", 15 | "reference": "bae2d6c0064ee32e5f478e0208af419ba3fcb2ee" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/PHPJasper/phpjasper/zipball/bae2d6c0064ee32e5f478e0208af419ba3fcb2ee", 20 | "reference": "bae2d6c0064ee32e5f478e0208af419ba3fcb2ee", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": "^7.2|^8.0" 25 | }, 26 | "require-dev": { 27 | "php-coveralls/php-coveralls": "^2.2", 28 | "phpstan/phpstan": "^0.12.5", 29 | "phpunit/phpunit": "^8.4|^9.4", 30 | "squizlabs/php_codesniffer": "*" 31 | }, 32 | "type": "library", 33 | "autoload": { 34 | "psr-4": { 35 | "PHPJasper\\": "src/" 36 | } 37 | }, 38 | "notification-url": "https://packagist.org/downloads/", 39 | "license": [ 40 | "MIT" 41 | ], 42 | "authors": [ 43 | { 44 | "name": "Daniel Rodrigues Lima", 45 | "email": "geekcom@php.net", 46 | "role": "lead" 47 | } 48 | ], 49 | "description": "A PHP report generator", 50 | "keywords": [ 51 | "pdf", 52 | "php-reports", 53 | "reports" 54 | ], 55 | "support": { 56 | "issues": "https://github.com/PHPJasper/phpjasper/issues", 57 | "source": "https://github.com/PHPJasper/phpjasper/tree/3.4.0" 58 | }, 59 | "funding": [ 60 | { 61 | "url": "https://nubank.com.br/pagar/518o5/zVBzxd00Sb", 62 | "type": "custom" 63 | } 64 | ], 65 | "time": "2023-11-05T17:24:54+00:00" 66 | } 67 | ], 68 | "packages-dev": [], 69 | "aliases": [], 70 | "minimum-stability": "stable", 71 | "stability-flags": [], 72 | "prefer-stable": false, 73 | "prefer-lowest": false, 74 | "platform": { 75 | "php": "^7.2|^8.0" 76 | }, 77 | "platform-dev": [], 78 | "plugin-api-version": "2.6.0" 79 | } 80 | -------------------------------------------------------------------------------- /src/input/hello_world.jrxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | <band height="72"> 12 | <frame> 13 | <reportElement mode="Opaque" x="-20" y="-20" width="595" height="92" backcolor="#006699" uuid="3501dac6-be9b-47b1-bf09-8b25fbc6c79f"/> 14 | <staticText> 15 | <reportElement x="20" y="20" width="349" height="45" forecolor="#FFFFFF" uuid="2464c9ca-82a1-48c9-87ea-b68192294c4a"/> 16 | <textElement> 17 | <font fontName="DejaVu Sans" size="34" isBold="true"/> 18 | </textElement> 19 | <text><![CDATA[PHPjasper example]]></text> 20 | </staticText> 21 | </frame> 22 | </band> 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/Examples.php: -------------------------------------------------------------------------------- 1 | PHPJasper = new PHPJasper(); 18 | } 19 | 20 | public function compileExample() 21 | { 22 | $input_file = __DIR__ . '/input/hello_world.jrxml'; 23 | $output_file = __DIR__ . '/compiled'; 24 | 25 | $this->PHPJasper->compile($input_file, $output_file)->execute(); 26 | } 27 | 28 | public function processExample() 29 | { 30 | $input = __DIR__ . '/compiled/hello_world.jasper'; 31 | $output = __DIR__ . '/output'; 32 | $options = ['format' => ['pdf', 'rtf', 'xml'], 'locale' => 'en']; 33 | 34 | $this->PHPJasper->process( 35 | $input, 36 | $output, 37 | $options 38 | )->execute(); 39 | } 40 | 41 | public function listParametersExample() 42 | { 43 | $input = __DIR__ . '/input/hello_world_params.jrxml'; 44 | $output = $this->PHPJasper->listParameters($input)->execute(); 45 | 46 | foreach ($output as $parameter_description) { 47 | print '
' . $parameter_description . '
'; 48 | } 49 | } 50 | 51 | public function DbExample() 52 | { 53 | $input = __DIR__ . '/input/teste.jrxml'; 54 | $output = __DIR__ . '/output'; 55 | $options = [ 56 | 'format' => ['pdf', 'xml', 'html'], 57 | 'locale' => 'en', 58 | 'params' => [], 59 | 'db_connection' => [ 60 | 'driver' => 'generic', //mysql, postgres, oracle, generic (jdbc) 61 | 'username' => 'username', 62 | 'password' => 'password', 63 | 'host' => 'localhost', 64 | 'database' => 'database_name', 65 | 'port' => '0000' //3306 for mysql 66 | ] 67 | ]; 68 | $this->PHPJasper->process( 69 | $input, 70 | $output, 71 | $options 72 | )->execute(); 73 | } 74 | 75 | public function DbExampleWithSubReport() 76 | { 77 | $input = __DIR__ . '/input/Master.jrxml'; 78 | $output = __DIR__ . '/output'; 79 | $options = [ 80 | 'format' => ['pdf'], 81 | 'locale' => 'en', 82 | 'params' => [], 83 | 'resources' => __DIR__ . '/resources', //place of resources 84 | 'db_connection' => [ 85 | 'driver' => 'mysql', //mysql, postgres, oracle, generic (jdbc) 86 | 'username' => 'phpjasper', 87 | 'password' => 'phpjasper', 88 | 'host' => 'mysql', 89 | 'database' => 'sub_reports', 90 | 'port' => '3306', 91 | ] 92 | ]; 93 | 94 | $this->PHPJasper->process( 95 | $input, 96 | $output, 97 | $options 98 | )->execute(); 99 | } 100 | 101 | public function XMLExample() 102 | { 103 | $input = __DIR__ . '/input/CancelAck.jrxml'; 104 | $output = __DIR__ . '/output'; 105 | $data_file = __DIR__ . '/data_files/CancelAck.xml'; 106 | $options = [ 107 | 'format' => ['pdf'], 108 | 'params' => [], 109 | 'locale' => 'en', 110 | 'db_connection' => [ 111 | 'driver' => 'xml', 112 | 'data_file' => $data_file, 113 | 'xml_xpath' => '/CancelResponse/CancelResult/ID' 114 | ] 115 | ]; 116 | 117 | $this->PHPJasper->process( 118 | $input, 119 | $output, 120 | $options 121 | )->execute(); 122 | } 123 | 124 | public function JsonExample() 125 | { 126 | $input = __DIR__ . '/input/json.jrxml'; 127 | $output = __DIR__ . '/output'; 128 | $data_file = __DIR__ . '/data_files/contacts.json'; 129 | $options = [ 130 | 'format' => ['pdf'], 131 | 'params' => [], 132 | 'locale' => 'en', 133 | 'db_connection' => [ 134 | 'driver' => 'json', 135 | 'data_file' => $data_file, 136 | 'json_query' => 'contacts.person' 137 | ] 138 | ]; 139 | 140 | $this->PHPJasper->process( 141 | $input, 142 | $output, 143 | $options 144 | )->execute(); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/input/Master.jrxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | <band height="51" splitType="Stretch"> 20 | <staticText> 21 | <reportElement mode="Opaque" x="0" y="0" width="555" height="50" forecolor="#4164A6" uuid="2e9bc4a2-7a29-4567-8abb-f04dfadc87b4"/> 22 | <textElement textAlignment="Left" verticalAlignment="Middle"> 23 | <font size="20"/> 24 | </textElement> 25 | <text><![CDATA[Address Book]]></text> 26 | </staticText> 27 | </band> 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /src/input/json.jrxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | <band height="72"> 28 | <frame> 29 | <reportElement mode="Opaque" x="-20" y="-20" width="595" height="92" backcolor="#006699" uuid="d6b7d5aa-5c6b-4106-9569-b0014b63e753"/> 30 | <staticText> 31 | <reportElement x="20" y="20" width="267" height="43" forecolor="#FFFFFF" uuid="2932e85f-a2d7-40d5-9dad-0b5ea669ad15"/> 32 | <textElement> 33 | <font size="22" isBold="true"/> 34 | </textElement> 35 | <text><![CDATA[PHPJasper example]]></text> 36 | </staticText> 37 | <staticText> 38 | <reportElement x="298" y="43" width="277" height="20" forecolor="#FFFFFF" uuid="04e1a0ed-0b0f-41d4-93e9-792d4fd37d28"/> 39 | <textElement textAlignment="Right"> 40 | <font size="14" isBold="false"/> 41 | </textElement> 42 | <text><![CDATA[Report with JSON Datasource]]></text> 43 | </staticText> 44 | </frame> 45 | </band> 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /src/input/hello_world_params.jrxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | <band height="72"> 17 | <frame> 18 | <reportElement uuid="5347bff5-dbb0-4672-b148-036cdd75c8c7" mode="Opaque" x="-20" y="-20" width="595" height="92" backcolor="#006699"/> 19 | <staticText> 20 | <reportElement uuid="8b0fa6d5-c0c6-4530-95bb-93c3b34d2fca" x="20" y="20" width="234" height="43" forecolor="#FFFFFF"/> 21 | <textElement> 22 | <font size="34" isBold="true"/> 23 | </textElement> 24 | <text><![CDATA[JasperStarter]]></text> 25 | </staticText> 26 | <staticText> 27 | <reportElement uuid="84c20b7b-2750-44e1-8f6e-87cc755158c2" x="298" y="43" width="277" height="20" forecolor="#FFFFFF"/> 28 | <textElement textAlignment="Right"> 29 | <font size="14" isBold="false"/> 30 | </textElement> 31 | <text><![CDATA[Report with parameters]]></text> 32 | </staticText> 33 | </frame> 34 | </band> 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /src/input/CancelAck.jrxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | --------------------------------------------------------------------------------