diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-08-01 22:01:26 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-08-02 14:22:10 -0400 |
commit | bf846ac0510da21f7faa601fbd30d9147dc3ee71 (patch) | |
tree | d6acca38a7b233b24ba5f1331320efab7fcadc69 | |
parent | eace5e0a1c4bab37699429447b1a17e3c9410503 (diff) |
fdo#67099: Remove overheads on inserting cells during ods import.
We will switch to using ScDocumentImport to populate the document from
import filters, instead of using ScDocument directly.
Change-Id: Ie59d6877d1ac4fc04751a84b663772a9dc9a3efc
-rw-r--r-- | sc/inc/column.hxx | 11 | ||||
-rw-r--r-- | sc/inc/documentimport.hxx | 13 | ||||
-rw-r--r-- | sc/source/core/data/column2.cxx | 35 | ||||
-rw-r--r-- | sc/source/core/data/column3.cxx | 260 | ||||
-rw-r--r-- | sc/source/core/data/documentimport.cxx | 231 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlcelli.cxx | 33 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlimprt.cxx | 12 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlimprt.hxx | 7 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlsubti.cxx | 14 |
9 files changed, 404 insertions, 212 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index a42ac8f19c29..045b76a844a3 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -136,6 +136,11 @@ friend class sc::ColumnSpanSet; ScColumn(const ScColumn&); // disabled ScColumn& operator= (const ScColumn&); // disabled + bool ParseString( + ScCellValue& rCell, + SCROW nRow, SCTAB nTab, const String& rString, formula::FormulaGrammar::AddressConvention eConv, + ScSetStringParam* pParam ); + public: ScColumn(); ~ScColumn(); @@ -523,12 +528,6 @@ private: void CopyCellTextAttrsToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDestCol) const; - /** - * Clear and re-populate the cell text attribute array from the non-empty - * cells stored in the cell array. - */ - void ResetCellTextAttrs(); - void SwapCellTextAttrs( SCROW nRow1, SCROW nRow2 ); }; diff --git a/sc/inc/documentimport.hxx b/sc/inc/documentimport.hxx index 9fddf2b86282..06203019b042 100644 --- a/sc/inc/documentimport.hxx +++ b/sc/inc/documentimport.hxx @@ -17,9 +17,12 @@ #include <boost/noncopyable.hpp> +class EditTextObject; class ScDocument; +class ScColumn; class ScAddress; class ScTokenArray; +class ScFormulaCell; struct ScDocumentImportImpl; /** @@ -42,6 +45,8 @@ public: ScDocument& getDoc(); const ScDocument& getDoc() const; + void setDefaultNumericScript(sal_uInt16 nScript); + /** * @param rName sheet name. * @@ -57,10 +62,18 @@ public: void setAutoInput(const ScAddress& rPos, const OUString& rStr); void setNumericCell(const ScAddress& rPos, double fVal); void setStringCell(const ScAddress& rPos, const OUString& rStr); + void setEditCell(const ScAddress& rPos, EditTextObject* pEditText); void setFormulaCell(const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar); void setFormulaCell(const ScAddress& rPos, const ScTokenArray& rArray); + void setFormulaCell(const ScAddress& rPos, ScFormulaCell* pCell); + + void setMatrixCells( + const ScRange& rRange, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGrammar); void finalize(); + +private: + void initColumn(ScColumn& rCol); }; #endif diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index ab6c88a2e1a5..6a52d8cc8447 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -1626,41 +1626,6 @@ void ScColumn::CopyCellTextAttrsToDocument(SCROW nRow1, SCROW nRow2, ScColumn& r } } -namespace { - -class CellTextAttrInitializer -{ - sc::CellTextAttrStoreType maAttrs; - sc::CellTextAttrStoreType::iterator miPos; -public: - CellTextAttrInitializer() : maAttrs(MAXROWCOUNT), miPos(maAttrs.begin()) {} - - void operator() (const sc::CellStoreType::value_type& node) - { - if (node.type == sc::element_type_empty) - return; - - // Fill with default values for non-empty cell segments. - std::vector<sc::CellTextAttr> aDefaults(node.size); - miPos = maAttrs.set(miPos, node.position, aDefaults.begin(), aDefaults.end()); - } - - void swap(sc::CellTextAttrStoreType& rAttrs) - { - maAttrs.swap(rAttrs); - } -}; - -} - -void ScColumn::ResetCellTextAttrs() -{ - CellTextAttrInitializer aFunc; - std::for_each(maCells.begin(), maCells.end(), aFunc); - aFunc.swap(maCellTextAttrs); - CellStorageModified(); -} - void ScColumn::SwapCellTextAttrs( SCROW nRow1, SCROW nRow2 ) { typedef std::pair<sc::CellTextAttrStoreType::iterator,size_t> PosType; diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index a3ccfd1abe40..4474aecebd39 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -1409,162 +1409,172 @@ void ScColumn::StartListeningInArea( sc::StartListeningContext& rCxt, SCROW nRow sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc); } - -/** - * Returns true if the cell format was set as well - */ -bool ScColumn::SetString( SCROW nRow, SCTAB nTabP, const String& rString, - formula::FormulaGrammar::AddressConvention eConv, - ScSetStringParam* pParam ) +bool ScColumn::ParseString( + ScCellValue& rCell, SCROW nRow, SCTAB nTabP, const String& rString, + formula::FormulaGrammar::AddressConvention eConv, + ScSetStringParam* pParam ) { - bool bNumFmtSet = false; - if (!ValidRow(nRow)) + if (!rString.Len()) return false; - ScCellValue aNewCell; - if (rString.Len() > 0) - { - ScSetStringParam aParam; - if (pParam) - aParam = *pParam; - - sal_uInt32 nIndex = 0; - sal_uInt32 nOldIndex = 0; - sal_Unicode cFirstChar; - if (!aParam.mpNumFormatter) - aParam.mpNumFormatter = pDocument->GetFormatTable(); - - nIndex = nOldIndex = GetNumberFormat( nRow ); - if ( rString.Len() > 1 - && aParam.mpNumFormatter->GetType(nIndex) != NUMBERFORMAT_TEXT ) - cFirstChar = rString.GetChar(0); - else - cFirstChar = 0; // Text + bool bNumFmtSet = false; + + ScSetStringParam aParam; + + if (pParam) + aParam = *pParam; + + sal_uInt32 nIndex = 0; + sal_uInt32 nOldIndex = 0; + sal_Unicode cFirstChar; + if (!aParam.mpNumFormatter) + aParam.mpNumFormatter = pDocument->GetFormatTable(); - if ( cFirstChar == '=' ) + nIndex = nOldIndex = GetNumberFormat( nRow ); + if ( rString.Len() > 1 + && aParam.mpNumFormatter->GetType(nIndex) != NUMBERFORMAT_TEXT ) + cFirstChar = rString.GetChar(0); + else + cFirstChar = 0; // Text + + if ( cFirstChar == '=' ) + { + if ( rString.Len() == 1 ) // = Text + rCell.set(rString); + else // = Formula + rCell.set( + new ScFormulaCell( + pDocument, ScAddress(nCol, nRow, nTabP), rString, + formula::FormulaGrammar::mergeToGrammar(formula::FormulaGrammar::GRAM_DEFAULT, eConv), + MM_NONE)); + } + else if ( cFirstChar == '\'') // 'Text + { + bool bNumeric = false; + if (aParam.mbHandleApostrophe) { - if ( rString.Len() == 1 ) // = Text - aNewCell.set(rString); - else // = Formula - aNewCell.set( - new ScFormulaCell( - pDocument, ScAddress(nCol, nRow, nTabP), rString, - formula::FormulaGrammar::mergeToGrammar(formula::FormulaGrammar::GRAM_DEFAULT, eConv), - MM_NONE)); + // Cell format is not 'Text', and the first char + // is an apostrophe. Check if the input is considered a number. + String aTest = rString.Copy(1); + double fTest; + bNumeric = aParam.mpNumFormatter->IsNumberFormat(aTest, nIndex, fTest); + if (bNumeric) + // This is a number. Strip out the first char. + rCell.set(aTest); } - else if ( cFirstChar == '\'') // 'Text + if (!bNumeric) + // This is normal text. Take it as-is. + rCell.set(rString); + } + else + { + double nVal; + + do { - bool bNumeric = false; - if (aParam.mbHandleApostrophe) + if (aParam.mbDetectNumberFormat) { - // Cell format is not 'Text', and the first char - // is an apostrophe. Check if the input is considered a number. - String aTest = rString.Copy(1); - double fTest; - bNumeric = aParam.mpNumFormatter->IsNumberFormat(aTest, nIndex, fTest); - if (bNumeric) - // This is a number. Strip out the first char. - aNewCell.set(aTest); - } - if (!bNumeric) - // This is normal text. Take it as-is. - aNewCell.set(rString); - } - else - { - double nVal; + if (!aParam.mpNumFormatter->IsNumberFormat(rString, nIndex, nVal)) + break; - do - { - if (aParam.mbDetectNumberFormat) + if ( aParam.mpNumFormatter ) { - if (!aParam.mpNumFormatter->IsNumberFormat(rString, nIndex, nVal)) - break; + // convert back to the original language if a built-in format was detected + const SvNumberformat* pOldFormat = aParam.mpNumFormatter->GetEntry( nOldIndex ); + if ( pOldFormat ) + nIndex = aParam.mpNumFormatter->GetFormatForLanguageIfBuiltIn( nIndex, pOldFormat->GetLanguage() ); + } - if ( aParam.mpNumFormatter ) - { - // convert back to the original language if a built-in format was detected - const SvNumberformat* pOldFormat = aParam.mpNumFormatter->GetEntry( nOldIndex ); - if ( pOldFormat ) - nIndex = aParam.mpNumFormatter->GetFormatForLanguageIfBuiltIn( nIndex, pOldFormat->GetLanguage() ); - } + rCell.set(nVal); + if ( nIndex != nOldIndex) + { + // #i22345# New behavior: Apply the detected number format only if + // the old one was the default number, date, time or boolean format. + // Exception: If the new format is boolean, always apply it. - aNewCell.set(nVal); - if ( nIndex != nOldIndex) + bool bOverwrite = false; + const SvNumberformat* pOldFormat = aParam.mpNumFormatter->GetEntry( nOldIndex ); + if ( pOldFormat ) { - // #i22345# New behavior: Apply the detected number format only if - // the old one was the default number, date, time or boolean format. - // Exception: If the new format is boolean, always apply it. - - sal_Bool bOverwrite = false; - const SvNumberformat* pOldFormat = aParam.mpNumFormatter->GetEntry( nOldIndex ); - if ( pOldFormat ) + short nOldType = pOldFormat->GetType() & ~NUMBERFORMAT_DEFINED; + if ( nOldType == NUMBERFORMAT_NUMBER || nOldType == NUMBERFORMAT_DATE || + nOldType == NUMBERFORMAT_TIME || nOldType == NUMBERFORMAT_LOGICAL ) { - short nOldType = pOldFormat->GetType() & ~NUMBERFORMAT_DEFINED; - if ( nOldType == NUMBERFORMAT_NUMBER || nOldType == NUMBERFORMAT_DATE || - nOldType == NUMBERFORMAT_TIME || nOldType == NUMBERFORMAT_LOGICAL ) + if ( nOldIndex == aParam.mpNumFormatter->GetStandardFormat( + nOldType, pOldFormat->GetLanguage() ) ) { - if ( nOldIndex == aParam.mpNumFormatter->GetStandardFormat( - nOldType, pOldFormat->GetLanguage() ) ) - { - bOverwrite = true; // default of these types can be overwritten - } + bOverwrite = true; // default of these types can be overwritten } } - if ( !bOverwrite && aParam.mpNumFormatter->GetType( nIndex ) == NUMBERFORMAT_LOGICAL ) - { - bOverwrite = true; // overwrite anything if boolean was detected - } + } + if ( !bOverwrite && aParam.mpNumFormatter->GetType( nIndex ) == NUMBERFORMAT_LOGICAL ) + { + bOverwrite = true; // overwrite anything if boolean was detected + } - if ( bOverwrite ) - { - ApplyAttr( nRow, SfxUInt32Item( ATTR_VALUE_FORMAT, - (sal_uInt32) nIndex) ); - bNumFmtSet = true; - } + if ( bOverwrite ) + { + ApplyAttr( nRow, SfxUInt32Item( ATTR_VALUE_FORMAT, + (sal_uInt32) nIndex) ); + bNumFmtSet = true; } } - else if (aParam.meSetTextNumFormat != ScSetStringParam::Always) - { - // Only check if the string is a regular number. - const LocaleDataWrapper* pLocale = aParam.mpNumFormatter->GetLocaleData(); - if (!pLocale) - break; + } + else if (aParam.meSetTextNumFormat != ScSetStringParam::Always) + { + // Only check if the string is a regular number. + const LocaleDataWrapper* pLocale = aParam.mpNumFormatter->GetLocaleData(); + if (!pLocale) + break; - LocaleDataItem aLocaleItem = pLocale->getLocaleItem(); - const OUString& rDecSep = aLocaleItem.decimalSeparator; - const OUString& rGroupSep = aLocaleItem.thousandSeparator; - if (rDecSep.getLength() != 1 || rGroupSep.getLength() != 1) - break; + LocaleDataItem aLocaleItem = pLocale->getLocaleItem(); + const OUString& rDecSep = aLocaleItem.decimalSeparator; + const OUString& rGroupSep = aLocaleItem.thousandSeparator; + if (rDecSep.getLength() != 1 || rGroupSep.getLength() != 1) + break; - sal_Unicode dsep = rDecSep.getStr()[0]; - sal_Unicode gsep = rGroupSep.getStr()[0]; + sal_Unicode dsep = rDecSep.getStr()[0]; + sal_Unicode gsep = rGroupSep.getStr()[0]; - if (!ScStringUtil::parseSimpleNumber(rString, dsep, gsep, nVal)) - break; + if (!ScStringUtil::parseSimpleNumber(rString, dsep, gsep, nVal)) + break; - aNewCell.set(nVal); - } + rCell.set(nVal); } - while (false); + } + while (false); - if (aNewCell.meType == CELLTYPE_NONE) + if (rCell.meType == CELLTYPE_NONE) + { + if (aParam.meSetTextNumFormat != ScSetStringParam::Never && aParam.mpNumFormatter->IsNumberFormat(rString, nIndex, nVal)) { - if (aParam.meSetTextNumFormat != ScSetStringParam::Never && aParam.mpNumFormatter->IsNumberFormat(rString, nIndex, nVal)) - { - // Set the cell format type to Text. - sal_uInt32 nFormat = aParam.mpNumFormatter->GetStandardFormat(NUMBERFORMAT_TEXT); - ScPatternAttr aNewAttrs(pDocument->GetPool()); - SfxItemSet& rSet = aNewAttrs.GetItemSet(); - rSet.Put( SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat) ); - ApplyPattern(nRow, aNewAttrs); - } - - aNewCell.set(rString); + // Set the cell format type to Text. + sal_uInt32 nFormat = aParam.mpNumFormatter->GetStandardFormat(NUMBERFORMAT_TEXT); + ScPatternAttr aNewAttrs(pDocument->GetPool()); + SfxItemSet& rSet = aNewAttrs.GetItemSet(); + rSet.Put( SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat) ); + ApplyPattern(nRow, aNewAttrs); } + + rCell.set(rString); } } + return bNumFmtSet; +} + +/** + * Returns true if the cell format was set as well + */ +bool ScColumn::SetString( SCROW nRow, SCTAB nTabP, const String& rString, + formula::FormulaGrammar::AddressConvention eConv, + ScSetStringParam* pParam ) +{ + if (!ValidRow(nRow)) + return false; + + ScCellValue aNewCell; + bool bNumFmtSet = ParseString(aNewCell, nRow, nTabP, rString, eConv, pParam); aNewCell.release(*this, nRow); // Do not set Formats and Formulas here anymore! diff --git a/sc/source/core/data/documentimport.cxx b/sc/source/core/data/documentimport.cxx index 679e04f6b040..bfda2f5a0f2f 100644 --- a/sc/source/core/data/documentimport.cxx +++ b/sc/source/core/data/documentimport.cxx @@ -15,13 +15,15 @@ #include "docoptio.hxx" #include "globalnames.hxx" #include "mtvelements.hxx" +#include "tokenarray.hxx" struct ScDocumentImportImpl { ScDocument& mrDoc; sc::ColumnBlockPositionSet maBlockPosSet; + sal_uInt16 mnDefaultScriptNumeric; - ScDocumentImportImpl(ScDocument& rDoc) : mrDoc(rDoc), maBlockPosSet(rDoc) {} + ScDocumentImportImpl(ScDocument& rDoc) : mrDoc(rDoc), maBlockPosSet(rDoc), mnDefaultScriptNumeric(SC_SCRIPTTYPE_UNKNOWN) {} }; ScDocumentImport::ScDocumentImport(ScDocument& rDoc) : mpImpl(new ScDocumentImportImpl(rDoc)) {} @@ -40,6 +42,11 @@ const ScDocument& ScDocumentImport::getDoc() const return mpImpl->mrDoc; } +void ScDocumentImport::setDefaultNumericScript(sal_uInt16 nScript) +{ + mpImpl->mnDefaultScriptNumeric = nScript; +} + SCTAB ScDocumentImport::getSheetIndex(const OUString& rName) const { SCTAB nTab = -1; @@ -78,8 +85,39 @@ void ScDocumentImport::setAutoInput(const ScAddress& rPos, const OUString& rStr) if (!pTab) return; - pTab->aCol[rPos.Col()].SetString( - rPos.Row(), rPos.Tab(), rStr, mpImpl->mrDoc.GetAddressConvention()); + sc::ColumnBlockPosition* pBlockPos = + mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col()); + + if (!pBlockPos) + return; + + ScCellValue aCell; + pTab->aCol[rPos.Col()].ParseString( + aCell, rPos.Row(), rPos.Tab(), rStr, mpImpl->mrDoc.GetAddressConvention(), NULL); + + sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells; + switch (aCell.meType) + { + case CELLTYPE_STRING: + // string is copied. + pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), *aCell.mpString); + break; + case CELLTYPE_EDIT: + // Cell takes the ownership of the text object. + pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.mpEditText); + aCell.mpEditText = NULL; + break; + case CELLTYPE_VALUE: + pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.mfValue); + break; + case CELLTYPE_FORMULA: + // This formula cell instance is directly placed in the document without copying. + pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.mpFormula); + aCell.mpFormula = NULL; + break; + default: + pBlockPos->miCellPos = rCells.set_empty(pBlockPos->miCellPos, rPos.Row(), rPos.Row()); + } } void ScDocumentImport::setNumericCell(const ScAddress& rPos, double fVal) @@ -88,7 +126,14 @@ void ScDocumentImport::setNumericCell(const ScAddress& rPos, double fVal) if (!pTab) return; - pTab->aCol[rPos.Col()].SetValue(rPos.Row(), fVal); + sc::ColumnBlockPosition* pBlockPos = + mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col()); + + if (!pBlockPos) + return; + + sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells; + pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), fVal); } void ScDocumentImport::setStringCell(const ScAddress& rPos, const OUString& rStr) @@ -97,7 +142,30 @@ void ScDocumentImport::setStringCell(const ScAddress& rPos, const OUString& rStr if (!pTab) return; - pTab->aCol[rPos.Col()].SetRawString(rPos.Row(), rStr); + sc::ColumnBlockPosition* pBlockPos = + mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col()); + + if (!pBlockPos) + return; + + sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells; + pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), rStr); +} + +void ScDocumentImport::setEditCell(const ScAddress& rPos, EditTextObject* pEditText) +{ + ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab()); + if (!pTab) + return; + + sc::ColumnBlockPosition* pBlockPos = + mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col()); + + if (!pBlockPos) + return; + + sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells; + pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), pEditText); } void ScDocumentImport::setFormulaCell( @@ -107,8 +175,15 @@ void ScDocumentImport::setFormulaCell( if (!pTab) return; - pTab->aCol[rPos.Col()].SetFormulaCell( - rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, rFormula, eGrammar)); + sc::ColumnBlockPosition* pBlockPos = + mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col()); + + if (!pBlockPos) + return; + + sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells; + pBlockPos->miCellPos = + rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, rFormula, eGrammar)); } void ScDocumentImport::setFormulaCell(const ScAddress& rPos, const ScTokenArray& rArray) @@ -117,8 +192,133 @@ void ScDocumentImport::setFormulaCell(const ScAddress& rPos, const ScTokenArray& if (!pTab) return; - pTab->aCol[rPos.Col()].SetFormulaCell( - rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, &rArray)); + sc::ColumnBlockPosition* pBlockPos = + mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col()); + + if (!pBlockPos) + return; + + sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells; + pBlockPos->miCellPos = + rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, &rArray)); +} + +void ScDocumentImport::setFormulaCell(const ScAddress& rPos, ScFormulaCell* pCell) +{ + ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab()); + if (!pTab) + return; + + sc::ColumnBlockPosition* pBlockPos = + mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col()); + + if (!pBlockPos) + return; + + sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells; + pBlockPos->miCellPos = + rCells.set(pBlockPos->miCellPos, rPos.Row(), pCell); +} + +void ScDocumentImport::setMatrixCells( + const ScRange& rRange, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram) +{ + const ScAddress& rBasePos = rRange.aStart; + + ScTable* pTab = mpImpl->mrDoc.FetchTable(rBasePos.Tab()); + if (!pTab) + return; + + sc::ColumnBlockPosition* pBlockPos = + mpImpl->maBlockPosSet.getBlockPosition(rBasePos.Tab(), rBasePos.Col()); + + if (!pBlockPos) + return; + + sc::CellStoreType& rCells = pTab->aCol[rBasePos.Col()].maCells; + + // Set the master cell. + ScFormulaCell* pCell = new ScFormulaCell(&mpImpl->mrDoc, rBasePos, &rArray, eGram, MM_FORMULA); + + pBlockPos->miCellPos = + rCells.set(pBlockPos->miCellPos, rBasePos.Row(), pCell); + + // Set the reference cells. + ScSingleRefData aRefData; + aRefData.InitFlags(); + aRefData.SetColRel(true); + aRefData.SetRowRel(true); + aRefData.SetTabRel(true); + aRefData.SetAddress(rBasePos, rBasePos); + + ScTokenArray aArr; // consists only of one single reference token. + ScToken* t = static_cast<ScToken*>(aArr.AddMatrixSingleReference(aRefData)); + + ScAddress aPos = rBasePos; + for (SCROW nRow = rRange.aStart.Row()+1; nRow <= rRange.aEnd.Row(); ++nRow) + { + // Token array must be cloned so that each formula cell receives its own copy. + aPos.SetRow(nRow); + // Reference in each cell must point to the origin cell relative to the current cell. + aRefData.SetAddress(rBasePos, aPos); + t->GetSingleRef() = aRefData; + boost::scoped_ptr<ScTokenArray> pTokArr(aArr.Clone()); + pCell = new ScFormulaCell(&mpImpl->mrDoc, aPos, pTokArr.get(), eGram, MM_REFERENCE); + pBlockPos->miCellPos = + rCells.set(pBlockPos->miCellPos, aPos.Row(), pCell); + } + + for (SCCOL nCol = rRange.aStart.Col()+1; nCol <= rRange.aEnd.Col(); ++nCol) + { + pBlockPos = mpImpl->maBlockPosSet.getBlockPosition(rBasePos.Tab(), nCol); + if (!pBlockPos) + return; + + sc::CellStoreType& rColCells = pTab->aCol[nCol].maCells; + + aPos.SetCol(nCol); + for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow) + { + aPos.SetRow(nRow); + aRefData.SetAddress(rBasePos, aPos); + t->GetSingleRef() = aRefData; + boost::scoped_ptr<ScTokenArray> pTokArr(aArr.Clone()); + pCell = new ScFormulaCell(&mpImpl->mrDoc, aPos, pTokArr.get(), eGram, MM_REFERENCE); + pBlockPos->miCellPos = + rColCells.set(pBlockPos->miCellPos, aPos.Row(), pCell); + } + } +} + +namespace { + +class CellTextAttrInitializer +{ + sc::CellTextAttrStoreType maAttrs; + sc::CellTextAttrStoreType::iterator miPos; + sal_uInt16 mnScriptNumeric; +public: + CellTextAttrInitializer(sal_uInt16 nScriptNumeric) : maAttrs(MAXROWCOUNT), miPos(maAttrs.begin()), mnScriptNumeric(nScriptNumeric) {} + + void operator() (const sc::CellStoreType::value_type& node) + { + if (node.type == sc::element_type_empty) + return; + + // Fill with default values for non-empty cell segments. + sc::CellTextAttr aDefault; + if (node.type == sc::element_type_numeric) + aDefault.mnScriptType = mnScriptNumeric; + std::vector<sc::CellTextAttr> aDefaults(node.size, aDefault); + miPos = maAttrs.set(miPos, node.position, aDefaults.begin(), aDefaults.end()); + } + + void swap(sc::CellTextAttrStoreType& rAttrs) + { + maAttrs.swap(rAttrs); + } +}; + } void ScDocumentImport::finalize() @@ -134,11 +334,16 @@ void ScDocumentImport::finalize() ScColumn* pCol = &rTab.aCol[0]; ScColumn* pColEnd = pCol + static_cast<size_t>(MAXCOLCOUNT); for (; pCol != pColEnd; ++pCol) - { - ScColumn& rCol = *pCol; - rCol.ResetCellTextAttrs(); - } + initColumn(*pCol); } } +void ScDocumentImport::initColumn(ScColumn& rCol) +{ + CellTextAttrInitializer aFunc(mpImpl->mnDefaultScriptNumeric); + std::for_each(rCol.maCells.begin(), rCol.maCells.end(), aFunc); + aFunc.swap(rCol.maCellTextAttrs); + rCol.CellStorageModified(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx index 5b1c58fa69a8..318f591dd6f8 100644 --- a/sc/source/filter/xml/xmlcelli.cxx +++ b/sc/source/filter/xml/xmlcelli.cxx @@ -51,6 +51,7 @@ #include "stringutil.hxx" #include "tokenarray.hxx" #include "scmatrix.hxx" +#include "documentimport.hxx" #include <xmloff/xmltkmap.hxx> #include <xmloff/xmltoken.hxx> @@ -1050,10 +1051,10 @@ void ScXMLTableRowCellContext::PutTextCell( const ScAddress& rCurrentPos, } else //regular text cells { - ScDocument* pDoc = rXMLImport.GetDocument(); + ScDocumentImport& rDoc = rXMLImport.GetDoc(); if (maStringValue) { - pDoc->SetTextCell(rCurrentPos, *maStringValue); + rDoc.setStringCell(rCurrentPos, *maStringValue); bDoIncrement = true; } else if (mbEditEngineHasText) @@ -1061,9 +1062,7 @@ void ScXMLTableRowCellContext::PutTextCell( const ScAddress& rCurrentPos, if (maFields.empty() && maFormats.empty() && mpEditEngine->GetParagraphCount() == 1) { // This is a normal text without format runs. - ScSetStringParam aParam; - aParam.setTextInput(); - pDoc->SetString(rCurrentPos, mpEditEngine->GetText(), &aParam); + rDoc.setStringCell(rCurrentPos, mpEditEngine->GetText()); } else { @@ -1083,13 +1082,13 @@ void ScXMLTableRowCellContext::PutTextCell( const ScAddress& rCurrentPos, // This edit engine uses the SfxItemPool instance returned // from pDoc->GetEditPool() to create the text object, which // is a prerequisite for using this constructor of ScEditCell. - pDoc->SetEditText(rCurrentPos, mpEditEngine->CreateTextObject()); + rDoc.setEditCell(rCurrentPos, mpEditEngine->CreateTextObject()); } bDoIncrement = true; } else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() ) { - pDoc->SetTextCell(rCurrentPos, *pOUText); + rDoc.setStringCell(rCurrentPos, *pOUText); bDoIncrement = true; } else @@ -1123,10 +1122,7 @@ void ScXMLTableRowCellContext::PutValueCell( const ScAddress& rCurrentPos ) // style's number format is latin-only. If the cell uses a different // format, the script type will be reset when the style is applied. - ScDocument* pDoc = rXMLImport.GetDocument(); - pDoc->SetValue(rCurrentPos, fValue); - if ( rXMLImport.IsLatinDefaultStyle() ) - pDoc->SetScriptType(rCurrentPos, SCRIPTTYPE_LATIN); + rXMLImport.GetDoc().setNumericCell(rCurrentPos, fValue); } rXMLImport.ProgressBarIncrement(false); } @@ -1324,6 +1320,7 @@ void ScXMLTableRowCellContext::AddNonFormulaCell( const ScAddress& rCellPos ) void ScXMLTableRowCellContext::PutFormulaCell( const ScAddress& rCellPos ) { ScDocument* pDoc = rXMLImport.GetDocument(); + ScDocumentImport& rDoc = rXMLImport.GetDoc(); OUString aText = maFormula->first; OUString aFormulaNmsp = maFormula->second; @@ -1331,7 +1328,6 @@ void ScXMLTableRowCellContext::PutFormulaCell( const ScAddress& rCellPos ) ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard ( new ScExternalRefManager::ApiGuard(pDoc)); - if ( !aText.isEmpty() ) { if ( aText[0] == '=' && aText.getLength() > 1 ) @@ -1342,18 +1338,17 @@ void ScXMLTableRowCellContext::PutFormulaCell( const ScAddress& rCellPos ) if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && !aFormulaNmsp.isEmpty() ) pCode->AddStringXML( aFormulaNmsp ); - pDoc->IncXMLImportedFormulaCount( aText.getLength() ); + rDoc.getDoc().IncXMLImportedFormulaCount( aText.getLength() ); ScFormulaCell* pNewCell = new ScFormulaCell(pDoc, rCellPos, pCode.get(), eGrammar, MM_NONE); SetFormulaCell(pNewCell); - pNewCell = pDoc->SetFormulaCell(rCellPos, pNewCell); - if (pNewCell) - pNewCell->SetNeedNumberFormat( true ); + rDoc.setFormulaCell(rCellPos, pNewCell); + pNewCell->SetNeedNumberFormat( true ); } else if ( aText[0] == '\'' && aText.getLength() > 1 ) { // for bEnglish, "'" at the beginning is always interpreted as text // marker and stripped - pDoc->SetTextCell(rCellPos, aText.copy(1)); + rDoc.setStringCell(rCellPos, aText.copy(1)); } else { @@ -1361,11 +1356,11 @@ void ScXMLTableRowCellContext::PutFormulaCell( const ScAddress& rCellPos ) sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US); double fVal; if ( pFormatter->IsNumberFormat( aText, nEnglish, fVal ) ) - pDoc->SetValue(rCellPos, fVal); + rDoc.setNumericCell(rCellPos, fVal); //the (english) number format will not be set //search matching local format and apply it else - pDoc->SetTextCell(rCellPos, aText); + rDoc.setStringCell(rCellPos, aText); } } } diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx index 3396b01b8235..c1bbd3a0592b 100644 --- a/sc/source/filter/xml/xmlimprt.cxx +++ b/sc/source/filter/xml/xmlimprt.cxx @@ -66,6 +66,7 @@ #include "externalrefmgr.hxx" #include "editutil.hxx" #include "editattributemap.hxx" +#include "documentimport.hxx" #include <comphelper/extract.hxx> @@ -2073,7 +2074,6 @@ ScXMLImport::ScXMLImport( bRemoveLastChar(false), bNullDateSetted(false), bSelfImportingXMLSet(false), - bLatinDefaultStyle(false), bFromWrapper(false), mbHasNewCondFormatData(false) { @@ -2314,6 +2314,11 @@ void ScXMLImport::SetStatistics( } } +ScDocumentImport& ScXMLImport::GetDoc() +{ + return *mpDocImport; +} + sal_Int16 ScXMLImport::GetCellType(const OUString& rStrValue) const { CellTypeMap::const_iterator itr = aCellTypeMap.find(rStrValue); @@ -2420,7 +2425,7 @@ void ScXMLImport::ExamineDefaultStyle() sal_uInt8 nScript = pDoc->GetStringScriptType( aDecSep ); if ( nScript == 0 || nScript == SCRIPTTYPE_LATIN ) - bLatinDefaultStyle = true; + mpDocImport->setDefaultNumericScript(SCRIPTTYPE_LATIN); } } } @@ -2928,6 +2933,7 @@ throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::R if (!pDoc) throw lang::IllegalArgumentException(); + mpDocImport.reset(new ScDocumentImport(*pDoc)); mpComp.reset(new ScCompiler(pDoc, ScAddress())); mpComp->SetGrammar(formula::FormulaGrammar::GRAM_ODFF); @@ -3198,6 +3204,8 @@ throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeE { if (GetModel().is()) { + mpDocImport->finalize(); + uno::Reference<document::XViewDataSupplier> xViewDataSupplier(GetModel(), uno::UNO_QUERY); if (xViewDataSupplier.is()) { diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx index db952dbd510f..d4d45a79db1a 100644 --- a/sc/source/filter/xml/xmlimprt.hxx +++ b/sc/source/filter/xml/xmlimprt.hxx @@ -53,6 +53,7 @@ class ScMyStyleNumberFormats; class XMLNumberFormatAttributesExportHelper; class ScEditEngineDefaulter; +class ScDocumentImport; enum ScXMLDocTokens { @@ -802,6 +803,7 @@ class ScXMLImport: public SvXMLImport, boost::noncopyable CellTypeMap aCellTypeMap; ScDocument* pDoc; + boost::scoped_ptr<ScDocumentImport> mpDocImport; boost::scoped_ptr<ScCompiler> mpComp; // For error-checking of cached string cell values. boost::scoped_ptr<ScEditEngineDefaulter> mpEditEngine; mutable boost::scoped_ptr<ScXMLEditAttributeMap> mpEditAttrMap; @@ -935,7 +937,6 @@ class ScXMLImport: public SvXMLImport, boost::noncopyable bool bRemoveLastChar; bool bNullDateSetted; bool bSelfImportingXMLSet; - bool bLatinDefaultStyle; // latin-only number format in default style? bool bFromWrapper; // called from ScDocShell / ScXMLImportWrapper? bool mbHasNewCondFormatData; @@ -976,6 +977,8 @@ public: virtual void SetStatistics( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue> & i_rStats); + ScDocumentImport& GetDoc(); + inline ScDocument* GetDocument() { return pDoc; } inline const ScDocument* GetDocument() const { return pDoc; } @@ -984,8 +987,6 @@ public: sal_uInt16 GetStyleFamilyMask() const { return nStyleFamilyMask; } bool IsStylesOnlyMode() const { return !bLoadDoc; } - bool IsLatinDefaultStyle() const { return bLatinDefaultStyle; } - sal_Int16 GetCellType(const OUString& rStrValue) const; UniReference < XMLPropertySetMapper > GetCellStylesPropertySetMapper() const { return xCellStylesPropertySetMapper; } diff --git a/sc/source/filter/xml/xmlsubti.cxx b/sc/source/filter/xml/xmlsubti.cxx index b7d8ed3fe372..3cc05839ccd3 100644 --- a/sc/source/filter/xml/xmlsubti.cxx +++ b/sc/source/filter/xml/xmlsubti.cxx @@ -31,6 +31,8 @@ #include "tabprotection.hxx" #include "tokenarray.hxx" #include "convuno.hxx" +#include "documentimport.hxx" + #include <svx/svdpage.hxx> #include <sax/tools/converter.hxx> @@ -279,19 +281,13 @@ void ScMyTables::AddMatrixRange( maMatrixRangeList.Append(aScRange); - ScDocument* pDoc = rImport.GetDocument(); - ScMarkData aMark; - aMark.SetMarkArea( aScRange ); - aMark.SelectTable( aScRange.aStart.Tab(), sal_True ); + ScDocumentImport& rDoc = rImport.GetDoc(); boost::scoped_ptr<ScTokenArray> pCode(new ScTokenArray); pCode->AddStringXML( rFormula ); if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && !rFormulaNmsp.isEmpty() ) pCode->AddStringXML( rFormulaNmsp ); - pDoc->InsertMatrixFormula( - nStartColumn, nStartRow, - nEndColumn, nEndRow, - aMark, EMPTY_OUSTRING, pCode.get(), eGrammar, false ); - pDoc->IncXMLImportedFormulaCount( rFormula.getLength() ); + rDoc.setMatrixCells(aScRange, *pCode, eGrammar); + rDoc.getDoc().IncXMLImportedFormulaCount( rFormula.getLength() ); } bool ScMyTables::IsPartOfMatrix(const ScAddress& rScAddress) const |