diff options
author | Oliver Bolte <obo@openoffice.org> | 2009-09-07 15:38:19 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2009-09-07 15:38:19 +0000 |
commit | fbeb3ce4a4fc1cf2a4a171709cfeb677971cf577 (patch) | |
tree | 0954231fafce7d5addb67820f28cbec4280820ee /sc/source/filter/xml | |
parent | 712e83090c793bd4a29ca77022e52d7fd82b70f7 (diff) |
CWS-TOOLING: integrate CWS calcsheetdata
2009-08-13 16:18:48 +0200 nn r274950 : #i102616# shared/remote files, better handling of formula results
2009-08-12 11:17:30 +0200 nn r274884 : CWS-TOOLING: rebase CWS calcsheetdata to trunk@274622 (milestone: DEV300:m54)
2009-08-12 10:30:47 +0200 nn r274881 : #i102616# some clean-up
2009-08-11 19:01:18 +0200 nn r274876 : #i102616# store loaded namespaces, so prefixes remain valid
2009-08-11 19:00:49 +0200 nn r274875 : #i102616# store loaded namespaces, so prefixes remain valid
2009-08-10 19:12:04 +0200 nn r274835 : #i102616# detective, notes, encoding, error handling
2009-08-07 11:18:46 +0200 nn r274751 : #i102616# use new method SvXMLAutoStylePoolP::AddNamed
2009-08-07 11:18:15 +0200 nn r274750 : #i102616# new method SvXMLAutoStylePoolP::AddNamed
2009-08-06 18:02:42 +0200 nn r274740 : #i102616# modification: shapes, notes, pending row heights; skip sheets in export iterator
2009-08-05 18:41:59 +0200 nn r274694 : #i102616# handle text styles in notes
2009-08-03 18:55:59 +0200 nn r274594 : #i102616# handle text styles in cells
2009-07-31 19:00:06 +0200 nn r274548 : #i102616# handle styles for notes
2009-07-28 16:46:20 +0200 nn r274414 : missed a conflict
2009-07-28 14:01:56 +0200 nn r274404 : CWS-TOOLING: rebase CWS calcsheetdata to trunk@274203 (milestone: DEV300:m53)
2009-07-23 18:28:47 +0200 nn r274278 : #i102616# handle table styles
2009-07-22 15:40:24 +0200 nn r274244 : #i102616# handle row styles
2009-07-21 20:09:37 +0200 nn r274211 : #i102616# handle column styles
2009-07-16 13:00:18 +0200 nn r274043 : #i102616# invalidate all stream positions when inserting/deleting sheets
2009-07-15 17:41:15 +0200 nn r274021 : #i102616# don't collect cell styles twice for copied sheets
2009-07-14 18:36:11 +0200 nn r273985 : #i102616# allow to query stream position, clear buffer
2009-07-14 18:32:10 +0200 nn r273984 : #i102616# allow to specify a name for an autostyle
2009-07-09 22:01:23 +0200 nn r273870 : #i102616# copy stream for unchanged sheets
2009-07-08 18:11:42 +0200 nn r273844 : #i102616# store stream positions of sheets
2009-06-24 19:08:18 +0200 nn r273363 : #i102616# detect changed sheets since loading
2009-06-09 15:53:32 +0200 nn r272774 : #i102616# store automatic cell style information after loading
Diffstat (limited to 'sc/source/filter/xml')
24 files changed, 1453 insertions, 221 deletions
diff --git a/sc/source/filter/xml/XMLExportIterator.cxx b/sc/source/filter/xml/XMLExportIterator.cxx index 72194c8be11c..c0b50a06b45a 100644 --- a/sc/source/filter/xml/XMLExportIterator.cxx +++ b/sc/source/filter/xml/XMLExportIterator.cxx @@ -130,6 +130,13 @@ void ScMyShapesContainer::SetCellData( ScMyCell& rMyCell ) rMyCell.bHasShape = !rMyCell.aShapeList.empty(); } +void ScMyShapesContainer::SkipTable(SCTAB nSkip) +{ + ScMyShapeList::iterator aItr = aShapeList.begin(); + while( (aItr != aShapeList.end()) && (aItr->aAddress.Tab() == nSkip) ) + aItr = aShapeList.erase(aItr); +} + void ScMyShapesContainer::Sort() { aShapeList.sort(); @@ -184,6 +191,13 @@ void ScMyNoteShapesContainer::SetCellData( ScMyCell& rMyCell ) } } +void ScMyNoteShapesContainer::SkipTable(SCTAB nSkip) +{ + ScMyNoteShapeList::iterator aItr = aNoteShapeList.begin(); + while( (aItr != aNoteShapeList.end()) && (aItr->aPos.Tab() == nSkip) ) + aItr = aNoteShapeList.erase(aItr); +} + void ScMyNoteShapesContainer::Sort() { aNoteShapeList.sort(); @@ -269,6 +283,13 @@ void ScMyMergedRangesContainer::SetCellData( ScMyCell& rMyCell ) } } +void ScMyMergedRangesContainer::SkipTable(SCTAB nSkip) +{ + ScMyMergedRangeList::iterator aItr = aRangeList.begin(); + while( (aItr != aRangeList.end()) && (aItr->aCellRange.Sheet == nSkip) ) + aItr = aRangeList.erase(aItr); +} + void ScMyMergedRangesContainer::Sort() { aRangeList.sort(); @@ -344,6 +365,13 @@ void ScMyAreaLinksContainer::SetCellData( ScMyCell& rMyCell ) } } +void ScMyAreaLinksContainer::SkipTable(SCTAB nSkip) +{ + ScMyAreaLinkList::iterator aItr = aAreaLinkList.begin(); + while( (aItr != aAreaLinkList.end()) && (aItr->aDestRange.Sheet == nSkip) ) + aItr = aAreaLinkList.erase(aItr); +} + void ScMyAreaLinksContainer::Sort() { aAreaLinkList.sort(); @@ -417,6 +445,13 @@ void ScMyEmptyDatabaseRangesContainer::SetCellData( ScMyCell& rMyCell ) } } +void ScMyEmptyDatabaseRangesContainer::SkipTable(SCTAB nSkip) +{ + ScMyEmptyDatabaseRangeList::iterator aItr = aDatabaseList.begin(); + while( (aItr != aDatabaseList.end()) && (aItr->Sheet == nSkip) ) + aItr = aDatabaseList.erase(aItr); +} + void ScMyEmptyDatabaseRangesContainer::Sort() { aDatabaseList.sort(); @@ -498,6 +533,13 @@ void ScMyDetectiveObjContainer::SetCellData( ScMyCell& rMyCell ) rMyCell.bHasDetectiveObj = (rMyCell.aDetectiveObjVec.size() != 0); } +void ScMyDetectiveObjContainer::SkipTable(SCTAB nSkip) +{ + ScMyDetectiveObjList::iterator aItr = aDetectiveObjList.begin(); + while( (aItr != aDetectiveObjList.end()) && (aItr->aPosition.Sheet == nSkip) ) + aItr = aDetectiveObjList.erase(aItr); +} + void ScMyDetectiveObjContainer::Sort() { aDetectiveObjList.sort(); @@ -557,6 +599,13 @@ void ScMyDetectiveOpContainer::SetCellData( ScMyCell& rMyCell ) rMyCell.bHasDetectiveOp = (rMyCell.aDetectiveOpVec.size() != 0); } +void ScMyDetectiveOpContainer::SkipTable(SCTAB nSkip) +{ + ScMyDetectiveOpList::iterator aItr = aDetectiveOpList.begin(); + while( (aItr != aDetectiveOpList.end()) && (aItr->aPosition.Sheet == nSkip) ) + aItr = aDetectiveOpList.erase(aItr); +} + void ScMyDetectiveOpContainer::Sort() { aDetectiveOpList.sort(); @@ -766,6 +815,27 @@ void ScMyNotEmptyCellsIterator::SetCurrentTable(const SCTAB nTable, } } +void ScMyNotEmptyCellsIterator::SkipTable(SCTAB nSkip) +{ + // Skip entries for a sheet that is copied instead of saving normally. + // Cells (including aAnnotations) are handled separately in SetCurrentTable. + + if( pShapes ) + pShapes->SkipTable(nSkip); + if( pNoteShapes ) + pNoteShapes->SkipTable(nSkip); + if( pEmptyDatabaseRanges ) + pEmptyDatabaseRanges->SkipTable(nSkip); + if( pMergedRanges ) + pMergedRanges->SkipTable(nSkip); + if( pAreaLinks ) + pAreaLinks->SkipTable(nSkip); + if( pDetectiveObj ) + pDetectiveObj->SkipTable(nSkip); + if( pDetectiveOp ) + pDetectiveOp->SkipTable(nSkip); +} + sal_Bool ScMyNotEmptyCellsIterator::GetNext(ScMyCell& aCell, ScFormatRangeStyles* pCellStyles) { table::CellAddress aAddress( nCurrentTable, MAXCOL + 1, MAXROW + 1 ); diff --git a/sc/source/filter/xml/XMLExportIterator.hxx b/sc/source/filter/xml/XMLExportIterator.hxx index d15ef94f99e6..92c61ca060e9 100644 --- a/sc/source/filter/xml/XMLExportIterator.hxx +++ b/sc/source/filter/xml/XMLExportIterator.hxx @@ -96,6 +96,7 @@ public: const ScMyShapeList* GetShapes() { return &aShapeList; } virtual void SetCellData( ScMyCell& rMyCell ); virtual void Sort(); + void SkipTable(SCTAB nSkip); }; struct ScMyNoteShape @@ -124,6 +125,7 @@ public: const ScMyNoteShapeList* GetNotes() { return &aNoteShapeList; } virtual void SetCellData( ScMyCell& rMyCell ); virtual void Sort(); + void SkipTable(SCTAB nSkip); }; //============================================================================== @@ -152,6 +154,7 @@ public: using ScMyIteratorBase::UpdateAddress; virtual void SetCellData( ScMyCell& rMyCell ); virtual void Sort(); // + remove doublets + void SkipTable(SCTAB nSkip); }; //============================================================================== @@ -192,6 +195,7 @@ public: using ScMyIteratorBase::UpdateAddress; virtual void SetCellData( ScMyCell& rMyCell ); virtual void Sort(); + void SkipTable(SCTAB nSkip); }; //============================================================================== @@ -218,6 +222,7 @@ public: using ScMyIteratorBase::UpdateAddress; virtual void SetCellData( ScMyCell& rMyCell ); virtual void Sort(); + void SkipTable(SCTAB nSkip); }; //============================================================================== @@ -254,6 +259,7 @@ public: using ScMyIteratorBase::UpdateAddress; virtual void SetCellData( ScMyCell& rMyCell ); virtual void Sort(); + void SkipTable(SCTAB nSkip); }; //============================================================================== @@ -284,6 +290,7 @@ public: using ScMyIteratorBase::UpdateAddress; virtual void SetCellData( ScMyCell& rMyCell ); virtual void Sort(); + void SkipTable(SCTAB nSkip); }; //============================================================================== @@ -400,6 +407,7 @@ public: void SetCurrentTable(const SCTAB nTable, com::sun::star::uno::Reference<com::sun::star::sheet::XSpreadsheet>& rxTable); + void SkipTable(SCTAB nSkip); sal_Bool GetNext(ScMyCell& aCell, ScFormatRangeStyles* pCellStyles); }; diff --git a/sc/source/filter/xml/XMLStylesExportHelper.cxx b/sc/source/filter/xml/XMLStylesExportHelper.cxx index 6482fe571b62..98100f4b3646 100644 --- a/sc/source/filter/xml/XMLStylesExportHelper.cxx +++ b/sc/source/filter/xml/XMLStylesExportHelper.cxx @@ -878,7 +878,7 @@ sal_Int32 ScFormatRangeStyles::GetIndexOfStyleName(const rtl::OUString& rString, sal_Int32 nPrefixLength(rPrefix.getLength()); rtl::OUString sTemp(rString.copy(nPrefixLength)); sal_Int32 nIndex(sTemp.toInt32()); - if (aAutoStyleNames.at(nIndex - 1)->equals(rString)) + if (nIndex > 0 && static_cast<size_t>(nIndex-1) < aAutoStyleNames.size() && aAutoStyleNames.at(nIndex - 1)->equals(rString)) { bIsAutoStyle = sal_True; return nIndex - 1; @@ -1111,7 +1111,7 @@ sal_Int32 ScColumnRowStylesBase::GetIndexOfStyleName(const rtl::OUString& rStrin sal_Int32 nPrefixLength(rPrefix.getLength()); rtl::OUString sTemp(rString.copy(nPrefixLength)); sal_Int32 nIndex(sTemp.toInt32()); - if (aStyleNames.at(nIndex - 1)->equals(rString)) + if (nIndex > 0 && static_cast<size_t>(nIndex-1) < aStyleNames.size() && aStyleNames.at(nIndex - 1)->equals(rString)) return nIndex - 1; else { diff --git a/sc/source/filter/xml/XMLTableShapeImportHelper.cxx b/sc/source/filter/xml/XMLTableShapeImportHelper.cxx index 48def752b038..f498faf93e5b 100644 --- a/sc/source/filter/xml/XMLTableShapeImportHelper.cxx +++ b/sc/source/filter/xml/XMLTableShapeImportHelper.cxx @@ -36,6 +36,8 @@ #include "drwlayer.hxx" #include "xmlannoi.hxx" #include "rangeutl.hxx" +#include "docuno.hxx" +#include "sheetdata.hxx" #include <xmloff/nmspmap.hxx> #include <xmloff/xmlnmspe.hxx> #include <xmloff/xmluconv.hxx> @@ -80,9 +82,11 @@ void XMLTableShapeImportHelper::finishShape( const uno::Reference< xml::sax::XAttributeList >& xAttrList, uno::Reference< drawing::XShapes >& rShapes ) { + bool bNote = false; XMLShapeImportHelper::finishShape( rShape, xAttrList, rShapes ); static_cast<ScXMLImport&>(mrImporter).LockSolarMutex(); - if (rShapes == static_cast<ScXMLImport&>(mrImporter).GetTables().GetCurrentXShapes()) + ScMyTables& rTables = static_cast<ScXMLImport&>(mrImporter).GetTables(); + if (rShapes == rTables.GetCurrentXShapes()) { if (!pAnnotationContext) { @@ -126,7 +130,7 @@ void XMLTableShapeImportHelper::finishShape( if (!bOnTable) { - static_cast<ScXMLImport&>(mrImporter).GetTables().AddShape(rShape, + rTables.AddShape(rShape, pRangeList, aStartCell, aEndCell, nEndX, nEndY); SvxShape* pShapeImp = SvxShape::getImplementation(rShape); if (pShapeImp) @@ -145,7 +149,7 @@ void XMLTableShapeImportHelper::finishShape( // -> call AddShape with invalid cell position (checked in ScMyShapeResizer::ResizeShapes) table::CellAddress aInvalidPos( -1, -1, -1 ); - static_cast<ScXMLImport&>(mrImporter).GetTables().AddShape(rShape, + rTables.AddShape(rShape, pRangeList, aInvalidPos, aInvalidPos, 0, 0); } @@ -160,7 +164,26 @@ void XMLTableShapeImportHelper::finishShape( } else // shape is annotation { - pAnnotationContext->SetShape(rShape, rShapes); + // get the style names for stream copying + rtl::OUString aStyleName; + rtl::OUString aTextStyle; + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; ++i ) + { + const rtl::OUString& rAttrName(xAttrList->getNameByIndex( i )); + rtl::OUString aLocalName; + sal_uInt16 nPrefix(static_cast<ScXMLImport&>(mrImporter).GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName )); + if(nPrefix == XML_NAMESPACE_DRAW) + { + if (IsXMLToken(aLocalName, XML_STYLE_NAME)) + aStyleName = xAttrList->getValueByIndex( i ); + else if (IsXMLToken(aLocalName, XML_TEXT_STYLE_NAME)) + aTextStyle = xAttrList->getValueByIndex( i ); + } + } + + pAnnotationContext->SetShape(rShape, rShapes, aStyleName, aTextStyle); + bNote = true; } } else //#99532# this are grouped shapes which should also get the layerid @@ -183,5 +206,13 @@ void XMLTableShapeImportHelper::finishShape( } SetLayer(rShape, nLayerID, rShape->getShapeType()); } + + if (!bNote) + { + // any shape other than a note prevents copying the sheet + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(mrImporter.GetModel())->GetSheetSaveData(); + pSheetData->BlockSheet( rTables.GetCurrentSheet() ); + } + static_cast<ScXMLImport&>(mrImporter).UnlockSolarMutex(); } diff --git a/sc/source/filter/xml/XMLTableShapeImportHelper.hxx b/sc/source/filter/xml/XMLTableShapeImportHelper.hxx index 4299649427e4..06d49dc4beed 100644 --- a/sc/source/filter/xml/XMLTableShapeImportHelper.hxx +++ b/sc/source/filter/xml/XMLTableShapeImportHelper.hxx @@ -57,6 +57,8 @@ public: void SetCell (const ::com::sun::star::table::CellAddress& rAddress) { aStartCell = rAddress; } void SetOnTable (const sal_Bool bTempOnTable) { bOnTable = bTempOnTable; } void SetAnnotation(ScXMLAnnotationContext* pAnnotation) { pAnnotationContext = pAnnotation; } + + ScXMLAnnotationContext* GetAnnotationContext() const { return pAnnotationContext; } }; diff --git a/sc/source/filter/xml/makefile.mk b/sc/source/filter/xml/makefile.mk index 19d8a99f789c..c1e7e215e199 100644 --- a/sc/source/filter/xml/makefile.mk +++ b/sc/source/filter/xml/makefile.mk @@ -51,57 +51,8 @@ PROJECTPCHSOURCE=..\pch\filt_pch # --- Files -------------------------------------------------------- -CXXFILES = \ - xmlwrap.cxx \ - xmlimprt.cxx \ - xmlexprt.cxx \ - xmlbodyi.cxx \ - xmltabi.cxx \ - xmlexternaltabi.cxx \ - xmlrowi.cxx \ - xmlcelli.cxx \ - xmlconti.cxx \ - xmlcoli.cxx \ - xmlsubti.cxx \ - xmlnexpi.cxx \ - xmldrani.cxx \ - xmlfilti.cxx \ - xmlsorti.cxx \ - xmlstyle.cxx \ - xmlstyli.cxx \ - xmldpimp.cxx \ - xmlannoi.cxx \ - xmlsceni.cxx \ - xmlcvali.cxx \ - XMLTableMasterPageExport.cxx \ - xmllabri.cxx \ - XMLTableHeaderFooterContext.cxx \ - XMLDetectiveContext.cxx \ - XMLCellRangeSourceContext.cxx \ - XMLConsolidationContext.cxx \ - XMLConverter.cxx \ - XMLExportIterator.cxx \ - XMLColumnRowGroupExport.cxx \ - XMLStylesExportHelper.cxx \ - XMLStylesImportHelper.cxx \ - XMLExportDataPilot.cxx \ - XMLExportDatabaseRanges.cxx \ - XMLTableShapeImportHelper.cxx \ - XMLTableShapesContext.cxx \ - XMLExportDDELinks.cxx \ - XMLDDELinksContext.cxx \ - XMLCalculationSettingsContext.cxx \ - XMLTableSourceContext.cxx \ - XMLTextPContext.cxx \ - XMLTableShapeResizer.cxx \ - XMLChangeTrackingExportHelper.cxx \ - xmlfonte.cxx \ - XMLChangeTrackingImportHelper.cxx \ - XMLTrackedChangesContext.cxx \ - XMLExportSharedData.cxx \ - XMLEmptyContext.cxx - SLOFILES = \ + $(SLO)$/sheetdata.obj \ $(SLO)$/xmlwrap.obj \ $(SLO)$/xmlimprt.obj \ $(SLO)$/xmlexprt.obj \ diff --git a/sc/source/filter/xml/sheetdata.cxx b/sc/source/filter/xml/sheetdata.cxx new file mode 100644 index 000000000000..a8b96eb6d768 --- /dev/null +++ b/sc/source/filter/xml/sheetdata.cxx @@ -0,0 +1,275 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sheetdata.cxx,v $ + * $Revision: 1.69.32.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include <xmloff/families.hxx> +#include <xmloff/xmlaustp.hxx> +#include <xmloff/nmspmap.hxx> +#include <tools/string.hxx> +#include <tools/debug.hxx> + +#include "sheetdata.hxx" + +// ----------------------------------------------------------------------- + +ScSheetSaveData::ScSheetSaveData() : + mnStartTab( -1 ), + mnStartOffset( -1 ), + maPreviousNote( rtl::OUString(), rtl::OUString(), ScAddress(ScAddress::INITIALIZE_INVALID) ) +{ +} + +ScSheetSaveData::~ScSheetSaveData() +{ +} + +void ScSheetSaveData::AddCellStyle( const rtl::OUString& rName, const ScAddress& rCellPos ) +{ + maCellStyles.push_back( ScCellStyleEntry( rName, rCellPos ) ); +} + +void ScSheetSaveData::AddColumnStyle( const rtl::OUString& rName, const ScAddress& rCellPos ) +{ + maColumnStyles.push_back( ScCellStyleEntry( rName, rCellPos ) ); +} + +void ScSheetSaveData::AddRowStyle( const rtl::OUString& rName, const ScAddress& rCellPos ) +{ + maRowStyles.push_back( ScCellStyleEntry( rName, rCellPos ) ); +} + +void ScSheetSaveData::AddTableStyle( const rtl::OUString& rName, const ScAddress& rCellPos ) +{ + maTableStyles.push_back( ScCellStyleEntry( rName, rCellPos ) ); +} + +void ScSheetSaveData::HandleNoteStyles( const rtl::OUString& rStyleName, const rtl::OUString& rTextName, const ScAddress& rCellPos ) +{ + // only consecutive duplicates (most common case) are filtered out here, + // the others are found when the styles are created + + if ( rStyleName == maPreviousNote.maStyleName && + rTextName == maPreviousNote.maTextStyle && + rCellPos.Tab() == maPreviousNote.maCellPos.Tab() ) + { + // already stored for the same sheet - ignore + return; + } + + ScNoteStyleEntry aNewEntry( rStyleName, rTextName, rCellPos ); + maPreviousNote = aNewEntry; + maNoteStyles.push_back( aNewEntry ); +} + +void ScSheetSaveData::AddNoteContentStyle( sal_uInt16 nFamily, const rtl::OUString& rName, const ScAddress& rCellPos, const ESelection& rSelection ) +{ + if ( nFamily == XML_STYLE_FAMILY_TEXT_PARAGRAPH ) + maNoteParaStyles.push_back( ScTextStyleEntry( rName, rCellPos, rSelection ) ); + else + maNoteTextStyles.push_back( ScTextStyleEntry( rName, rCellPos, rSelection ) ); +} + +void ScSheetSaveData::AddTextStyle( const rtl::OUString& rName, const ScAddress& rCellPos, const ESelection& rSelection ) +{ + maTextStyles.push_back( ScTextStyleEntry( rName, rCellPos, rSelection ) ); +} + +void ScSheetSaveData::BlockSheet( sal_Int32 nTab ) +{ + if ( nTab >= (sal_Int32)maBlocked.size() ) + maBlocked.resize( nTab + 1, false ); // fill vector with "false" entries + + maBlocked[nTab] = true; +} + +bool ScSheetSaveData::IsSheetBlocked( sal_Int32 nTab ) const +{ + if ( nTab < (sal_Int32)maBlocked.size() ) + return maBlocked[nTab]; + else + return false; +} + +void ScSheetSaveData::AddStreamPos( sal_Int32 nTab, sal_Int32 nStartOffset, sal_Int32 nEndOffset ) +{ + if ( nTab >= (sal_Int32)maStreamEntries.size() ) + maStreamEntries.resize( nTab + 1 ); + + maStreamEntries[nTab] = ScStreamEntry( nStartOffset, nEndOffset ); +} + +void ScSheetSaveData::StartStreamPos( sal_Int32 nTab, sal_Int32 nStartOffset ) +{ + DBG_ASSERT( mnStartTab < 0, "StartStreamPos without EndStreamPos" ); + + mnStartTab = nTab; + mnStartOffset = nStartOffset; +} + +void ScSheetSaveData::EndStreamPos( sal_Int32 nEndOffset ) +{ + if ( mnStartTab >= 0 ) + { + AddStreamPos( mnStartTab, mnStartOffset, nEndOffset ); + mnStartTab = -1; + mnStartOffset = -1; + } +} + +void ScSheetSaveData::GetStreamPos( sal_Int32 nTab, sal_Int32& rStartOffset, sal_Int32& rEndOffset ) const +{ + if ( nTab < (sal_Int32)maStreamEntries.size() ) + { + const ScStreamEntry& rEntry = maStreamEntries[nTab]; + rStartOffset = rEntry.mnStartOffset; + rEndOffset = rEntry.mnEndOffset; + } + else + rStartOffset = rEndOffset = -1; +} + +bool ScSheetSaveData::HasStreamPos( sal_Int32 nTab ) const +{ + sal_Int32 nStartOffset = -1; + sal_Int32 nEndOffset = -1; + GetStreamPos( nTab, nStartOffset, nEndOffset ); + return ( nStartOffset >= 0 && nEndOffset >= 0 ); +} + +void ScSheetSaveData::ResetSaveEntries() +{ + maSaveEntries.clear(); +} + +void ScSheetSaveData::AddSavePos( sal_Int32 nTab, sal_Int32 nStartOffset, sal_Int32 nEndOffset ) +{ + if ( nTab >= (sal_Int32)maSaveEntries.size() ) + maSaveEntries.resize( nTab + 1 ); + + maSaveEntries[nTab] = ScStreamEntry( nStartOffset, nEndOffset ); +} + +void ScSheetSaveData::UseSaveEntries() +{ + maStreamEntries = maSaveEntries; +} + +void ScSheetSaveData::StoreInitialNamespaces( const SvXMLNamespaceMap& rNamespaces ) +{ + // the initial namespaces are just removed from the list of loaded namespaces, + // so only a hash_set of the prefixes is needed. + + const NameSpaceHash& rNameHash = rNamespaces.GetAllEntries(); + NameSpaceHash::const_iterator aIter = rNameHash.begin(), aEnd = rNameHash.end(); + while (aIter != aEnd) + { + maInitialPrefixes.insert( aIter->first ); + ++aIter; + } +} + +void ScSheetSaveData::StoreLoadedNamespaces( const SvXMLNamespaceMap& rNamespaces ) +{ + // store the loaded namespaces, so the prefixes in copied stream fragments remain valid + + const NameSpaceHash& rNameHash = rNamespaces.GetAllEntries(); + NameSpaceHash::const_iterator aIter = rNameHash.begin(), aEnd = rNameHash.end(); + while (aIter != aEnd) + { + // ignore the initial namespaces + if ( maInitialPrefixes.find( aIter->first ) == maInitialPrefixes.end() ) + { + const NameSpaceEntry& rEntry = aIter->second.getBody(); + maLoadedNamespaces.push_back( ScLoadedNamespaceEntry( rEntry.sPrefix, rEntry.sName, rEntry.nKey ) ); + } + ++aIter; + } +} + +bool lcl_NameInHash( const NameSpaceHash& rNameHash, const rtl::OUString& rName ) +{ + NameSpaceHash::const_iterator aIter = rNameHash.begin(), aEnd = rNameHash.end(); + while (aIter != aEnd) + { + if ( aIter->second->sName == rName ) + return true; + + ++aIter; + } + return false; // not found +} + +bool ScSheetSaveData::AddLoadedNamespaces( SvXMLNamespaceMap& rNamespaces ) const +{ + // Add the loaded namespaces to the name space map. + + // first loop: only look for conflicts + // (if the loaded namespaces were added first, this might not be necessary) + const NameSpaceHash& rNameHash = rNamespaces.GetAllEntries(); + std::vector<ScLoadedNamespaceEntry>::const_iterator aIter = maLoadedNamespaces.begin(); + std::vector<ScLoadedNamespaceEntry>::const_iterator aEnd = maLoadedNamespaces.end(); + while (aIter != aEnd) + { + NameSpaceHash::const_iterator aHashIter = rNameHash.find( aIter->maPrefix ); + if ( aHashIter == rNameHash.end() ) + { + if ( lcl_NameInHash( rNameHash, aIter->maName ) ) + { + // a second prefix for the same name would confuse SvXMLNamespaceMap lookup, + // so this is also considered a conflict + return false; + } + } + else if ( aHashIter->second->sName != aIter->maName ) + { + // same prefix, but different name: loaded namespaces can't be used + return false; + } + ++aIter; + } + + // only if there were no conflicts, add the entries that aren't in the map already + // (the key is needed if the same namespace is added later within an element) + aIter = maLoadedNamespaces.begin(); + while (aIter != aEnd) + { + NameSpaceHash::const_iterator aHashIter = rNameHash.find( aIter->maPrefix ); + if ( aHashIter == rNameHash.end() ) + rNamespaces.Add( aIter->maPrefix, aIter->maName, aIter->mnKey ); + ++aIter; + } + + return true; // success +} + diff --git a/sc/source/filter/xml/xmlannoi.cxx b/sc/source/filter/xml/xmlannoi.cxx index f8081b7b8f48..294a335033c1 100644 --- a/sc/source/filter/xml/xmlannoi.cxx +++ b/sc/source/filter/xml/xmlannoi.cxx @@ -207,9 +207,17 @@ void ScXMLAnnotationContext::EndElement() pTableShapeImport->SetAnnotation(NULL); } -void ScXMLAnnotationContext::SetShape( const uno::Reference< drawing::XShape >& rxShape, const uno::Reference< drawing::XShapes >& rxShapes ) +void ScXMLAnnotationContext::SetShape( const uno::Reference< drawing::XShape >& rxShape, const uno::Reference< drawing::XShapes >& rxShapes, + const rtl::OUString& rStyleName, const rtl::OUString& rTextStyle ) { mrAnnotationData.mxShape = rxShape; mrAnnotationData.mxShapes = rxShapes; + mrAnnotationData.maStyleName = rStyleName; + mrAnnotationData.maTextStyle = rTextStyle; +} + +void ScXMLAnnotationContext::AddContentStyle( sal_uInt16 nFamily, const rtl::OUString& rName, const ESelection& rSelection ) +{ + mrAnnotationData.maContentStyles.push_back( ScXMLAnnotationStyleEntry( nFamily, rName, rSelection ) ); } diff --git a/sc/source/filter/xml/xmlannoi.hxx b/sc/source/filter/xml/xmlannoi.hxx index c509b72124ed..41b206bd4380 100644 --- a/sc/source/filter/xml/xmlannoi.hxx +++ b/sc/source/filter/xml/xmlannoi.hxx @@ -34,12 +34,27 @@ #include <xmloff/xmlictxt.hxx> #include <xmloff/xmlimp.hxx> #include <rtl/ustrbuf.hxx> +#include <svx/editdata.hxx> #include <com/sun/star/drawing/XShape.hpp> #include <com/sun/star/drawing/XShapes.hpp> class ScXMLImport; class ScXMLTableRowCellContext; +struct ScXMLAnnotationStyleEntry +{ + sal_uInt16 mnFamily; + rtl::OUString maName; + ESelection maSelection; + + ScXMLAnnotationStyleEntry( sal_uInt16 nFam, const rtl::OUString& rNam, const ESelection& rSel ) : + mnFamily( nFam ), + maName( rNam ), + maSelection( rSel ) + { + } +}; + struct ScXMLAnnotationData { ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > @@ -49,8 +64,11 @@ struct ScXMLAnnotationData ::rtl::OUString maAuthor; ::rtl::OUString maCreateDate; ::rtl::OUString maSimpleText; + ::rtl::OUString maStyleName; + ::rtl::OUString maTextStyle; bool mbUseShapePos; bool mbShown; + std::vector<ScXMLAnnotationStyleEntry> maContentStyles; explicit ScXMLAnnotationData(); ~ScXMLAnnotationData(); @@ -82,7 +100,10 @@ public: void SetShape( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& rxShape, - const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes ); + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::rtl::OUString& rStyleName, const ::rtl::OUString& rTextStyle ); + + void AddContentStyle( sal_uInt16 nFamily, const rtl::OUString& rName, const ESelection& rSelection ); private: ScXMLAnnotationData& mrAnnotationData; diff --git a/sc/source/filter/xml/xmlbodyi.cxx b/sc/source/filter/xml/xmlbodyi.cxx index 048f1ec0c549..a301ddbf27e6 100644 --- a/sc/source/filter/xml/xmlbodyi.cxx +++ b/sc/source/filter/xml/xmlbodyi.cxx @@ -36,6 +36,8 @@ #include <cstdio> #include "document.hxx" +#include "docuno.hxx" +#include "sheetdata.hxx" #include "xmlbodyi.hxx" #include "xmltabi.hxx" @@ -136,6 +138,14 @@ SvXMLImportContext *ScXMLBodyContext::CreateChildContext( USHORT nPrefix, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList>& xAttrList ) { + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetScImport().GetModel())->GetSheetSaveData(); + if ( pSheetData && pSheetData->HasStartPos() ) + { + // stream part to copy ends before the next child element + sal_Int32 nEndOffset = GetScImport().GetByteOffset(); + pSheetData->EndStreamPos( nEndOffset ); + } + SvXMLImportContext *pContext = 0; const SvXMLTokenMap& rTokenMap = GetScImport().GetBodyElemTokenMap(); @@ -218,8 +228,36 @@ SvXMLImportContext *ScXMLBodyContext::CreateChildContext( USHORT nPrefix, return pContext; } +void ScXMLBodyContext::Characters( const OUString& ) +{ + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetScImport().GetModel())->GetSheetSaveData(); + if ( pSheetData && pSheetData->HasStartPos() ) + { + // stream part to copy ends before any content (whitespace) within the spreadsheet element + sal_Int32 nEndOffset = GetScImport().GetByteOffset(); + pSheetData->EndStreamPos( nEndOffset ); + } + // otherwise ignore +} + void ScXMLBodyContext::EndElement() { + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetScImport().GetModel())->GetSheetSaveData(); + if ( pSheetData && pSheetData->HasStartPos() ) + { + // stream part to copy ends before the closing tag of spreadsheet element + sal_Int32 nEndOffset = GetScImport().GetByteOffset(); + pSheetData->EndStreamPos( nEndOffset ); + } + + if ( pSheetData ) + { + // store the loaded namespaces (for the office:spreadsheet element), + // so the prefixes in copied stream fragments remain valid + const SvXMLNamespaceMap& rNamespaces = GetImport().GetNamespaceMap(); + pSheetData->StoreLoadedNamespaces( rNamespaces ); + } + if (!bHadCalculationSettings) { // #111055#; set calculation settings defaults if there is no calculation settings element diff --git a/sc/source/filter/xml/xmlbodyi.hxx b/sc/source/filter/xml/xmlbodyi.hxx index d57af40eaf25..2c489418bfff 100644 --- a/sc/source/filter/xml/xmlbodyi.hxx +++ b/sc/source/filter/xml/xmlbodyi.hxx @@ -57,6 +57,7 @@ public: const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); virtual void EndElement(); + virtual void Characters( const ::rtl::OUString& rChars ); }; #endif diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx index f0a4569cc86e..6a42d505cdc8 100644 --- a/sc/source/filter/xml/xmlcelli.cxx +++ b/sc/source/filter/xml/xmlcelli.cxx @@ -44,6 +44,7 @@ #include "docuno.hxx" #include "unonames.hxx" #include "postit.hxx" +#include "sheetdata.hxx" #include "XMLTableShapeImportHelper.hxx" #include "XMLTextPContext.hxx" @@ -550,6 +551,11 @@ void ScXMLTableRowCellContext::SetContentValidation(com::sun::star::uno::Referen } } xPropSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_VALIXML)), uno::makeAny(xPropertySet)); + + // For now, any sheet with validity is blocked from stream-copying. + // Later, the validation names could be stored along with the style names. + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetImport().GetModel())->GetSheetSaveData(); + pSheetData->BlockSheet( GetScImport().GetTables().GetCurrentSheet() ); } } } @@ -676,6 +682,18 @@ void ScXMLTableRowCellContext::SetAnnotation(const table::CellAddress& aCellAddr uno::Reference< drawing::XShape > xShape; rXMLImport.GetShapeImport()->shapeWithZIndexAdded( xShape, xShapesIA->getCount() ); } + + // store the style names for stream copying + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rXMLImport.GetModel())->GetSheetSaveData(); + pSheetData->HandleNoteStyles( mxAnnotationData->maStyleName, mxAnnotationData->maTextStyle, aPos ); + + std::vector<ScXMLAnnotationStyleEntry>::const_iterator aIter = mxAnnotationData->maContentStyles.begin(); + std::vector<ScXMLAnnotationStyleEntry>::const_iterator aEnd = mxAnnotationData->maContentStyles.end(); + while (aIter != aEnd) + { + pSheetData->AddNoteContentStyle( aIter->mnFamily, aIter->maName, aPos, aIter->maSelection ); + ++aIter; + } } // core implementation diff --git a/sc/source/filter/xml/xmlcoli.cxx b/sc/source/filter/xml/xmlcoli.cxx index 31662f4e68dd..73c06f23a7bf 100644 --- a/sc/source/filter/xml/xmlcoli.cxx +++ b/sc/source/filter/xml/xmlcoli.cxx @@ -42,6 +42,7 @@ #include "document.hxx" #include "docuno.hxx" #include "olinetab.hxx" +#include "sheetdata.hxx" #include "unonames.hxx" #include <xmloff/xmltkmap.hxx> @@ -145,7 +146,7 @@ SvXMLImportContext *ScXMLTableColContext::CreateChildContext( USHORT nPrefix, void ScXMLTableColContext::EndElement() { ScXMLImport& rXMLImport = GetScImport(); - //sal_Int32 nSheet = rXMLImport.GetTables().GetCurrentSheet(); + sal_Int32 nSheet = rXMLImport.GetTables().GetCurrentSheet(); sal_Int32 nCurrentColumn = rXMLImport.GetTables().GetCurrentColumn(); uno::Reference<sheet::XSpreadsheet> xSheet(rXMLImport.GetTables().GetCurrentXSheet()); if(xSheet.is()) @@ -169,7 +170,16 @@ void ScXMLTableColContext::EndElement() XMLTableStyleContext* pStyle = (XMLTableStyleContext *)pStyles->FindStyleChildContext( XML_STYLE_FAMILY_TABLE_COLUMN, sStyleName, sal_True); if (pStyle) + { pStyle->FillPropertySet(xColumnProperties); + + if ( nSheet != pStyle->GetLastSheet() ) + { + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rXMLImport.GetModel())->GetSheetSaveData(); + pSheetData->AddColumnStyle( sStyleName, ScAddress( (SCCOL)nCurrentColumn, 0, (SCTAB)nSheet ) ); + pStyle->SetLastSheet(nSheet); + } + } } } rtl::OUString sVisible(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CELLVIS)); diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index 98965cba07bc..a35a426e4831 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -53,10 +53,12 @@ #include "XMLColumnRowGroupExport.hxx" #include "XMLStylesExportHelper.hxx" #include "XMLChangeTrackingExportHelper.hxx" +#include "sheetdata.hxx" #include "docoptio.hxx" #include "XMLExportSharedData.hxx" #include "chgviset.hxx" #include "docuno.hxx" +#include "textuno.hxx" #include "chartlis.hxx" #include "unoguard.hxx" #include "scitems.hxx" @@ -80,6 +82,7 @@ #include <xmloff/xmluconv.hxx> #include <xmloff/txtparae.hxx> #include <xmloff/xmlcnitm.hxx> +#include <xmloff/xmlerror.hxx> #include <rtl/ustring.hxx> @@ -122,6 +125,8 @@ #include <com/sun/star/container/XNamed.hpp> #include <com/sun/star/sheet/XSheetLinkable.hpp> #include <com/sun/star/form/XFormsSupplier2.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/chart2/XChartDocument.hpp> #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp> @@ -452,6 +457,7 @@ ScXMLExport::ScXMLExport( const sal_uInt16 nExportFlag) : SvXMLExport( xServiceFactory, SvXMLUnitConverter::GetMapUnit(GetFieldUnit()), XML_SPREADSHEET, nExportFlag ), pDoc(NULL), + nSourceStreamPos(0), pNumberFormatAttributesExportHelper(NULL), pSharedData(NULL), pColumnStyles(NULL), @@ -567,6 +573,45 @@ ScXMLExport::~ScXMLExport() delete pNumberFormatAttributesExportHelper; } +void ScXMLExport::SetSourceStream( const uno::Reference<io::XInputStream>& xNewStream ) +{ + xSourceStream = xNewStream; + + if ( xSourceStream.is() ) + { + // make sure it's a plain UTF-8 stream as written by OOo itself + + const sal_Char pXmlHeader[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; + sal_Int32 nLen = strlen(pXmlHeader); + + uno::Sequence<sal_Int8> aFileStart(nLen); + sal_Int32 nRead = xSourceStream->readBytes( aFileStart, nLen ); + + if ( nRead != nLen || rtl_compareMemory( aFileStart.getConstArray(), pXmlHeader, nLen ) != 0 ) + { + // invalid - ignore stream, save normally + xSourceStream.clear(); + } + else + { + // keep track of the bytes already read + nSourceStreamPos = nRead; + + const ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetModel())->GetSheetSaveData(); + if (pSheetData) + { + // add the loaded namespaces to the name space map + + if ( !pSheetData->AddLoadedNamespaces( _GetNamespaceMap() ) ) + { + // conflicts in the namespaces - ignore the stream, save normally + xSourceStream.clear(); + } + } + } + } +} + sal_Int32 ScXMLExport::GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const { NumberFormatIndexMap::const_iterator itr = aNumFmtIndexMap.find(nNumFmt); @@ -803,7 +848,7 @@ void ScXMLExport::_ExportFontDecls() SvXMLExport::_ExportFontDecls(); } -table::CellRangeAddress ScXMLExport::GetEndAddress(uno::Reference<sheet::XSpreadsheet>& xTable, const sal_Int32 /* nTable */) +table::CellRangeAddress ScXMLExport::GetEndAddress(const uno::Reference<sheet::XSpreadsheet>& xTable, const sal_Int32 /* nTable */) { table::CellRangeAddress aCellAddress; uno::Reference<sheet::XSheetCellCursor> xCursor(xTable->createCursor()); @@ -1481,6 +1526,95 @@ void ScXMLExport::SetBodyAttributes() } } +static bool lcl_CopyStreamElement( const uno::Reference< io::XInputStream >& xInput, + const uno::Reference< io::XOutputStream >& xOutput, + sal_Int32 nCount ) +{ + const sal_Int32 nBufSize = 16*1024; + uno::Sequence<sal_Int8> aSequence(nBufSize); + + sal_Int32 nRemaining = nCount; + bool bFirst = true; + + while ( nRemaining > 0 ) + { + sal_Int32 nRead = xInput->readBytes( aSequence, std::min( nRemaining, nBufSize ) ); + if (bFirst) + { + // safety check: Make sure the copied part actually points to the start of an element + if ( nRead < 1 || aSequence[0] != static_cast<sal_Int8>('<') ) + { + return false; // abort and set an error + } + bFirst = false; + } + if (nRead == nRemaining) + { + // safety check: Make sure the copied part also ends at the end of an element + if ( aSequence[nRead-1] != static_cast<sal_Int8>('>') ) + { + return false; // abort and set an error + } + } + + if ( nRead == nBufSize ) + { + xOutput->writeBytes( aSequence ); + nRemaining -= nRead; + } + else + { + if ( nRead > 0 ) + { + uno::Sequence<sal_Int8> aTempBuf( aSequence.getConstArray(), nRead ); + xOutput->writeBytes( aTempBuf ); + } + nRemaining = 0; + } + } + return true; // successful +} + +void ScXMLExport::CopySourceStream( sal_Int32 nStartOffset, sal_Int32 nEndOffset, sal_Int32& rNewStart, sal_Int32& rNewEnd ) +{ + uno::Reference<xml::sax::XDocumentHandler> xHandler = GetDocHandler(); + uno::Reference<io::XActiveDataSource> xDestSource( xHandler, uno::UNO_QUERY ); + if ( xDestSource.is() ) + { + uno::Reference<io::XOutputStream> xDestStream = xDestSource->getOutputStream(); + uno::Reference<io::XSeekable> xDestSeek( xDestStream, uno::UNO_QUERY ); + if ( xDestSeek.is() ) + { + // temporary: set same stream again to clear buffer + xDestSource->setOutputStream( xDestStream ); + + if ( getExportFlags() & EXPORT_PRETTY ) + { + ByteString aOutStr("\n "); + uno::Sequence<sal_Int8> aOutSeq( (sal_Int8*)aOutStr.GetBuffer(), aOutStr.Len() ); + xDestStream->writeBytes( aOutSeq ); + } + + rNewStart = (sal_Int32)xDestSeek->getPosition(); + + if ( nStartOffset > nSourceStreamPos ) + xSourceStream->skipBytes( nStartOffset - nSourceStreamPos ); + + if ( !lcl_CopyStreamElement( xSourceStream, xDestStream, nEndOffset - nStartOffset ) ) + { + // If copying went wrong, set an error. + // ScXMLImportWrapper then resets all stream flags, so the next save attempt will use normal saving. + + uno::Sequence<OUString> aEmptySeq; + SetError(XMLERROR_CANCEL|XMLERROR_FLAG_SEVERE, aEmptySeq); + } + nSourceStreamPos = nEndOffset; + + rNewEnd = (sal_Int32)xDestSeek->getPosition(); + } + } +} + void ScXMLExport::_ExportContent() { nCurrentTable = 0; @@ -1500,6 +1634,10 @@ void ScXMLExport::_ExportContent() if ( !xSpreadDoc.is() ) return; + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(xSpreadDoc)->GetSheetSaveData(); + if (pSheetData) + pSheetData->ResetSaveEntries(); + uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY ); if ( xIndex.is() ) { @@ -1531,6 +1669,27 @@ void ScXMLExport::_ExportContent() WriteTheLabelRanges( xSpreadDoc ); for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable) { + sal_Int32 nStartOffset = -1; + sal_Int32 nEndOffset = -1; + if (pSheetData && pDoc && pDoc->IsStreamValid((SCTAB)nTable)) + pSheetData->GetStreamPos( nTable, nStartOffset, nEndOffset ); + + if ( nStartOffset >= 0 && nEndOffset >= 0 && xSourceStream.is() ) + { + sal_Int32 nNewStart = -1; + sal_Int32 nNewEnd = -1; + CopySourceStream( nStartOffset, nEndOffset, nNewStart, nNewEnd ); + + // store position of copied sheet in output + pSheetData->AddSavePos( nTable, nNewStart, nNewEnd ); + + // skip iterator entries for this sheet + pCellsItr->SkipTable(static_cast<SCTAB>(nTable)); + } + else + { + //! indent after rebasing to m52 + uno::Reference<sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY); if (xTable.is()) { @@ -1653,6 +1812,8 @@ void ScXMLExport::_ExportContent() nEqualCells = 0; } } + + } IncrementProgressBar(sal_False); } } @@ -1729,6 +1890,245 @@ void ScXMLExport::_ExportStyles( sal_Bool bUsed ) SvXMLExport::_ExportStyles(bUsed); } +void ScXMLExport::AddStyleFromCells(const uno::Reference<beans::XPropertySet>& xProperties, + const uno::Reference<sheet::XSpreadsheet>& xTable, + sal_Int32 nTable, const rtl::OUString* pOldName) +{ + //! pass xCellRanges instead + uno::Reference<sheet::XSheetCellRanges> xCellRanges( xProperties, uno::UNO_QUERY ); + + rtl::OUString SC_SCELLPREFIX(RTL_CONSTASCII_USTRINGPARAM(XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX)); + rtl::OUString SC_NUMBERFORMAT(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_NUMFMT)); + + rtl::OUString sStyleName; + sal_Int32 nNumberFormat(-1); + sal_Int32 nValidationIndex(-1); + std::vector< XMLPropertyState > xPropStates(xCellStylesExportPropertySetMapper->Filter( xProperties )); + std::vector< XMLPropertyState >::iterator aItr(xPropStates.begin()); + std::vector< XMLPropertyState >::iterator aEndItr(xPropStates.end()); + sal_Int32 nCount(0); + while (aItr != aEndItr) + { + if (aItr->mnIndex != -1) + { + switch (xCellStylesPropertySetMapper->GetEntryContextId(aItr->mnIndex)) + { + case CTF_SC_VALIDATION : + { + pValidationsContainer->AddValidation(aItr->maValue, nValidationIndex); + // this is not very slow, because it is most the last property or + // if it is not the last property it is the property before the last property, + // so in the worst case only one property has to be copied, but in the best case no + // property has to be copied + aItr = xPropStates.erase(aItr); + aEndItr = xPropStates.end(); // #120346# old aEndItr is invalidated! + } + break; + case CTF_SC_CELLSTYLE : + { + aItr->maValue >>= sStyleName; + aItr->mnIndex = -1; + ++aItr; + ++nCount; + } + break; + case CTF_SC_NUMBERFORMAT : + { + if (aItr->maValue >>= nNumberFormat) + addDataStyle(nNumberFormat); + ++aItr; + ++nCount; + } + break; + default: + { + ++aItr; + ++nCount; + } + break; + } + } + else + { + ++aItr; + ++nCount; + } + } + if (nCount == 1) // this is the CellStyle and should be removed if alone + xPropStates.clear(); + if (nNumberFormat == -1) + xProperties->getPropertyValue(SC_NUMBERFORMAT) >>= nNumberFormat; + if (sStyleName.getLength()) + { + if (xPropStates.size()) + { + sal_Int32 nIndex; + if (pOldName) + { + if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, xPropStates)) + { + GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_CELL, *pOldName); + // add to pCellStyles, so the name is found for normal sheets + rtl::OUString* pTemp(new rtl::OUString(*pOldName)); + if (!pCellStyles->AddStyleName(pTemp, nIndex)) + delete pTemp; + } + } + else + { + rtl::OUString sName; + sal_Bool bIsAutoStyle(sal_True); + if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, xPropStates)) + { + rtl::OUString* pTemp(new rtl::OUString(sName)); + if (!pCellStyles->AddStyleName(pTemp, nIndex)) + delete pTemp; + } + else + nIndex = pCellStyles->GetIndexOfStyleName(sName, SC_SCELLPREFIX, bIsAutoStyle); + + uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses()); + table::CellRangeAddress* pAddresses(aAddresses.getArray()); + sal_Bool bGetMerge(sal_True); + for (sal_Int32 i = 0; i < aAddresses.getLength(); ++i, ++pAddresses) + { + pSharedData->SetLastColumn(nTable, pAddresses->EndColumn); + pSharedData->SetLastRow(nTable, pAddresses->EndRow); + pCellStyles->AddRangeStyleName(*pAddresses, nIndex, bIsAutoStyle, nValidationIndex, nNumberFormat); + if (bGetMerge) + bGetMerge = GetMerged(pAddresses, xTable); + } + } + } + else + { + rtl::OUString* pTemp(new rtl::OUString(EncodeStyleName(sStyleName))); + sal_Int32 nIndex(0); + if (!pCellStyles->AddStyleName(pTemp, nIndex, sal_False)) + { + delete pTemp; + pTemp = NULL; + } + if ( !pOldName ) + { + uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses()); + table::CellRangeAddress* pAddresses(aAddresses.getArray()); + sal_Bool bGetMerge(sal_True); + for (sal_Int32 i = 0; i < aAddresses.getLength(); ++i, ++pAddresses) + { + if (bGetMerge) + bGetMerge = GetMerged(pAddresses, xTable); + pCellStyles->AddRangeStyleName(*pAddresses, nIndex, sal_False, nValidationIndex, nNumberFormat); + if (!sStyleName.equalsAsciiL("Default", 7) || nValidationIndex != -1) + { + pSharedData->SetLastColumn(nTable, pAddresses->EndColumn); + pSharedData->SetLastRow(nTable, pAddresses->EndRow); + } + } + } + } + } +} + +void ScXMLExport::AddStyleFromColumn(const uno::Reference<beans::XPropertySet>& xColumnProperties, + const rtl::OUString* pOldName, sal_Int32& rIndex, sal_Bool& rIsVisible) +{ + rtl::OUString SC_SCOLUMNPREFIX(RTL_CONSTASCII_USTRINGPARAM(XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX)); + + std::vector<XMLPropertyState> xPropStates(xColumnStylesExportPropertySetMapper->Filter(xColumnProperties)); + if(xPropStates.size()) + { + std::vector< XMLPropertyState >::iterator aItr(xPropStates.begin()); + std::vector< XMLPropertyState >::iterator aEndItr(xPropStates.end()); + while (aItr != aEndItr) + { + if (xColumnStylesPropertySetMapper->GetEntryContextId(aItr->mnIndex) == CTF_SC_ISVISIBLE) + { + aItr->maValue >>= rIsVisible; + break; + } + ++aItr; + } + + rtl::OUString sParent; + if (pOldName) + { + if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_COLUMN, sParent, xPropStates)) + { + GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_COLUMN, *pOldName); + // add to pColumnStyles, so the name is found for normal sheets + rtl::OUString* pTemp(new rtl::OUString(*pOldName)); + rIndex = pColumnStyles->AddStyleName(pTemp); + } + } + else + { + rtl::OUString sName; + if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_COLUMN, sParent, xPropStates)) + { + rtl::OUString* pTemp(new rtl::OUString(sName)); + rIndex = pColumnStyles->AddStyleName(pTemp); + } + else + rIndex = pColumnStyles->GetIndexOfStyleName(sName, SC_SCOLUMNPREFIX); + } + } +} + +void ScXMLExport::AddStyleFromRow(const uno::Reference<beans::XPropertySet>& xRowProperties, + const rtl::OUString* pOldName, sal_Int32& rIndex) +{ + rtl::OUString SC_SROWPREFIX(RTL_CONSTASCII_USTRINGPARAM(XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX)); + + std::vector<XMLPropertyState> xPropStates(xRowStylesExportPropertySetMapper->Filter(xRowProperties)); + if(xPropStates.size()) + { + rtl::OUString sParent; + if (pOldName) + { + if (GetAutoStylePool()->AddNamed(*pOldName, XML_STYLE_FAMILY_TABLE_ROW, sParent, xPropStates)) + { + GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_ROW, *pOldName); + // add to pRowStyles, so the name is found for normal sheets + rtl::OUString* pTemp(new rtl::OUString(*pOldName)); + rIndex = pRowStyles->AddStyleName(pTemp); + } + } + else + { + rtl::OUString sName; + if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_ROW, sParent, xPropStates)) + { + rtl::OUString* pTemp(new rtl::OUString(sName)); + rIndex = pRowStyles->AddStyleName(pTemp); + } + else + rIndex = pRowStyles->GetIndexOfStyleName(sName, SC_SROWPREFIX); + } + } +} + +uno::Any lcl_GetEnumerated( uno::Reference<container::XEnumerationAccess> xEnumAccess, sal_Int32 nIndex ) +{ + uno::Any aRet; + uno::Reference<container::XEnumeration> xEnum( xEnumAccess->createEnumeration() ); + try + { + sal_Int32 nSkip = nIndex; + while ( nSkip > 0 ) + { + (void) xEnum->nextElement(); + --nSkip; + } + aRet = xEnum->nextElement(); + } + catch (container::NoSuchElementException&) + { + // leave aRet empty + } + return aRet; +} + void ScXMLExport::_ExportAutoStyles() { if (GetModel().is()) @@ -1741,6 +2141,272 @@ void ScXMLExport::_ExportAutoStyles() { if (getExportFlags() & EXPORT_CONTENT) { + // re-create automatic styles with old names from stored data + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(xSpreadDoc)->GetSheetSaveData(); + if (pSheetData && pDoc) + { + // formulas have to be calculated now, to detect changed results + // (during normal save, they will be calculated anyway) + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; ++nTab) + if (pDoc->IsStreamValid(nTab)) + { + ScCellIterator aIter( pDoc, 0,0,nTab, MAXCOL,MAXROW,nTab ); + ScBaseCell* pCell = aIter.GetFirst(); + while (pCell) + { + if (pCell->GetCellType() == CELLTYPE_FORMULA) + static_cast<ScFormulaCell*>(pCell)->IsValue(); // interpret if dirty + pCell = aIter.GetNext(); + } + } + + // stored cell styles + const std::vector<ScCellStyleEntry>& rCellEntries = pSheetData->GetCellStyles(); + std::vector<ScCellStyleEntry>::const_iterator aCellIter = rCellEntries.begin(); + std::vector<ScCellStyleEntry>::const_iterator aCellEnd = rCellEntries.end(); + while (aCellIter != aCellEnd) + { + ScAddress aPos = aCellIter->maCellPos; + sal_Int32 nTable = aPos.Tab(); + bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) ); + if (bCopySheet) + { + uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY); + uno::Reference <beans::XPropertySet> xProperties( + xTable->getCellByPosition( aPos.Col(), aPos.Row() ), uno::UNO_QUERY ); + + AddStyleFromCells(xProperties, xTable, nTable, &aCellIter->maName); + } + ++aCellIter; + } + + // stored column styles + const std::vector<ScCellStyleEntry>& rColumnEntries = pSheetData->GetColumnStyles(); + std::vector<ScCellStyleEntry>::const_iterator aColumnIter = rColumnEntries.begin(); + std::vector<ScCellStyleEntry>::const_iterator aColumnEnd = rColumnEntries.end(); + while (aColumnIter != aColumnEnd) + { + ScAddress aPos = aColumnIter->maCellPos; + sal_Int32 nTable = aPos.Tab(); + bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) ); + if (bCopySheet) + { + uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY); + uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns()); + uno::Reference<beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex( aPos.Col() ), uno::UNO_QUERY); + + sal_Int32 nIndex(-1); + sal_Bool bIsVisible(sal_True); + AddStyleFromColumn( xColumnProperties, &aColumnIter->maName, nIndex, bIsVisible ); + } + ++aColumnIter; + } + + // stored row styles + const std::vector<ScCellStyleEntry>& rRowEntries = pSheetData->GetRowStyles(); + std::vector<ScCellStyleEntry>::const_iterator aRowIter = rRowEntries.begin(); + std::vector<ScCellStyleEntry>::const_iterator aRowEnd = rRowEntries.end(); + while (aRowIter != aRowEnd) + { + ScAddress aPos = aRowIter->maCellPos; + sal_Int32 nTable = aPos.Tab(); + bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) ); + if (bCopySheet) + { + uno::Reference<table::XColumnRowRange> xColumnRowRange(xIndex->getByIndex(nTable), uno::UNO_QUERY); + uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows()); + uno::Reference<beans::XPropertySet> xRowProperties(xTableRows->getByIndex( aPos.Row() ), uno::UNO_QUERY); + + sal_Int32 nIndex(-1); + AddStyleFromRow( xRowProperties, &aRowIter->maName, nIndex ); + } + ++aRowIter; + } + + // stored table styles + const std::vector<ScCellStyleEntry>& rTableEntries = pSheetData->GetTableStyles(); + std::vector<ScCellStyleEntry>::const_iterator aTableIter = rTableEntries.begin(); + std::vector<ScCellStyleEntry>::const_iterator aTableEnd = rTableEntries.end(); + while (aTableIter != aTableEnd) + { + ScAddress aPos = aTableIter->maCellPos; + sal_Int32 nTable = aPos.Tab(); + bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) ); + if (bCopySheet) + { + //! separate method AddStyleFromTable needed? + uno::Reference<beans::XPropertySet> xTableProperties(xIndex->getByIndex(nTable), uno::UNO_QUERY); + if (xTableProperties.is()) + { + std::vector<XMLPropertyState> xPropStates(xTableStylesExportPropertySetMapper->Filter(xTableProperties)); + rtl::OUString sParent; + rtl::OUString sName( aTableIter->maName ); + GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TABLE_TABLE, sParent, xPropStates); + GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TABLE_TABLE, sName); + } + } + ++aTableIter; + } + + // stored styles for notes + + UniReference<SvXMLExportPropertyMapper> xShapeMapper = XMLShapeExport::CreateShapePropMapper( *this ); + GetShapeExport(); // make sure the graphics styles family is added + + const std::vector<ScNoteStyleEntry>& rNoteEntries = pSheetData->GetNoteStyles(); + std::vector<ScNoteStyleEntry>::const_iterator aNoteIter = rNoteEntries.begin(); + std::vector<ScNoteStyleEntry>::const_iterator aNoteEnd = rNoteEntries.end(); + while (aNoteIter != aNoteEnd) + { + ScAddress aPos = aNoteIter->maCellPos; + sal_Int32 nTable = aPos.Tab(); + bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) ); + if (bCopySheet) + { + //! separate method AddStyleFromNote needed? + + ScPostIt* pNote = pDoc->GetNote( aPos ); + DBG_ASSERT( pNote, "note not found" ); + if (pNote) + { + SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos ); + // all uno shapes are created anyway in CollectSharedData + uno::Reference<beans::XPropertySet> xShapeProperties( pDrawObj->getUnoShape(), uno::UNO_QUERY ); + if (xShapeProperties.is()) + { + if ( aNoteIter->maStyleName.getLength() ) + { + std::vector<XMLPropertyState> xPropStates(xShapeMapper->Filter(xShapeProperties)); + rtl::OUString sParent; + rtl::OUString sName( aNoteIter->maStyleName ); + GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_SD_GRAPHICS_ID, sParent, xPropStates); + GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_SD_GRAPHICS_ID, sName); + } + if ( aNoteIter->maTextStyle.getLength() ) + { + std::vector<XMLPropertyState> xPropStates( + GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(xShapeProperties)); + rtl::OUString sParent; + rtl::OUString sName( aNoteIter->maTextStyle ); + GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_PARAGRAPH, sParent, xPropStates); + GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_PARAGRAPH, sName); + } + } + } + } + ++aNoteIter; + } + + // note paragraph styles + + //UniReference<SvXMLExportPropertyMapper> xParaPropMapper = XMLTextParagraphExport::CreateParaExtPropMapper( *this ); + UniReference<SvXMLExportPropertyMapper> xParaPropMapper = GetTextParagraphExport()->GetParagraphPropertyMapper(); + + const std::vector<ScTextStyleEntry>& rNoteParaEntries = pSheetData->GetNoteParaStyles(); + std::vector<ScTextStyleEntry>::const_iterator aNoteParaIter = rNoteParaEntries.begin(); + std::vector<ScTextStyleEntry>::const_iterator aNoteParaEnd = rNoteParaEntries.end(); + while (aNoteParaIter != aNoteParaEnd) + { + ScAddress aPos = aNoteParaIter->maCellPos; + sal_Int32 nTable = aPos.Tab(); + bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) ); + if (bCopySheet) + { + ScPostIt* pNote = pDoc->GetNote( aPos ); + DBG_ASSERT( pNote, "note not found" ); + if (pNote) + { + SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos ); + uno::Reference<container::XEnumerationAccess> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xParaProp( + lcl_GetEnumerated( xCellText, aNoteParaIter->maSelection.nStartPara ), uno::UNO_QUERY ); + if ( xParaProp.is() ) + { + std::vector<XMLPropertyState> xPropStates(xParaPropMapper->Filter(xParaProp)); + rtl::OUString sParent; + rtl::OUString sName( aNoteParaIter->maName ); + GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_PARAGRAPH, sParent, xPropStates); + GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_PARAGRAPH, sName); + } + } + } + ++aNoteParaIter; + } + + // note text styles + + UniReference<SvXMLExportPropertyMapper> xTextPropMapper = XMLTextParagraphExport::CreateCharExtPropMapper( *this ); + + const std::vector<ScTextStyleEntry>& rNoteTextEntries = pSheetData->GetNoteTextStyles(); + std::vector<ScTextStyleEntry>::const_iterator aNoteTextIter = rNoteTextEntries.begin(); + std::vector<ScTextStyleEntry>::const_iterator aNoteTextEnd = rNoteTextEntries.end(); + while (aNoteTextIter != aNoteTextEnd) + { + ScAddress aPos = aNoteTextIter->maCellPos; + sal_Int32 nTable = aPos.Tab(); + bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) ); + if (bCopySheet) + { + ScPostIt* pNote = pDoc->GetNote( aPos ); + DBG_ASSERT( pNote, "note not found" ); + if (pNote) + { + SdrCaptionObj* pDrawObj = pNote->GetOrCreateCaption( aPos ); + uno::Reference<text::XSimpleText> xCellText(pDrawObj->getUnoShape(), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xCursorProp(xCellText->createTextCursor(), uno::UNO_QUERY); + ScDrawTextCursor* pCursor = ScDrawTextCursor::getImplementation( xCursorProp ); + if (pCursor) + { + pCursor->SetSelection( aNoteTextIter->maSelection ); + + std::vector<XMLPropertyState> xPropStates(xTextPropMapper->Filter(xCursorProp)); + rtl::OUString sParent; + rtl::OUString sName( aNoteTextIter->maName ); + GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_TEXT, sParent, xPropStates); + GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_TEXT, sName); + } + } + } + ++aNoteTextIter; + } + + // stored text styles + + //UniReference<SvXMLExportPropertyMapper> xTextPropMapper = XMLTextParagraphExport::CreateCharExtPropMapper( *this ); + + const std::vector<ScTextStyleEntry>& rTextEntries = pSheetData->GetTextStyles(); + std::vector<ScTextStyleEntry>::const_iterator aTextIter = rTextEntries.begin(); + std::vector<ScTextStyleEntry>::const_iterator aTextEnd = rTextEntries.end(); + while (aTextIter != aTextEnd) + { + ScAddress aPos = aTextIter->maCellPos; + sal_Int32 nTable = aPos.Tab(); + bool bCopySheet = pDoc->IsStreamValid( static_cast<SCTAB>(nTable) ); + if (bCopySheet) + { + //! separate method AddStyleFromText needed? + //! cache sheet object + + uno::Reference<table::XCellRange> xCellRange(xIndex->getByIndex(nTable), uno::UNO_QUERY); + uno::Reference<text::XSimpleText> xCellText(xCellRange->getCellByPosition(aPos.Col(), aPos.Row()), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xCursorProp(xCellText->createTextCursor(), uno::UNO_QUERY); + ScCellTextCursor* pCursor = ScCellTextCursor::getImplementation( xCursorProp ); + if (pCursor) + { + pCursor->SetSelection( aTextIter->maSelection ); + + std::vector<XMLPropertyState> xPropStates(xTextPropMapper->Filter(xCursorProp)); + rtl::OUString sParent; + rtl::OUString sName( aTextIter->maName ); + GetAutoStylePool()->AddNamed(sName, XML_STYLE_FAMILY_TEXT_TEXT, sParent, xPropStates); + GetAutoStylePool()->RegisterName(XML_STYLE_FAMILY_TEXT_TEXT, sName); + } + } + ++aTextIter; + } + } + ExportExternalRefCacheStyles(); if (!pSharedData) @@ -1751,18 +2417,18 @@ void ScXMLExport::_ExportAutoStyles() CollectSharedData(nTableCount, nShapesCount, nCellCount); //DBG_ERROR("no shared data setted"); } - rtl::OUString SC_SCOLUMNPREFIX(RTL_CONSTASCII_USTRINGPARAM(XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX)); - rtl::OUString SC_SROWPREFIX(RTL_CONSTASCII_USTRINGPARAM(XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX)); - rtl::OUString SC_SCELLPREFIX(RTL_CONSTASCII_USTRINGPARAM(XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX)); - rtl::OUString SC_NUMBERFORMAT(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_NUMFMT)); sal_Int32 nTableCount(xIndex->getCount()); pCellStyles->AddNewTable(nTableCount - 1); CollectShapesAutoStyles(nTableCount); for (sal_Int32 nTable = 0; nTable < nTableCount; ++nTable) { + bool bUseStream = pSheetData && pDoc && pDoc->IsStreamValid((SCTAB)nTable) && + pSheetData->HasStreamPos(nTable) && xSourceStream.is(); + uno::Reference <sheet::XSpreadsheet> xTable(xIndex->getByIndex(nTable), uno::UNO_QUERY); if (xTable.is()) { + // table styles array must be complete, including copied tables - Add should find the stored style uno::Reference<beans::XPropertySet> xTableProperties(xTable, uno::UNO_QUERY); if (xTableProperties.is()) { @@ -1775,7 +2441,11 @@ void ScXMLExport::_ExportAutoStyles() aTableStyles.push_back(sName); } } - uno::Reference<sheet::XUniqueCellFormatRangesSupplier> xCellFormatRanges ( xTableProperties, uno::UNO_QUERY ); + } + // collect other auto-styles only for non-copied sheets + if (xTable.is() && !bUseStream) + { + uno::Reference<sheet::XUniqueCellFormatRangesSupplier> xCellFormatRanges ( xTable, uno::UNO_QUERY ); if ( xCellFormatRanges.is() ) { uno::Reference<container::XIndexAccess> xFormatRangesIndex(xCellFormatRanges->getUniqueCellFormatRanges()); @@ -1791,123 +2461,14 @@ void ScXMLExport::_ExportAutoStyles() uno::Reference <beans::XPropertySet> xProperties (xCellRanges, uno::UNO_QUERY); if (xProperties.is()) { - rtl::OUString sStyleName; - sal_Int32 nNumberFormat(-1); - sal_Int32 nValidationIndex(-1); - std::vector< XMLPropertyState > xPropStates(xCellStylesExportPropertySetMapper->Filter( xProperties )); - std::vector< XMLPropertyState >::iterator aItr(xPropStates.begin()); - std::vector< XMLPropertyState >::iterator aEndItr(xPropStates.end()); - sal_Int32 nCount(0); - while (aItr != aEndItr) - { - if (aItr->mnIndex != -1) - { - switch (xCellStylesPropertySetMapper->GetEntryContextId(aItr->mnIndex)) - { - case CTF_SC_VALIDATION : - { - pValidationsContainer->AddValidation(aItr->maValue, nValidationIndex); - // this is not very slow, because it is most the last property or - // if it is not the last property it is the property before the last property, - // so in the worst case only one property has to be copied, but in the best case no - // property has to be copied - aItr = xPropStates.erase(aItr); - aEndItr = xPropStates.end(); // #120346# old aEndItr is invalidated! - } - break; - case CTF_SC_CELLSTYLE : - { - aItr->maValue >>= sStyleName; - aItr->mnIndex = -1; - ++aItr; - ++nCount; - } - break; - case CTF_SC_NUMBERFORMAT : - { - if (aItr->maValue >>= nNumberFormat) - addDataStyle(nNumberFormat); - ++aItr; - ++nCount; - } - break; - default: - { - ++aItr; - ++nCount; - } - break; - } - } - else - { - ++aItr; - ++nCount; - } - } - if (nCount == 1) // this is the CellStyle and should be removed if alone - xPropStates.clear(); - if (nNumberFormat == -1) - xProperties->getPropertyValue(SC_NUMBERFORMAT) >>= nNumberFormat; - if (sStyleName.getLength()) - { - if (xPropStates.size()) - { - sal_Int32 nIndex; - rtl::OUString sName; - sal_Bool bIsAutoStyle(sal_True); - if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_CELL, sStyleName, xPropStates)) - { - rtl::OUString* pTemp(new rtl::OUString(sName)); - if (!pCellStyles->AddStyleName(pTemp, nIndex)) - delete pTemp; - } - else - nIndex = pCellStyles->GetIndexOfStyleName(sName, SC_SCELLPREFIX, bIsAutoStyle); - uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses()); - table::CellRangeAddress* pAddresses(aAddresses.getArray()); - sal_Bool bGetMerge(sal_True); - for (sal_Int32 i = 0; i < aAddresses.getLength(); ++i, ++pAddresses) - { - pSharedData->SetLastColumn(nTable, pAddresses->EndColumn); - pSharedData->SetLastRow(nTable, pAddresses->EndRow); - pCellStyles->AddRangeStyleName(*pAddresses, nIndex, bIsAutoStyle, nValidationIndex, nNumberFormat); - if (bGetMerge) - bGetMerge = GetMerged(pAddresses, xTable); - } - } - else - { - rtl::OUString* pTemp(new rtl::OUString(EncodeStyleName(sStyleName))); - sal_Int32 nIndex(0); - if (!pCellStyles->AddStyleName(pTemp, nIndex, sal_False)) - { - delete pTemp; - pTemp = NULL; - } - uno::Sequence<table::CellRangeAddress> aAddresses(xCellRanges->getRangeAddresses()); - table::CellRangeAddress* pAddresses(aAddresses.getArray()); - sal_Bool bGetMerge(sal_True); - for (sal_Int32 i = 0; i < aAddresses.getLength(); ++i, ++pAddresses) - { - if (bGetMerge) - bGetMerge = GetMerged(pAddresses, xTable); - pCellStyles->AddRangeStyleName(*pAddresses, nIndex, sal_False, nValidationIndex, nNumberFormat); - if (!sStyleName.equalsAsciiL("Default", 7) || nValidationIndex != -1) - { - pSharedData->SetLastColumn(nTable, pAddresses->EndColumn); - pSharedData->SetLastRow(nTable, pAddresses->EndRow); - } - } - } - } + AddStyleFromCells(xProperties, xTable, nTable, NULL); IncrementProgressBar(sal_False); } } } } } - uno::Reference<table::XColumnRowRange> xColumnRowRange (xTableProperties, uno::UNO_QUERY); + uno::Reference<table::XColumnRowRange> xColumnRowRange (xTable, uno::UNO_QUERY); if (xColumnRowRange.is()) { if (pDoc) @@ -1935,31 +2496,9 @@ void ScXMLExport::_ExportAutoStyles() uno::Reference <beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex(nColumn), uno::UNO_QUERY); if (xColumnProperties.is()) { - std::vector<XMLPropertyState> xPropStates(xColumnStylesExportPropertySetMapper->Filter(xColumnProperties)); - if(xPropStates.size()) - { - std::vector< XMLPropertyState >::iterator aItr(xPropStates.begin()); - std::vector< XMLPropertyState >::iterator aEndItr(xPropStates.end()); - while (aItr != aEndItr) - { - if (xColumnStylesPropertySetMapper->GetEntryContextId(aItr->mnIndex) == CTF_SC_ISVISIBLE) - { - aItr->maValue >>= bIsVisible; - break; - } - ++aItr; - } - rtl::OUString sParent; - rtl::OUString sName; - if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_COLUMN, sParent, xPropStates)) - { - rtl::OUString* pTemp(new rtl::OUString(sName)); - nIndex = pColumnStyles->AddStyleName(pTemp); - } - else - nIndex = pColumnStyles->GetIndexOfStyleName(sName, SC_SCOLUMNPREFIX); - pColumnStyles->AddFieldStyleName(nTable, nColumn, nIndex, bIsVisible); - } + AddStyleFromColumn( xColumnProperties, NULL, nIndex, bIsVisible ); + //if(xPropStates.size()) + pColumnStyles->AddFieldStyleName(nTable, nColumn, nIndex, bIsVisible); } sal_Int32 nOld(nColumn); nColumn = pDoc->GetNextDifferentChangedCol(sal::static_int_cast<SCTAB>(nTable), static_cast<USHORT>(nColumn)); @@ -1996,20 +2535,9 @@ void ScXMLExport::_ExportAutoStyles() uno::Reference <beans::XPropertySet> xRowProperties(xTableRows->getByIndex(nRow), uno::UNO_QUERY); if(xRowProperties.is()) { - std::vector<XMLPropertyState> xPropStates(xRowStylesExportPropertySetMapper->Filter(xRowProperties)); - if(xPropStates.size()) - { - rtl::OUString sParent; - rtl::OUString sName; - if (GetAutoStylePool()->Add(sName, XML_STYLE_FAMILY_TABLE_ROW, sParent, xPropStates)) - { - rtl::OUString* pTemp(new rtl::OUString(sName)); - nIndex = pRowStyles->AddStyleName(pTemp); - } - else - nIndex = pRowStyles->GetIndexOfStyleName(sName, SC_SROWPREFIX); - pRowStyles->AddFieldStyleName(nTable, nRow, nIndex); - } + AddStyleFromRow( xRowProperties, NULL, nIndex ); + //if(xPropStates.size()) + pRowStyles->AddFieldStyleName(nTable, nRow, nIndex); } sal_Int32 nOld(nRow); nRow = pDoc->GetNextDifferentChangedRow(sal::static_int_cast<SCTAB>(nTable), static_cast<USHORT>(nRow), false); @@ -2025,7 +2553,7 @@ void ScXMLExport::_ExportAutoStyles() } } } - uno::Reference<sheet::XCellRangesQuery> xCellRangesQuery (xTableProperties, uno::UNO_QUERY); + uno::Reference<sheet::XCellRangesQuery> xCellRangesQuery (xTable, uno::UNO_QUERY); if (xCellRangesQuery.is()) { uno::Reference<sheet::XSheetCellRanges> xSheetCellRanges(xCellRangesQuery->queryContentCells(sheet::CellFlags::FORMATTED)); diff --git a/sc/source/filter/xml/xmlexprt.hxx b/sc/source/filter/xml/xmlexprt.hxx index d38bd7b23970..b71886c1871e 100644 --- a/sc/source/filter/xml/xmlexprt.hxx +++ b/sc/source/filter/xml/xmlexprt.hxx @@ -38,6 +38,10 @@ #include <com/sun/star/drawing/XShapes.hpp> #include <com/sun/star/table/XCellRange.hpp> +namespace com { namespace sun { namespace star { + namespace beans { class XPropertySet; } +} } } + #include <hash_map> class ScOutlineArray; @@ -72,6 +76,9 @@ class ScXMLExport : public SvXMLExport com::sun::star::uno::Reference <com::sun::star::sheet::XSpreadsheet> xCurrentTable; com::sun::star::uno::Reference <com::sun::star::table::XCellRange> xCurrentTableCellRange; + com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xSourceStream; + sal_Int32 nSourceStreamPos; + UniReference < XMLPropertyHandlerFactory > xScPropHdlFactory; UniReference < XMLPropertySetMapper > xCellStylesPropertySetMapper; UniReference < XMLPropertySetMapper > xColumnStylesPropertySetMapper; @@ -139,7 +146,7 @@ class ScXMLExport : public SvXMLExport void CollectInternalShape( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape ); - com::sun::star::table::CellRangeAddress GetEndAddress(com::sun::star::uno::Reference<com::sun::star::sheet::XSpreadsheet>& xTable, + com::sun::star::table::CellRangeAddress GetEndAddress(const com::sun::star::uno::Reference<com::sun::star::sheet::XSpreadsheet>& xTable, const sal_Int32 nTable); // ScMyEmptyDatabaseRangesContainer GetEmptyDatabaseRanges(); void GetAreaLinks( com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheetDocument>& xSpreadDoc, ScMyAreaLinksContainer& rAreaLinks ); @@ -207,7 +214,21 @@ class ScXMLExport : public SvXMLExport void CollectUserDefinedNamespaces(const SfxItemPool* pPool, sal_uInt16 nAttrib); + void AddStyleFromCells( + const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet >& xProperties, + const com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheet >& xTable, + sal_Int32 nTable, const rtl::OUString* pOldName ); + void AddStyleFromColumn( + const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet >& xColumnProperties, + const rtl::OUString* pOldName, sal_Int32& rIndex, sal_Bool& rIsVisible ); + void AddStyleFromRow( + const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet >& xRowProperties, + const rtl::OUString* pOldName, sal_Int32& rIndex ); + void IncrementProgressBar(sal_Bool bEditCell, sal_Int32 nInc = 1); + + void CopySourceStream( sal_Int32 nStartOffset, sal_Int32 nEndOffset, sal_Int32& rNewStart, sal_Int32& rNewEnd ); + protected: virtual SvXMLAutoStylePoolP* CreateAutoStylePool(); virtual XMLPageExport* CreatePageExport(); @@ -234,6 +255,8 @@ public: UniReference < XMLPropertySetMapper > GetCellStylesPropertySetMapper() { return xCellStylesPropertySetMapper; } UniReference < XMLPropertySetMapper > GetTableStylesPropertySetMapper() { return xTableStylesPropertySetMapper; } + void SetSourceStream( const com::sun::star::uno::Reference<com::sun::star::io::XInputStream>& xNewStream ); + void GetChangeTrackViewSettings(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& rProps); virtual void GetViewSettings(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& rProps); virtual void GetConfigurationSettings(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& rProps); diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx index 200e33743020..8e3f4b421a6c 100644 --- a/sc/source/filter/xml/xmlimprt.cxx +++ b/sc/source/filter/xml/xmlimprt.cxx @@ -71,6 +71,7 @@ #include "XMLChangeTrackingImportHelper.hxx" #include "chgviset.hxx" #include "XMLStylesImportHelper.hxx" +#include "sheetdata.hxx" #include "unonames.hxx" #include "rangeutl.hxx" #include "postit.hxx" @@ -93,6 +94,7 @@ #include <com/sun/star/sheet/NamedRangeFlag.hpp> #include <com/sun/star/sheet/XNamedRange.hpp> #include <com/sun/star/sheet/XLabelRanges.hpp> +#include <com/sun/star/io/XSeekable.hpp> #define SC_LOCALE "Locale" #define SC_STANDARDFORMAT "StandardFormat" @@ -2416,6 +2418,20 @@ void ScXMLImport::SetStyleToRanges() pStyle->FillPropertySet(xProperties); sal_Int32 nNumberFormat(pStyle->GetNumberFormat()); SetType(xProperties, nNumberFormat, nPrevCellType, sPrevCurrency); + + // store first cell of first range for each style, once per sheet + uno::Sequence<table::CellRangeAddress> aAddresses(xSheetCellRanges->getRangeAddresses()); + if ( aAddresses.getLength() > 0 ) + { + const table::CellRangeAddress& rRange = aAddresses[0]; + if ( rRange.Sheet != pStyle->GetLastSheet() ) + { + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetModel())->GetSheetSaveData(); + pSheetData->AddCellStyle( sPrevStyleName, + ScAddress( (SCCOL)rRange.StartColumn, (SCROW)rRange.StartRow, (SCTAB)rRange.Sheet ) ); + pStyle->SetLastSheet(rRange.Sheet); + } + } } else { @@ -2569,6 +2585,17 @@ throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeE if ( ( nFlags & IMPORT_CONTENT ) && !( nFlags & IMPORT_STYLES ) ) ExamineDefaultStyle(); + if (getImportFlags() & IMPORT_CONTENT) + { + if (GetModel().is()) + { + // store initial namespaces, to find the ones that were added from the file later + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetModel())->GetSheetSaveData(); + const SvXMLNamespaceMap& rNamespaces = GetNamespaceMap(); + pSheetData->StoreInitialNamespaces(rNamespaces); + } + } + UnlockSolarMutex(); } @@ -2772,6 +2799,19 @@ throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeE GetProgressBarHelper()->End(); // make room for subsequent SfxProgressBars if (pDoc) pDoc->CompileXML(); + + if (pDoc && GetModel().is()) + { + // set "valid stream" flags after loading (before UpdateRowHeights, so changed formula results + // in UpdateRowHeights can already clear the flags again) + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetModel())->GetSheetSaveData(); + + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; ++nTab) + if (!pSheetData->IsSheetBlocked( nTab )) + pDoc->SetStreamValid( nTab, TRUE ); + } + aTables.UpdateRowHeights(); aTables.ResizeShapes(); } @@ -2831,6 +2871,16 @@ void ScXMLImport::UnlockSolarMutex() } } +sal_Int32 ScXMLImport::GetByteOffset() +{ + sal_Int32 nOffset = -1; + uno::Reference<xml::sax::XLocator> xLocator = GetLocator(); + uno::Reference<io::XSeekable> xSeek( xLocator, uno::UNO_QUERY ); //! should use different interface + if ( xSeek.is() ) + nOffset = (sal_Int32)xSeek->getPosition(); + return nOffset; +} + void ScXMLImport::SetRangeOverflowType(sal_uInt32 nType) { // #i31130# Overflow is stored in the document, because the ScXMLImport object diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx index f96d34c40ca5..c108642d0b68 100644 --- a/sc/source/filter/xml/xmlimprt.hxx +++ b/sc/source/filter/xml/xmlimprt.hxx @@ -980,6 +980,8 @@ public: void LockSolarMutex(); void UnlockSolarMutex(); + sal_Int32 GetByteOffset(); + void SetRangeOverflowType(sal_uInt32 nType); sal_Int32 GetRangeType(const rtl::OUString sRangeType) const; diff --git a/sc/source/filter/xml/xmlrowi.cxx b/sc/source/filter/xml/xmlrowi.cxx index 079691944481..f62208cdd2ff 100644 --- a/sc/source/filter/xml/xmlrowi.cxx +++ b/sc/source/filter/xml/xmlrowi.cxx @@ -43,6 +43,7 @@ #include "document.hxx" #include "docuno.hxx" #include "olinetab.hxx" +#include "sheetdata.hxx" #include <xmloff/xmltkmap.hxx> #include <xmloff/nmspmap.hxx> @@ -170,6 +171,7 @@ void ScXMLTableRowContext::EndElement() GetScImport().GetTables().AddRow(); DBG_ERRORFILE("it seems here is a nonvalid file; possible missing of table:table-cell element"); } + sal_Int32 nSheet = rXMLImport.GetTables().GetCurrentSheet(); sal_Int32 nCurrentRow(rXMLImport.GetTables().GetCurrentRow()); uno::Reference<sheet::XSpreadsheet> xSheet(rXMLImport.GetTables().GetCurrentXSheet()); if(xSheet.is()) @@ -196,7 +198,16 @@ void ScXMLTableRowContext::EndElement() XMLTableStyleContext* pStyle((XMLTableStyleContext *)pStyles->FindStyleChildContext( XML_STYLE_FAMILY_TABLE_ROW, sStyleName, sal_True)); if (pStyle) + { pStyle->FillPropertySet(xRowProperties); + + if ( nSheet != pStyle->GetLastSheet() ) + { + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rXMLImport.GetModel())->GetSheetSaveData(); + pSheetData->AddRowStyle( sStyleName, ScAddress( 0, (SCROW)nFirstRow, (SCTAB)nSheet ) ); + pStyle->SetLastSheet(nSheet); + } + } } } sal_Bool bVisible (sal_True); diff --git a/sc/source/filter/xml/xmlstyli.cxx b/sc/source/filter/xml/xmlstyli.cxx index 79ba79f0e689..20158d1f13db 100644 --- a/sc/source/filter/xml/xmlstyli.cxx +++ b/sc/source/filter/xml/xmlstyli.cxx @@ -50,6 +50,11 @@ #include <tools/debug.hxx> #include "XMLTableHeaderFooterContext.hxx" #include "XMLConverter.hxx" +#include "XMLTableShapeImportHelper.hxx" +#include "sheetdata.hxx" +#include "xmlannoi.hxx" +#include "textuno.hxx" +#include "cellsuno.hxx" #include "docuno.hxx" #include "unonames.hxx" @@ -461,6 +466,7 @@ XMLTableStyleContext::XMLTableStyleContext( ScXMLImport& rImport, sNumberFormat(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))), pStyles(&rStyles), nNumberFormat(-1), + nLastSheet(-1), bConditionalFormatCreated(sal_False), bParentSet(sal_False) { @@ -609,15 +615,22 @@ sal_Int32 XMLTableStyleContext::GetNumberFormat() } return nNumberFormat; } + // ---------------------------------------------------------------------------- SvXMLStyleContext *XMLTableStylesContext::CreateStyleStyleChildContext( sal_uInt16 nFamily, sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > & xAttrList ) { - SvXMLStyleContext *pStyle(SvXMLStylesContext::CreateStyleStyleChildContext( nFamily, nPrefix, - rLocalName, - xAttrList )); + SvXMLStyleContext *pStyle; + // use own wrapper for text and paragraph, to record style usage + if (nFamily == XML_STYLE_FAMILY_TEXT_PARAGRAPH || nFamily == XML_STYLE_FAMILY_TEXT_TEXT) + pStyle = new ScCellTextStyleContext( GetImport(), nPrefix, rLocalName, + xAttrList, *this, nFamily ); + else + pStyle = SvXMLStylesContext::CreateStyleStyleChildContext( + nFamily, nPrefix, rLocalName, xAttrList ); + if (!pStyle) { switch( nFamily ) @@ -1013,3 +1026,56 @@ void ScMasterPageContext::Finish( sal_Bool bOverwrite ) ClearContent(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_PAGE_RIGHTHDRCON))); } +// --------------------------------------------------------------------------- + +ScCellTextStyleContext::ScCellTextStyleContext( SvXMLImport& rImport, sal_uInt16 nPrfx, + const rtl::OUString& rLName, const uno::Reference<xml::sax::XAttributeList> & xAttrList, + SvXMLStylesContext& rStyles, sal_uInt16 nFamily, sal_Bool bDefaultStyle ) : + XMLTextStyleContext( rImport, nPrfx, rLName, xAttrList, rStyles, nFamily, bDefaultStyle ), + nLastSheet(-1) +{ +} + +ScCellTextStyleContext::~ScCellTextStyleContext() +{ +} + +void ScCellTextStyleContext::FillPropertySet( const uno::Reference<beans::XPropertySet>& xPropSet ) +{ + XMLTextStyleContext::FillPropertySet( xPropSet ); + + ScXMLImport& rXMLImport = GetScImport(); + + ScCellTextCursor* pCellImp = ScCellTextCursor::getImplementation( xPropSet ); + if (pCellImp) + { + ScAddress aPos = pCellImp->GetCellObj().GetPosition(); + if ( static_cast<sal_Int32>(aPos.Tab()) != nLastSheet ) + { + ESelection aSel = pCellImp->GetSelection(); + + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetImport().GetModel())->GetSheetSaveData(); + pSheetData->AddTextStyle( GetName(), aPos, aSel ); + + nLastSheet = static_cast<sal_Int32>(aPos.Tab()); + } + } + else if ( rXMLImport.GetTables().GetCurrentSheet() != nLastSheet ) + { + ScDrawTextCursor* pDrawImp = ScDrawTextCursor::getImplementation( xPropSet ); + if (pDrawImp) + { + XMLTableShapeImportHelper* pTableShapeImport = (XMLTableShapeImportHelper*)GetScImport().GetShapeImport().get(); + ScXMLAnnotationContext* pAnnotationContext = pTableShapeImport->GetAnnotationContext(); + if (pAnnotationContext) + { + pAnnotationContext->AddContentStyle( GetFamily(), GetName(), pDrawImp->GetSelection() ); + nLastSheet = rXMLImport.GetTables().GetCurrentSheet(); + } + } + + // if it's a different shape, BlockSheet is called from XMLTableShapeImportHelper::finishShape + // formatted text in page headers/footers can be ignored + } +} + diff --git a/sc/source/filter/xml/xmlstyli.hxx b/sc/source/filter/xml/xmlstyli.hxx index 272ec0151134..c80ea8b5c92d 100644 --- a/sc/source/filter/xml/xmlstyli.hxx +++ b/sc/source/filter/xml/xmlstyli.hxx @@ -40,9 +40,12 @@ #include <xmloff/xmlimppr.hxx> #include <xmloff/XMLTextMasterPageContext.hxx> #include <xmloff/XMLTextMasterStylesContext.hxx> +#include <xmloff/txtstyli.hxx> #include <com/sun/star/sheet/ConditionOperator.hpp> #include "xmlimprt.hxx" +class ScSheetSaveData; + class ScXMLCellImportPropertyMapper : public SvXMLImportPropertyMapper { protected: @@ -101,6 +104,7 @@ class XMLTableStyleContext : public XMLPropStyleContext std::vector<ScXMLMapContent> aMaps; com::sun::star::uno::Any aConditionalFormat; sal_Int32 nNumberFormat; + sal_Int32 nLastSheet; sal_Bool bConditionalFormatCreated; sal_Bool bParentSet; @@ -158,6 +162,9 @@ public: sal_Int32 GetNumberFormat();// { return nNumberFormat; } + sal_Int32 GetLastSheet() const { return nLastSheet; } + void SetLastSheet(sal_Int32 nNew) { nLastSheet = nNew; } + private: using XMLPropStyleContext::SetStyle; }; @@ -298,5 +305,28 @@ public: virtual void Finish( sal_Bool bOverwrite ); }; +class ScCellTextStyleContext : public XMLTextStyleContext +{ + sal_Int32 nLastSheet; + + const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); } + ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); } + +public: + ScCellTextStyleContext( SvXMLImport& rImport, sal_uInt16 nPrfx, + const ::rtl::OUString& rLName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList, + SvXMLStylesContext& rStyles, sal_uInt16 nFamily, + sal_Bool bDefaultStyle = sal_False ); + virtual ~ScCellTextStyleContext(); + + // overload FillPropertySet to store style information + virtual void FillPropertySet( + const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet > & rPropSet ); +}; + + #endif diff --git a/sc/source/filter/xml/xmlsubti.cxx b/sc/source/filter/xml/xmlsubti.cxx index 231839b9f946..0f980c4a9608 100644 --- a/sc/source/filter/xml/xmlsubti.cxx +++ b/sc/source/filter/xml/xmlsubti.cxx @@ -43,6 +43,7 @@ #include "docuno.hxx" #include "cellsuno.hxx" #include "XMLStylesImportHelper.hxx" +#include "sheetdata.hxx" #include "tabprotection.hxx" #include <svx/svdpage.hxx> @@ -269,7 +270,12 @@ void ScMyTables::NewSheet(const rtl::OUString& sTableName, const rtl::OUString& XMLTableStyleContext* pStyle = (XMLTableStyleContext *)pStyles->FindStyleChildContext( XML_STYLE_FAMILY_TABLE_TABLE, sStyleName, sal_True); if (pStyle) + { pStyle->FillPropertySet(xProperties); + + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rImport.GetModel())->GetSheetSaveData(); + pSheetData->AddTableStyle( sStyleName, ScAddress( 0, 0, (SCTAB)nCurrentSheet ) ); + } } } } @@ -609,7 +615,11 @@ void ScMyTables::UpdateRowHeights() } if (aUpdateSheets.GetSelectCount()) + { + pDoc->LockStreamValid( true ); // ignore draw page size (but not formula results) ScModelObj::getImplementation(rImport.GetModel())->UpdateAllRowHeights(&aUpdateSheets); + pDoc->LockStreamValid( false ); + } } rImport.UnlockSolarMutex(); diff --git a/sc/source/filter/xml/xmltabi.cxx b/sc/source/filter/xml/xmltabi.cxx index cc95e01be821..8ea9701ecd32 100644 --- a/sc/source/filter/xml/xmltabi.cxx +++ b/sc/source/filter/xml/xmltabi.cxx @@ -50,6 +50,7 @@ #include "XMLStylesImportHelper.hxx" #include "rangeutl.hxx" #include "externalrefmgr.hxx" +#include "sheetdata.hxx" #include <xmloff/xmltkmap.hxx> #include <xmloff/nmspmap.hxx> @@ -147,9 +148,13 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport, const sal_Int32 nSpannedCols) : SvXMLImportContext( rImport, nPrfx, rLName ), pExternalRefInfo(NULL), + nStartOffset(-1), bStartFormPage(sal_False), bPrintEntireSheet(sal_True) { + // get start offset in file (if available) + nStartOffset = GetScImport().GetByteOffset(); + if (!bTempIsSubTable) { sal_Bool bProtection(sal_False); @@ -326,6 +331,9 @@ SvXMLImportContext *ScXMLTableContext::CreateChildContext( USHORT nPrefix, void ScXMLTableContext::EndElement() { + // get end offset in file (if available) +// sal_Int32 nEndOffset = GetScImport().GetByteOffset(); + GetScImport().LockSolarMutex(); GetScImport().GetStylesImportHelper()->EndTable(); ScDocument* pDoc(GetScImport().GetDocument()); @@ -386,6 +394,15 @@ void ScXMLTableContext::EndElement() GetScImport().GetTables().DeleteTable(); GetScImport().ProgressBarIncrement(sal_False); + + // store stream positions + if (!pExternalRefInfo.get() && nStartOffset >= 0 /* && nEndOffset >= 0 */) + { + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetScImport().GetModel())->GetSheetSaveData(); + sal_Int32 nTab = GetScImport().GetTables().GetCurrentSheet(); + // pSheetData->AddStreamPos( nTab, nStartOffset, nEndOffset ); + pSheetData->StartStreamPos( nTab, nStartOffset ); + } } GetScImport().UnlockSolarMutex(); } diff --git a/sc/source/filter/xml/xmltabi.hxx b/sc/source/filter/xml/xmltabi.hxx index 7b8c9878f2d5..1a4438b28955 100644 --- a/sc/source/filter/xml/xmltabi.hxx +++ b/sc/source/filter/xml/xmltabi.hxx @@ -52,6 +52,7 @@ class ScXMLTableContext : public SvXMLImportContext { rtl::OUString sPrintRanges; ::std::auto_ptr<ScXMLExternalTabData> pExternalRefInfo; + sal_Int32 nStartOffset; sal_Bool bStartFormPage; sal_Bool bPrintEntireSheet; diff --git a/sc/source/filter/xml/xmlwrap.cxx b/sc/source/filter/xml/xmlwrap.cxx index 960d78ada163..dbf672993310 100644 --- a/sc/source/filter/xml/xmlwrap.cxx +++ b/sc/source/filter/xml/xmlwrap.cxx @@ -624,6 +624,25 @@ sal_Bool ScXMLImportWrapper::Import(sal_Bool bStylesOnly, ErrCode& nError) return sal_False; } +bool lcl_HasValidStream(ScDocument& rDoc) +{ + SfxObjectShell* pObjSh = rDoc.GetDocumentShell(); + if ( pObjSh->IsDocShared() ) + return false; // never copy stream from shared file + + // don't read remote file again + // (could instead re-use medium directly in that case) + SfxMedium* pSrcMed = rDoc.GetDocumentShell()->GetMedium(); + if ( !pSrcMed || pSrcMed->IsRemote() ) + return false; + + SCTAB nTabCount = rDoc.GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; ++nTab) + if (rDoc.IsStreamValid(nTab)) + return true; + return false; +} + sal_Bool ScXMLImportWrapper::ExportToComponent(uno::Reference<lang::XMultiServiceFactory>& xServiceFactory, uno::Reference<frame::XModel>& xModel, uno::Reference<uno::XInterface>& xWriter, uno::Sequence<beans::PropertyValue>& aDescriptor, const rtl::OUString& sName, @@ -691,7 +710,49 @@ sal_Bool ScXMLImportWrapper::ExportToComponent(uno::Reference<lang::XMultiServic { ScXMLExport* pExport = static_cast<ScXMLExport*>(SvXMLExport::getImplementation(xFilter)); pExport->SetSharedData(pSharedData); - bRet = xFilter->filter( aDescriptor ); + + // if there are sheets to copy, get the source stream + if ( sName.equalsAscii("content.xml") && lcl_HasValidStream(rDoc) && + ( pExport->getExportFlags() & EXPORT_OASIS ) ) + { + // old stream is still in this file's storage - open read-only + + SfxMedium* pSrcMed = rDoc.GetDocumentShell()->GetMedium(); + String aSrcURL = pSrcMed->GetOrigURL(); + + // SfxMedium must not be read-only, or it will create a temp file in GetStorage + SfxMedium aTmpMedium( aSrcURL, STREAM_READWRITE, FALSE, NULL, NULL ); + uno::Reference<embed::XStorage> xTmpStorage = aTmpMedium.GetStorage(); + uno::Reference<io::XStream> xSrcStream; + uno::Reference<io::XInputStream> xSrcInput; + try + { + if (xTmpStorage.is()) + xSrcStream = xTmpStorage->openStreamElement( sName, embed::ElementModes::READ ); + if (xSrcStream.is()) + xSrcInput = xSrcStream->getInputStream(); + } + catch (uno::Exception&) + { + // stream not available (for example, password protected) - save normally (xSrcInput is null) + } + + pExport->SetSourceStream( xSrcInput ); + bRet = xFilter->filter( aDescriptor ); + pExport->SetSourceStream( uno::Reference<io::XInputStream>() ); + + // If there was an error, reset all stream flags, so the next save attempt will use normal saving. + if (!bRet) + { + SCTAB nTabCount = rDoc.GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if (rDoc.IsStreamValid(nTab)) + rDoc.SetStreamValid(nTab, FALSE); + } + } + else + bRet = xFilter->filter( aDescriptor ); + pSharedData = pExport->GetSharedData(); //stream is closed by SAX parser |