Kaydet (Commit) cc503abb authored tarafından Bartosz Kosiorek's avatar Bartosz Kosiorek Kaydeden (comit) Markus Mohrhard

tdf#100347 Fix Outline export into XLSX format

In previous XLSX export implementation the outline
for column was not saved. Also rows without cell content
was not saved if it was collapsed or outline level was set.
This commit resolve all such issues

Change-Id: I401f23e97f4803209fcd31c7d93baca3bd2a2385
Reviewed-on: https://gerrit.libreoffice.org/26625Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarMarkus Mohrhard <markus.mohrhard@googlemail.com>
üst 46094ff4
......@@ -110,6 +110,7 @@ public:
void testCellNoteExportXLS();
void testFormatExportODS();
void testOutlineExportXLSX();
void testHiddenEmptyRowsXLSX();
void testLandscapeOrientationXLSX();
......@@ -195,6 +196,8 @@ public:
CPPUNIT_TEST(testCellNoteExportODS);
CPPUNIT_TEST(testCellNoteExportXLS);
CPPUNIT_TEST(testFormatExportODS);
CPPUNIT_TEST(testOutlineExportXLSX);
CPPUNIT_TEST(testHiddenEmptyRowsXLSX);
CPPUNIT_TEST(testLandscapeOrientationXLSX);
CPPUNIT_TEST(testInlineArrayXLS);
......@@ -476,6 +479,84 @@ void ScExportTest::testFormatExportODS()
xDocSh->DoClose();
}
void ScExportTest::testOutlineExportXLSX()
{
//tdf#100347 FILESAVE FILEOPEN after exporting to xlsx format grouping are lost
ScDocShellRef xShell = loadDoc("outline.", FORMAT_ODS);
CPPUNIT_ASSERT(xShell.Is());
std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(&(*xShell), FORMAT_XLSX);
xmlDocPtr pSheet = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml");
CPPUNIT_ASSERT(pSheet);
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "outlineLevel", "1");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[1]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "outlineLevel", "2");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[2]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "hidden", "true");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "outlineLevel", "3");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[3]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "hidden", "true");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "outlineLevel", "4");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[4]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "hidden", "true");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "outlineLevel", "3");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[5]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[6]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[6]", "outlineLevel", "2");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[6]", "collapsed", "true");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[7]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[7]", "outlineLevel", "2");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[7]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[8]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[8]", "outlineLevel", "1");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[8]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[9]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[9]", "outlineLevel", "0");
assertXPath(pSheet, "/x:worksheet/x:cols/x:col[9]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "outlineLevel", "0");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[2]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[2]", "outlineLevel", "1");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[2]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[3]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[3]", "outlineLevel", "2");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[3]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]", "outlineLevel", "2");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[4]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[5]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[5]", "outlineLevel", "3");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[5]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[6]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[6]", "outlineLevel", "3");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[6]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[7]", "hidden", "true");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[7]", "outlineLevel", "4");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[7]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[8]", "hidden", "true");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[8]", "outlineLevel", "4");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[8]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[9]", "hidden", "true");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[9]", "outlineLevel", "4");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[9]", "collapsed", "false");
//next rows are the same as the previous one
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[21]", "hidden", "true");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[21]", "outlineLevel", "4");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[21]", "collapsed", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[22]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[22]", "outlineLevel", "3");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[22]", "collapsed", "true");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[23]", "hidden", "false");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[23]", "outlineLevel", "3");
assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[23]", "collapsed", "false");
}
void ScExportTest::testHiddenEmptyRowsXLSX()
{
//tdf#98106 FILESAVE: Hidden and empty rows became visible when export to .XLSX
......
......@@ -1578,6 +1578,7 @@ XclExpColinfo::XclExpColinfo( const XclExpRoot& rRoot,
mnWidth( 0 ),
mnScWidth( 0 ),
mnFlags( 0 ),
mnOutlineLevel( 0 ),
mnFirstXclCol( static_cast< sal_uInt16 >( nScCol ) ),
mnLastXclCol( static_cast< sal_uInt16 >( nScCol ) )
{
......@@ -1599,6 +1600,7 @@ XclExpColinfo::XclExpColinfo( const XclExpRoot& rRoot,
rOutlineBfr.Update( nScCol );
::set_flag( mnFlags, EXC_COLINFO_COLLAPSED, rOutlineBfr.IsCollapsed() );
::insert_value( mnFlags, rOutlineBfr.GetLevel(), 8, 3 );
mnOutlineLevel = rOutlineBfr.GetLevel();
}
void XclExpColinfo::ConvertXFIndexes()
......@@ -1651,9 +1653,9 @@ void XclExpColinfo::SaveXml( XclExpXmlStream& rStrm )
XML_collapsed, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_COLINFO_COLLAPSED ) ),
// OOXTODO: XML_customWidth,
XML_hidden, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_COLINFO_HIDDEN ) ),
XML_max, OString::number( (nLastXclCol+1) ).getStr(),
XML_min, OString::number( (mnFirstXclCol+1) ).getStr(),
// OOXTODO: XML_outlineLevel,
XML_outlineLevel, OString::number( mnOutlineLevel ).getStr(),
XML_max, OString::number( (nLastXclCol + 1) ).getStr(),
XML_min, OString::number( (mnFirstXclCol + 1) ).getStr(),
// OOXTODO: XML_phonetic,
XML_style, lcl_GetStyleId( rStrm, maXFId.mnXFIndex ).getStr(),
XML_width, OString::number( (double) (mnScWidth / (double)sc::TwipsToHMM( GetCharWidth() )) ).getStr(),
......@@ -1994,7 +1996,8 @@ sal_uInt16 XclExpRow::GetFirstFreeXclCol() const
bool XclExpRow::IsDefaultable() const
{
const sal_uInt16 nFlagsAlwaysMarkedAsDefault = EXC_ROW_DEFAULTFLAGS | EXC_ROW_UNSYNCED;
return !::get_flag( mnFlags, static_cast< sal_uInt16 >( ~nFlagsAlwaysMarkedAsDefault ) ) && IsEmpty();
return !::get_flag( mnFlags, static_cast< sal_uInt16 >( ~nFlagsAlwaysMarkedAsDefault ) ) &&
IsEmpty();
}
void XclExpRow::DisableIfDefault( const XclExpDefaultRowData& rDefRowData )
......@@ -2324,10 +2327,13 @@ XclExpRow& XclExpRowBuffer::GetOrCreateRow( sal_uInt32 nXclRow, bool bRowAlwaysE
itr = maRowMap.find(nFrom);
if ( itr == maRowMap.end() )
{
// only create RowMap entries for rows that differ from previous,
// the row is hidden (tdf#98106) or if it is the desired row
// only create RowMap entries if it is first row in spreadsheet,
// if it is the desired row, for rows that height differ from previous,
// if row is collapsed, has outline level (tdf#100347), or row is hidden (tdf#98106).
if ( !nFrom || ( nFrom == nXclRow ) ||
( rDoc.GetRowHeight(nFrom, nScTab, false) != rDoc.GetRowHeight(nFrom - 1, nScTab, false) ) ||
( maOutlineBfr.IsCollapsed() ) ||
( maOutlineBfr.GetLevel() != 0 ) ||
( rDoc.RowHidden(nFrom, nScTab) ) )
{
RowRef p(new XclExpRow(GetRoot(), nFrom, maOutlineBfr, bRowAlwaysEmpty));
......
......@@ -743,6 +743,7 @@ private:
sal_uInt16 mnWidth; /// Excel width of the column.
sal_uInt16 mnScWidth; /// Calc width of the column.
sal_uInt16 mnFlags; /// Additional column flags.
sal_uInt8 mnOutlineLevel; /// Outline Level of column (for OOXML)
sal_uInt16 mnFirstXclCol; /// Index to first column.
sal_uInt16 mnLastXclCol; /// Index to last column.
};
......@@ -894,7 +895,7 @@ private:
sal_uInt16 mnHeight; /// Row height in twips.
sal_uInt16 mnFlags; /// Flags for the ROW record.
sal_uInt16 mnXFIndex; /// Default row formatting.
sal_uInt16 mnOutlineLevel; /// Outline Level (for OOXML)
sal_uInt8 mnOutlineLevel; /// Outline Level of row (for OOXML)
sal_uInt32 mnXclRowRpt;
sal_uInt32 mnCurrentRow;
bool mbAlwaysEmpty; /// true = Do not add blank cells in Finalize().
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment