Unzipped Gnumeric File (#3591)

* Unzipped Gnumeric File

A Gnumeric file is normally a gzipped Xml file. However, the Gnumeric application will also read an unzipped Xml file. Allow PhpSpreadsheet to do the same.

* Scrutinizer (legitimate)

Fix minor problem.
This commit is contained in:
oleibman
2023-06-03 07:53:54 -07:00
committed by GitHub
parent a0a9b2be21
commit a2edbf8776
7 changed files with 479 additions and 44 deletions
+35 -16
View File
@@ -80,17 +80,15 @@ class Gnumeric extends BaseReader
*/
public function canRead(string $filename): bool
{
// Check if gzlib functions are available
if (File::testFileNoThrow($filename) && function_exists('gzread')) {
// Read signature data (first 3 bytes)
$fh = fopen($filename, 'rb');
if ($fh !== false) {
$data = fread($fh, 2);
fclose($fh);
$data = null;
if (File::testFileNoThrow($filename)) {
$data = $this->gzfileGetContents($filename);
if (strpos($data, self::NAMESPACE_GNM) === false) {
$data = '';
}
}
return isset($data) && $data === chr(0x1F) . chr(0x8B);
return !empty($data);
}
private static function matchXml(XMLReader $xml, string $expectedLocalName): bool
@@ -110,9 +108,13 @@ class Gnumeric extends BaseReader
public function listWorksheetNames($filename)
{
File::assertFile($filename);
if (!$this->canRead($filename)) {
throw new Exception($filename . ' is an invalid Gnumeric file.');
}
$xml = new XMLReader();
$xml->xml($this->getSecurityScannerOrThrow()->scanFile('compress.zlib://' . realpath($filename)), null, Settings::getLibXmlLoaderOptions());
$contents = $this->gzfileGetContents($filename);
$xml->xml($contents, null, Settings::getLibXmlLoaderOptions());
$xml->setParserProperty(2, true);
$worksheetNames = [];
@@ -139,9 +141,13 @@ class Gnumeric extends BaseReader
public function listWorksheetInfo($filename)
{
File::assertFile($filename);
if (!$this->canRead($filename)) {
throw new Exception($filename . ' is an invalid Gnumeric file.');
}
$xml = new XMLReader();
$xml->xml($this->getSecurityScannerOrThrow()->scanFile('compress.zlib://' . realpath($filename)), null, Settings::getLibXmlLoaderOptions());
$contents = $this->gzfileGetContents($filename);
$xml->xml($contents, null, Settings::getLibXmlLoaderOptions());
$xml->setParserProperty(2, true);
$worksheetInfo = [];
@@ -185,13 +191,23 @@ class Gnumeric extends BaseReader
*/
private function gzfileGetContents($filename)
{
$file = @gzopen($filename, 'rb');
$data = '';
if ($file !== false) {
while (!gzeof($file)) {
$data .= gzread($file, 1024);
$contents = @file_get_contents($filename);
if ($contents !== false) {
if (substr($contents, 0, 2) === "\x1f\x8b") {
// Check if gzlib functions are available
if (function_exists('gzdecode')) {
$contents = @gzdecode($contents);
if ($contents !== false) {
$data = $contents;
}
}
} else {
$data = $contents;
}
gzclose($file);
}
if ($data !== '') {
$data = $this->getSecurityScannerOrThrow()->scan($data);
}
return $data;
@@ -245,10 +261,13 @@ class Gnumeric extends BaseReader
{
$this->spreadsheet = $spreadsheet;
File::assertFile($filename);
if (!$this->canRead($filename)) {
throw new Exception($filename . ' is an invalid Gnumeric file.');
}
$gFileData = $this->gzfileGetContents($filename);
$xml2 = simplexml_load_string($this->getSecurityScannerOrThrow()->scan($gFileData), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions());
$xml2 = simplexml_load_string($gFileData, 'SimpleXMLElement', Settings::getLibXmlLoaderOptions());
$xml = self::testSimpleXml($xml2);
$gnmXML = $xml->children(self::NAMESPACE_GNM);
@@ -97,6 +97,7 @@ class IOFactoryTest extends TestCase
return [
['samples/templates/26template.xlsx', 'Xlsx', Reader\Xlsx::class],
['samples/templates/GnumericTest.gnumeric', 'Gnumeric', Reader\Gnumeric::class],
['tests/data/Reader/Gnumeric/PageSetup.gnumeric.unzipped.xml', 'Gnumeric', Reader\Gnumeric::class],
['samples/templates/old.gnumeric', 'Gnumeric', Reader\Gnumeric::class],
['samples/templates/30template.xls', 'Xls', Reader\Xls::class],
['samples/templates/OOCalcTest.ods', 'Ods', Reader\Ods::class],
@@ -2,6 +2,7 @@
namespace PhpOffice\PhpSpreadsheetTests\Reader\Gnumeric;
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
use PhpOffice\PhpSpreadsheet\Reader\Gnumeric;
use PHPUnit\Framework\TestCase;
@@ -9,9 +10,7 @@ class GnumericInfoTest extends TestCase
{
public function testListNames(): void
{
$filename = __DIR__
. '/../../../..'
. '/samples/templates/GnumericTest.gnumeric';
$filename = 'samples/templates/GnumericTest.gnumeric';
$reader = new Gnumeric();
$names = $reader->listWorksheetNames($filename);
self::assertCount(2, $names);
@@ -21,9 +20,7 @@ class GnumericInfoTest extends TestCase
public function testListInfo(): void
{
$filename = __DIR__
. '/../../../..'
. '/samples/templates/GnumericTest.gnumeric';
$filename = 'samples/templates/GnumericTest.gnumeric';
$reader = new Gnumeric();
$info = $reader->listWorksheetInfo($filename);
$expected = [
@@ -44,4 +41,22 @@ class GnumericInfoTest extends TestCase
];
self::assertEquals($expected, $info);
}
public function testListNamesNotGumeric(): void
{
$this->expectException(ReaderException::class);
$this->expectExceptionMessage('invalid Gnumeric file');
$filename = 'samples/templates/excel2003.xml';
$reader = new Gnumeric();
$reader->listWorksheetNames($filename);
}
public function testListInfoNotXml(): void
{
$this->expectException(ReaderException::class);
$this->expectExceptionMessage('invalid Gnumeric file');
$filename = __FILE__;
$reader = new Gnumeric();
$reader->listWorksheetInfo($filename);
}
}
@@ -3,6 +3,7 @@
namespace PhpOffice\PhpSpreadsheetTests\Reader\Gnumeric;
use DateTimeZone;
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
use PhpOffice\PhpSpreadsheet\Reader\Gnumeric;
use PhpOffice\PhpSpreadsheet\Shared\Date;
use PhpOffice\PhpSpreadsheet\Style\Border;
@@ -16,9 +17,7 @@ class GnumericLoadTest extends TestCase
{
public function testLoad(): void
{
$filename = __DIR__
. '/../../../..'
. '/samples/templates/GnumericTest.gnumeric';
$filename = 'samples/templates/GnumericTest.gnumeric';
$reader = new Gnumeric();
$spreadsheet = $reader->load($filename);
self::assertEquals(2, $spreadsheet->getSheetCount());
@@ -132,9 +131,7 @@ class GnumericLoadTest extends TestCase
public function testLoadFilter(): void
{
$filename = __DIR__
. '/../../../..'
. '/samples/templates/GnumericTest.gnumeric';
$filename = 'samples/templates/GnumericTest.gnumeric';
$reader = new Gnumeric();
$filter = new GnumericFilter();
$reader->setReadFilter($filter);
@@ -150,9 +147,7 @@ class GnumericLoadTest extends TestCase
public function testLoadOld(): void
{
$filename = __DIR__
. '/../../../..'
. '/samples/templates/old.gnumeric';
$filename = 'samples/templates/old.gnumeric';
$reader = new Gnumeric();
$spreadsheet = $reader->load($filename);
$props = $spreadsheet->getProperties();
@@ -162,9 +157,7 @@ class GnumericLoadTest extends TestCase
public function testLoadSelectedSheets(): void
{
$filename = __DIR__
. '/../../../..'
. '/samples/templates/GnumericTest.gnumeric';
$filename = 'samples/templates/GnumericTest.gnumeric';
$reader = new Gnumeric();
$reader->setLoadSheetsOnly(['Unknown Sheet', 'Report Data']);
$spreadsheet = $reader->load($filename);
@@ -176,4 +169,22 @@ class GnumericLoadTest extends TestCase
self::assertSame('A1', $sheet->getSelectedCells());
$spreadsheet->disconnectWorksheets();
}
public function testLoadNotGnumeric(): void
{
$this->expectException(ReaderException::class);
$this->expectExceptionMessage('invalid Gnumeric file');
$filename = 'samples/templates/excel2003.xml';
$reader = new Gnumeric();
$reader->load($filename);
}
public function testLoadNotXml(): void
{
$this->expectException(ReaderException::class);
$this->expectExceptionMessage('invalid Gnumeric file');
$filename = __FILE__;
$reader = new Gnumeric();
$reader->load($filename);
}
}
@@ -10,9 +10,19 @@ class PageSetupTest extends TestCase
{
private const MARGIN_PRECISION = 0.001;
public function testPageSetup(): void
public static function fileProvider(): array
{
return [
['tests/data/Reader/Gnumeric/PageSetup.gnumeric'],
['tests/data/Reader/Gnumeric/PageSetup.gnumeric.unzipped.xml'],
];
}
/**
* @dataProvider fileProvider
*/
public function testPageSetup(string $filename): void
{
$filename = 'tests/data/Reader/Gnumeric/PageSetup.gnumeric';
$reader = new Gnumeric();
$spreadsheet = $reader->load($filename);
$assertions = $this->pageSetupAssertions();
@@ -39,9 +49,11 @@ class PageSetupTest extends TestCase
$spreadsheet->disconnectWorksheets();
}
public function testPageMargins(): void
/**
* @dataProvider fileProvider
*/
public function testPageMargins(string $filename): void
{
$filename = 'tests/data/Reader/Gnumeric/PageSetup.gnumeric';
$reader = new Gnumeric();
$spreadsheet = $reader->load($filename);
$assertions = $this->pageMarginAssertions();
@@ -10,9 +10,7 @@ class XmlInfoTest extends TestCase
{
public function testListNames(): void
{
$filename = __DIR__
. '/../../../..'
. '/samples/templates/excel2003.xml';
$filename = 'samples/templates/excel2003.xml';
$reader = new Xml();
$names = $reader->listWorksheetNames($filename);
self::assertCount(2, $names);
@@ -23,17 +21,26 @@ class XmlInfoTest extends TestCase
public function testListNamesInvalidFile(): void
{
$this->expectException(ReaderException::class);
$this->expectExceptionMessage('Invalid Spreadsheet file');
$filename = __FILE__;
$reader = new Xml();
$names = $reader->listWorksheetNames($filename);
self::assertNotEquals($names, $names);
}
public function testListNamesGnumericFile(): void
{
$this->expectException(ReaderException::class);
$this->expectExceptionMessage('Invalid Spreadsheet file');
$filename = 'tests/data/Reader/Gnumeric/PageSetup.gnumeric.unzipped.xml';
$reader = new Xml();
$names = $reader->listWorksheetNames($filename);
self::assertNotEquals($names, $names);
}
public function testListInfo(): void
{
$filename = __DIR__
. '/../../../..'
. '/samples/templates/excel2003.xml';
$filename = 'samples/templates/excel2003.xml';
$reader = new Xml();
$info = $reader->listWorksheetInfo($filename);
$expected = [
@@ -58,18 +65,40 @@ class XmlInfoTest extends TestCase
public function testListInfoInvalidFile(): void
{
$this->expectException(ReaderException::class);
$this->expectExceptionMessage('Invalid Spreadsheet file');
$filename = __FILE__;
$reader = new Xml();
$info = $reader->listWorksheetInfo($filename);
self::assertNotEquals($info, $info);
}
public function testListInfoGnumericFile(): void
{
$this->expectException(ReaderException::class);
$this->expectExceptionMessage('Invalid Spreadsheet file');
$filename = 'tests/data/Reader/Gnumeric/PageSetup.gnumeric.unzipped.xml';
$reader = new Xml();
$info = $reader->listWorksheetInfo($filename);
self::assertNotEquals($info, $info);
}
public function testLoadInvalidFile(): void
{
$this->expectException(ReaderException::class);
$this->expectExceptionMessage('Invalid Spreadsheet file');
$filename = __FILE__;
$reader = new Xml();
$spreadsheet = $reader->load($filename);
self::assertNotEquals($spreadsheet, $spreadsheet);
}
public function testLoadGnumericFile(): void
{
$this->expectException(ReaderException::class);
$this->expectExceptionMessage('Invalid Spreadsheet file');
$filename = 'tests/data/Reader/Gnumeric/PageSetup.gnumeric.unzipped.xml';
$reader = new Xml();
$spreadsheet = $reader->load($filename);
self::assertNotEquals($spreadsheet, $spreadsheet);
}
}
@@ -0,0 +1,348 @@
<?xml version="1.0" encoding="UTF-8"?>
<gnm:Workbook xmlns:gnm="http://www.gnumeric.org/v10.dtd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.gnumeric.org/v9.xsd">
<gnm:Version Epoch="1" Major="12" Minor="17" Full="1.12.17"/>
<gnm:Attributes>
<gnm:Attribute>
<gnm:name>WorkbookView::show_horizontal_scrollbar</gnm:name>
<gnm:value>TRUE</gnm:value>
</gnm:Attribute>
<gnm:Attribute>
<gnm:name>WorkbookView::show_vertical_scrollbar</gnm:name>
<gnm:value>TRUE</gnm:value>
</gnm:Attribute>
<gnm:Attribute>
<gnm:name>WorkbookView::show_notebook_tabs</gnm:name>
<gnm:value>TRUE</gnm:value>
</gnm:Attribute>
<gnm:Attribute>
<gnm:name>WorkbookView::do_auto_completion</gnm:name>
<gnm:value>TRUE</gnm:value>
</gnm:Attribute>
<gnm:Attribute>
<gnm:name>WorkbookView::is_protected</gnm:name>
<gnm:value>FALSE</gnm:value>
</gnm:Attribute>
</gnm:Attributes>
<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:ooo="http://openoffice.org/2004/office" office:version="1.2">
<office:meta>
<dc:creator>Mark Baker</dc:creator>
<dc:date>2020-07-04T15:11:06Z</dc:date>
<meta:user-defined meta:name="dc:publisher" meta:value-type="string"></meta:user-defined>
<meta:user-defined meta:name="gsf:links-dirty" meta:value-type="boolean">false</meta:user-defined>
<meta:user-defined meta:name="gsf:scale" meta:value-type="boolean">false</meta:user-defined>
<meta:user-defined meta:name="gsf:security" meta:value-type="float">0</meta:user-defined>
<meta:creation-date>2020-06-29T17:37:00Z</meta:creation-date>
<meta:initial-creator>Mark Baker</meta:initial-creator>
<meta:user-defined meta:name="meta:print-date" meta:value-type="date">2020-07-04T11:51:41Z</meta:user-defined>
<meta:user-defined meta:name="xlsx:HyperlinksChanged" meta:value-type="boolean">false</meta:user-defined>
<meta:user-defined meta:name="xlsx:SharedDoc" meta:value-type="boolean">false</meta:user-defined>
</office:meta>
</office:document-meta>
<gnm:Calculation ManualRecalc="0" EnableIteration="1" MaxIterations="100" IterationTolerance="0.001" FloatRadix="2" FloatDigits="53"/>
<gnm:SheetNameIndex>
<gnm:SheetName gnm:Cols="16384" gnm:Rows="1048576">Sheet1</gnm:SheetName>
<gnm:SheetName gnm:Cols="16384" gnm:Rows="1048576">Sheet2</gnm:SheetName>
<gnm:SheetName gnm:Cols="16384" gnm:Rows="1048576">Sheet3</gnm:SheetName>
<gnm:SheetName gnm:Cols="16384" gnm:Rows="1048576">Sheet4</gnm:SheetName>
</gnm:SheetNameIndex>
<gnm:Geometry Width="1440" Height="626"/>
<gnm:Sheets>
<gnm:Sheet DisplayFormulas="0" HideZero="0" HideGrid="0" HideColHeader="0" HideRowHeader="0" DisplayOutlines="1" OutlineSymbolsBelow="1" OutlineSymbolsRight="1" Visibility="GNM_SHEET_VISIBILITY_VISIBLE" GridColor="0:0:0">
<gnm:Name>Sheet1</gnm:Name>
<gnm:MaxCol>2</gnm:MaxCol>
<gnm:MaxRow>4</gnm:MaxRow>
<gnm:Zoom>1</gnm:Zoom>
<gnm:Names>
<gnm:Name>
<gnm:name>Print_Area</gnm:name>
<gnm:value>#REF!</gnm:value>
<gnm:position>A1</gnm:position>
</gnm:Name>
<gnm:Name>
<gnm:name>Sheet_Title</gnm:name>
<gnm:value>&quot;Sheet1&quot;</gnm:value>
<gnm:position>A1</gnm:position>
</gnm:Name>
</gnm:Names>
<gnm:PrintInformation>
<gnm:Margins>
<gnm:top Points="68.03" PrefUnit="mm"/>
<gnm:bottom Points="53.86" PrefUnit="mm"/>
<gnm:left Points="36.85" PrefUnit="mm"/>
<gnm:right Points="36.85" PrefUnit="mm"/>
<gnm:header Points="22.68" PrefUnit="mm"/>
<gnm:footer Points="22.68" PrefUnit="mm"/>
</gnm:Margins>
<gnm:Scale type="percentage" percentage="75"/>
<gnm:vcenter value="0"/>
<gnm:hcenter value="1"/>
<gnm:grid value="0"/>
<gnm:even_if_only_styles value="0"/>
<gnm:monochrome value="0"/>
<gnm:draft value="0"/>
<gnm:titles value="0"/>
<gnm:do_not_print value="0"/>
<gnm:print_range value="GNM_PRINT_ACTIVE_SHEET"/>
<gnm:order>d_then_r</gnm:order>
<gnm:orientation>portrait</gnm:orientation>
<gnm:Header Left="" Middle="&amp;[TAB]" Right=""/>
<gnm:Footer Left="" Middle="Page &amp;[PAGE]" Right=""/>
<gnm:paper>iso_a4</gnm:paper>
<gnm:comments placement="GNM_PRINT_COMMENTS_IN_PLACE"/>
<gnm:errors PrintErrorsAs="GNM_PRINT_ERRORS_AS_DISPLAYED"/>
</gnm:PrintInformation>
<gnm:Styles>
<gnm:StyleRegion startCol="0" startRow="0" endCol="16383" endRow="1048575">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="11" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Calibri</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
</gnm:Styles>
<gnm:Cols DefaultSizePts="48"/>
<gnm:Rows DefaultSizePts="14.25">
<gnm:RowInfo No="0" Unit="14.25" HardSize="1" Count="4"/>
</gnm:Rows>
<gnm:Selections CursorCol="0" CursorRow="0">
<gnm:Selection startCol="0" startRow="0" endCol="2" endRow="4"/>
</gnm:Selections>
<gnm:Cells>
<gnm:Cell Row="0" Col="0" ValueType="40">1</gnm:Cell>
<gnm:Cell Row="0" Col="1" ValueType="40">2</gnm:Cell>
<gnm:Cell Row="0" Col="2" ValueType="40">3</gnm:Cell>
<gnm:Cell Row="1" Col="0" ValueType="40">4</gnm:Cell>
<gnm:Cell Row="1" Col="1" ValueType="40">5</gnm:Cell>
<gnm:Cell Row="1" Col="2" ValueType="40">6</gnm:Cell>
<gnm:Cell Row="2" Col="0" ValueType="40">7</gnm:Cell>
<gnm:Cell Row="2" Col="1" ValueType="40">8</gnm:Cell>
<gnm:Cell Row="2" Col="2" ValueType="40">9</gnm:Cell>
<gnm:Cell Row="4" Col="0">=sum(A2:C2,B1:B3)</gnm:Cell>
<gnm:Cell Row="4" Col="1">=count(A2:C2,B1:B3)</gnm:Cell>
</gnm:Cells>
<gnm:SheetLayout TopLeft="A1"/>
<gnm:Solver ModelType="0" ProblemType="0" MaxTime="60" MaxIter="1000" NonNeg="1" Discr="0" AutoScale="0" ProgramR="0"/>
</gnm:Sheet>
<gnm:Sheet DisplayFormulas="0" HideZero="0" HideGrid="0" HideColHeader="0" HideRowHeader="0" DisplayOutlines="1" OutlineSymbolsBelow="1" OutlineSymbolsRight="1" Visibility="GNM_SHEET_VISIBILITY_VISIBLE" GridColor="0:0:0">
<gnm:Name>Sheet2</gnm:Name>
<gnm:MaxCol>2</gnm:MaxCol>
<gnm:MaxRow>4</gnm:MaxRow>
<gnm:Zoom>1</gnm:Zoom>
<gnm:Names>
<gnm:Name>
<gnm:name>Print_Area</gnm:name>
<gnm:value>#REF!</gnm:value>
<gnm:position>A1</gnm:position>
</gnm:Name>
<gnm:Name>
<gnm:name>Sheet_Title</gnm:name>
<gnm:value>&quot;Sheet2&quot;</gnm:value>
<gnm:position>A1</gnm:position>
</gnm:Name>
</gnm:Names>
<gnm:PrintInformation>
<gnm:Margins>
<gnm:top Points="53.86" PrefUnit="mm"/>
<gnm:bottom Points="53.86" PrefUnit="mm"/>
<gnm:left Points="51.02" PrefUnit="mm"/>
<gnm:right Points="51.02" PrefUnit="mm"/>
<gnm:header Points="22.68" PrefUnit="mm"/>
<gnm:footer Points="22.68" PrefUnit="mm"/>
</gnm:Margins>
<gnm:Scale type="percentage" percentage="100"/>
<gnm:vcenter value="1"/>
<gnm:hcenter value="0"/>
<gnm:grid value="0"/>
<gnm:even_if_only_styles value="0"/>
<gnm:monochrome value="0"/>
<gnm:draft value="0"/>
<gnm:titles value="0"/>
<gnm:do_not_print value="0"/>
<gnm:print_range value="GNM_PRINT_ACTIVE_SHEET"/>
<gnm:order>r_then_d</gnm:order>
<gnm:orientation>landscape</gnm:orientation>
<gnm:Header Left="" Middle="&amp;[TAB]" Right=""/>
<gnm:Footer Left="" Middle="Page &amp;[PAGE]" Right=""/>
<gnm:paper>iso_a4</gnm:paper>
<gnm:comments placement="GNM_PRINT_COMMENTS_IN_PLACE"/>
<gnm:errors PrintErrorsAs="GNM_PRINT_ERRORS_AS_DISPLAYED"/>
</gnm:PrintInformation>
<gnm:Styles>
<gnm:StyleRegion startCol="0" startRow="0" endCol="16383" endRow="1048575">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="11" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Calibri</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
</gnm:Styles>
<gnm:Cols DefaultSizePts="48"/>
<gnm:Rows DefaultSizePts="14.25">
<gnm:RowInfo No="0" Unit="14.25" HardSize="1" Count="4"/>
</gnm:Rows>
<gnm:Selections CursorCol="0" CursorRow="0">
<gnm:Selection startCol="0" startRow="0" endCol="2" endRow="4"/>
</gnm:Selections>
<gnm:Cells>
<gnm:Cell Row="0" Col="0" ValueType="40">1</gnm:Cell>
<gnm:Cell Row="0" Col="1" ValueType="40">2</gnm:Cell>
<gnm:Cell Row="0" Col="2" ValueType="40">3</gnm:Cell>
<gnm:Cell Row="1" Col="0" ValueType="40">4</gnm:Cell>
<gnm:Cell Row="1" Col="1" ValueType="40">5</gnm:Cell>
<gnm:Cell Row="1" Col="2" ValueType="40">6</gnm:Cell>
<gnm:Cell Row="2" Col="0" ValueType="40">7</gnm:Cell>
<gnm:Cell Row="2" Col="1" ValueType="40">8</gnm:Cell>
<gnm:Cell Row="2" Col="2" ValueType="40">9</gnm:Cell>
<gnm:Cell Row="4" Col="0" ExprID="1">=sum($A$1:$C$1,$A$3:$C$3,$A$1:$A$3,$C$1:$C$3)</gnm:Cell>
<gnm:Cell Row="4" Col="1" ExprID="2">=count($A$1:$C$1,$A$3:$C$3,$A$1:$A$3,$C$1:$C$3)</gnm:Cell>
</gnm:Cells>
<gnm:SheetLayout TopLeft="A1"/>
<gnm:Solver ModelType="0" ProblemType="0" MaxTime="60" MaxIter="1000" NonNeg="1" Discr="0" AutoScale="0" ProgramR="0"/>
</gnm:Sheet>
<gnm:Sheet DisplayFormulas="0" HideZero="0" HideGrid="0" HideColHeader="0" HideRowHeader="0" DisplayOutlines="1" OutlineSymbolsBelow="1" OutlineSymbolsRight="1" Visibility="GNM_SHEET_VISIBILITY_VISIBLE" GridColor="0:0:0">
<gnm:Name>Sheet3</gnm:Name>
<gnm:MaxCol>2</gnm:MaxCol>
<gnm:MaxRow>4</gnm:MaxRow>
<gnm:Zoom>1</gnm:Zoom>
<gnm:Names>
<gnm:Name>
<gnm:name>Print_Area</gnm:name>
<gnm:value>Sheet3!$A$1:$C$5</gnm:value>
<gnm:position>A1</gnm:position>
</gnm:Name>
<gnm:Name>
<gnm:name>Sheet_Title</gnm:name>
<gnm:value>&quot;Sheet3&quot;</gnm:value>
<gnm:position>A1</gnm:position>
</gnm:Name>
</gnm:Names>
<gnm:PrintInformation>
<gnm:Margins>
<gnm:top Points="68.03" PrefUnit="mm"/>
<gnm:bottom Points="68.03" PrefUnit="mm"/>
<gnm:left Points="51.02" PrefUnit="mm"/>
<gnm:right Points="51.02" PrefUnit="mm"/>
<gnm:header Points="36.85" PrefUnit="mm"/>
<gnm:footer Points="36.85" PrefUnit="mm"/>
</gnm:Margins>
<gnm:Scale type="percentage" percentage="90"/>
<gnm:vcenter value="1"/>
<gnm:hcenter value="1"/>
<gnm:grid value="0"/>
<gnm:even_if_only_styles value="0"/>
<gnm:monochrome value="0"/>
<gnm:draft value="0"/>
<gnm:titles value="0"/>
<gnm:do_not_print value="0"/>
<gnm:print_range value="GNM_PRINT_ACTIVE_SHEET"/>
<gnm:order>d_then_r</gnm:order>
<gnm:orientation>portrait</gnm:orientation>
<gnm:Header Left="" Middle="&amp;[TAB]" Right=""/>
<gnm:Footer Left="" Middle="Page &amp;[PAGE]" Right=""/>
<gnm:paper>iso_a4</gnm:paper>
<gnm:comments placement="GNM_PRINT_COMMENTS_IN_PLACE"/>
<gnm:errors PrintErrorsAs="GNM_PRINT_ERRORS_AS_DISPLAYED"/>
</gnm:PrintInformation>
<gnm:Styles>
<gnm:StyleRegion startCol="0" startRow="0" endCol="16383" endRow="1048575">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="11" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Calibri</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
</gnm:Styles>
<gnm:Cols DefaultSizePts="48"/>
<gnm:Rows DefaultSizePts="14.25">
<gnm:RowInfo No="0" Unit="14.25" HardSize="1" Count="4"/>
</gnm:Rows>
<gnm:Selections CursorCol="0" CursorRow="0">
<gnm:Selection startCol="0" startRow="0" endCol="2" endRow="4"/>
</gnm:Selections>
<gnm:Cells>
<gnm:Cell Row="0" Col="0" ValueType="40">1</gnm:Cell>
<gnm:Cell Row="0" Col="1" ValueType="40">2</gnm:Cell>
<gnm:Cell Row="0" Col="2" ValueType="40">3</gnm:Cell>
<gnm:Cell Row="1" Col="0" ValueType="40">4</gnm:Cell>
<gnm:Cell Row="1" Col="1" ValueType="40">5</gnm:Cell>
<gnm:Cell Row="1" Col="2" ValueType="40">6</gnm:Cell>
<gnm:Cell Row="2" Col="0" ValueType="40">7</gnm:Cell>
<gnm:Cell Row="2" Col="1" ValueType="40">8</gnm:Cell>
<gnm:Cell Row="2" Col="2" ValueType="40">9</gnm:Cell>
<gnm:Cell Row="4" Col="0" ExprID="1"/>
<gnm:Cell Row="4" Col="1" ExprID="2"/>
</gnm:Cells>
<gnm:SheetLayout TopLeft="B2">
<gnm:FreezePanes FrozenTopLeft="A1" UnfrozenTopLeft="B2"/>
</gnm:SheetLayout>
<gnm:Solver ModelType="0" ProblemType="0" MaxTime="60" MaxIter="1000" NonNeg="1" Discr="0" AutoScale="0" ProgramR="0"/>
</gnm:Sheet>
<gnm:Sheet DisplayFormulas="0" HideZero="0" HideGrid="0" HideColHeader="0" HideRowHeader="0" DisplayOutlines="1" OutlineSymbolsBelow="1" OutlineSymbolsRight="1" Visibility="GNM_SHEET_VISIBILITY_VISIBLE" GridColor="0:0:0">
<gnm:Name>Sheet4</gnm:Name>
<gnm:MaxCol>2</gnm:MaxCol>
<gnm:MaxRow>4</gnm:MaxRow>
<gnm:Zoom>1</gnm:Zoom>
<gnm:Names>
<gnm:Name>
<gnm:name>Print_Area</gnm:name>
<gnm:value>#REF!</gnm:value>
<gnm:position>A1</gnm:position>
</gnm:Name>
<gnm:Name>
<gnm:name>Sheet_Title</gnm:name>
<gnm:value>&quot;Sheet4&quot;</gnm:value>
<gnm:position>A1</gnm:position>
</gnm:Name>
</gnm:Names>
<gnm:PrintInformation>
<gnm:Margins>
<gnm:top Points="54" PrefUnit="mm"/>
<gnm:bottom Points="54" PrefUnit="mm"/>
<gnm:left Points="50.4" PrefUnit="mm"/>
<gnm:right Points="50.4" PrefUnit="mm"/>
<gnm:header Points="21.6" PrefUnit="mm"/>
<gnm:footer Points="21.6" PrefUnit="mm"/>
</gnm:Margins>
<gnm:Scale type="percentage" percentage="100"/>
<gnm:vcenter value="0"/>
<gnm:hcenter value="0"/>
<gnm:grid value="0"/>
<gnm:even_if_only_styles value="0"/>
<gnm:monochrome value="0"/>
<gnm:draft value="0"/>
<gnm:titles value="0"/>
<gnm:do_not_print value="0"/>
<gnm:print_range value="GNM_PRINT_ACTIVE_SHEET"/>
<gnm:order>d_then_r</gnm:order>
<gnm:orientation>portrait</gnm:orientation>
<gnm:Header Left="" Middle="&amp;[TAB]" Right=""/>
<gnm:Footer Left="" Middle="Page &amp;[PAGE]" Right=""/>
<gnm:paper>iso_a4</gnm:paper>
<gnm:comments placement="GNM_PRINT_COMMENTS_IN_PLACE"/>
<gnm:errors PrintErrorsAs="GNM_PRINT_ERRORS_AS_DISPLAYED"/>
</gnm:PrintInformation>
<gnm:Styles>
<gnm:StyleRegion startCol="0" startRow="0" endCol="16383" endRow="1048575">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="11" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Calibri</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
</gnm:Styles>
<gnm:Cols DefaultSizePts="48"/>
<gnm:Rows DefaultSizePts="14.25"/>
<gnm:Selections CursorCol="0" CursorRow="0">
<gnm:Selection startCol="0" startRow="0" endCol="2" endRow="4"/>
</gnm:Selections>
<gnm:Cells>
<gnm:Cell Row="0" Col="0" ValueType="40">1</gnm:Cell>
<gnm:Cell Row="0" Col="1" ValueType="40">2</gnm:Cell>
<gnm:Cell Row="0" Col="2" ValueType="40">3</gnm:Cell>
<gnm:Cell Row="1" Col="0" ValueType="40">4</gnm:Cell>
<gnm:Cell Row="1" Col="1" ValueType="40">5</gnm:Cell>
<gnm:Cell Row="1" Col="2" ValueType="40">6</gnm:Cell>
<gnm:Cell Row="2" Col="0" ValueType="40">7</gnm:Cell>
<gnm:Cell Row="2" Col="1" ValueType="40">8</gnm:Cell>
<gnm:Cell Row="2" Col="2" ValueType="40">9</gnm:Cell>
<gnm:Cell Row="4" Col="0" ExprID="1"/>
<gnm:Cell Row="4" Col="1" ExprID="2"/>
</gnm:Cells>
<gnm:SheetLayout TopLeft="A1"/>
<gnm:Solver ModelType="0" ProblemType="0" MaxTime="60" MaxIter="1000" NonNeg="1" Discr="0" AutoScale="0" ProgramR="0"/>
</gnm:Sheet>
</gnm:Sheets>
<gnm:UIData SelectedTab="2"/>
</gnm:Workbook>