| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| |
| |
| |
| // INCLUDE --------------------------------------------------------------- |
| |
| #include "xmltabi.hxx" |
| #include "xmlimprt.hxx" |
| #include "xmlrowi.hxx" |
| #include "xmlcoli.hxx" |
| #include "xmlsceni.hxx" |
| #include "xmlexternaltabi.hxx" |
| #include "document.hxx" |
| #include "docuno.hxx" |
| #include "olinetab.hxx" |
| #include "XMLConverter.hxx" |
| #include "XMLTableShapesContext.hxx" |
| #include "XMLTableSourceContext.hxx" |
| #include "XMLStylesImportHelper.hxx" |
| #include "rangeutl.hxx" |
| #include "externalrefmgr.hxx" |
| #include "sheetdata.hxx" |
| #include "xmlnexpi.hxx" |
| |
| #include <xmloff/xmltkmap.hxx> |
| #include <xmloff/nmspmap.hxx> |
| #include <xmloff/formsimp.hxx> |
| #include <xmloff/xmltoken.hxx> |
| #include <xmloff/XMLEventsImportContext.hxx> |
| |
| #include <tools/urlobj.hxx> |
| |
| #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> |
| #include <com/sun/star/sheet/XSpreadsheets.hpp> |
| #include <com/sun/star/sheet/XSpreadsheet.hpp> |
| #include <com/sun/star/sheet/XPrintAreas.hpp> |
| #include <com/sun/star/table/CellAddress.hpp> |
| |
| using namespace com::sun::star; |
| using namespace xmloff::token; |
| |
| /** |
| * Determine whether this table is an external reference cache from its |
| * name. There is currently no way of determining whether a table is a |
| * regular table or an external reference cache other than examining the |
| * name itself. We should probably introduce a new boolean value for |
| * table:table element and use it instead of doing this, to make it more |
| * reliable and future-proof. |
| * |
| * @param rName |
| * |
| * @return |
| */ |
| static bool lcl_isExternalRefCache(const rtl::OUString& rName, rtl::OUString& rUrl, rtl::OUString& rExtTabName) |
| { |
| // 'file:///path/to/file.ods'#MySheet |
| // 'file:///path/to/file.ods'#MySheet with space |
| // 'file:///path/to/file's.ods'#Sheet (Notice the quote in the file name. |
| // That's allowed.) |
| |
| if ( rName.toChar() != '\'' ) // initial quote |
| return false; |
| |
| // #i114504# Other schemes besides "file:" are also allowed. |
| // CompareProtocolScheme is quick, only looks at the start of the string. |
| INetProtocol eProt = INetURLObject::CompareProtocolScheme( rName.copy(1) ); |
| if ( eProt == INET_PROT_NOT_VALID ) |
| return false; |
| |
| rtl::OUString aPrefix = INetURLObject::GetScheme( eProt ); |
| sal_Int32 nPrefLen = aPrefix.getLength(); |
| |
| rtl::OUStringBuffer aUrlBuf, aTabNameBuf; |
| aUrlBuf.append( aPrefix ); |
| sal_Int32 n = rName.getLength(); |
| const sal_Unicode* p = rName.getStr(); |
| |
| bool bInUrl = true; |
| sal_Unicode cPrev = 0; |
| for (sal_Int32 i = nPrefLen+1; i < n; ++i) // start the loop after quote and prefix |
| { |
| const sal_Unicode c = p[i]; |
| if (bInUrl) |
| { |
| // parsing file URL |
| if (c == '#') |
| { |
| if (cPrev != '\'') |
| return false; |
| |
| rUrl = aUrlBuf.makeStringAndClear(); |
| rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote. |
| bInUrl = false; |
| } |
| else |
| aUrlBuf.append(c); |
| } |
| else |
| // parsing sheet name. |
| aTabNameBuf.append(c); |
| |
| cPrev = c; |
| } |
| |
| if (bInUrl) |
| return false; |
| |
| if (aTabNameBuf.getLength() == 0) |
| return false; |
| |
| rExtTabName = aTabNameBuf.makeStringAndClear(); |
| |
| return true; |
| } |
| |
| ScXMLExternalTabData::ScXMLExternalTabData() : |
| mpCacheTable(), mnRow(0), mnCol(0), mnFileId(0) |
| { |
| } |
| |
| //------------------------------------------------------------------ |
| |
| ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport, |
| sal_uInt16 nPrfx, |
| const ::rtl::OUString& rLName, |
| const ::com::sun::star::uno::Reference< |
| ::com::sun::star::xml::sax::XAttributeList>& xAttrList, |
| const sal_Bool bTempIsSubTable, |
| 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); |
| rtl::OUString sName; |
| rtl::OUString sStyleName; |
| rtl::OUString sPassword; |
| sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0); |
| const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableAttrTokenMap(); |
| for( sal_Int16 i=0; i < nAttrCount; ++i ) |
| { |
| const rtl::OUString& sAttrName(xAttrList->getNameByIndex( i )); |
| rtl::OUString aLocalName; |
| sal_uInt16 nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName( |
| sAttrName, &aLocalName )); |
| const rtl::OUString& sValue(xAttrList->getValueByIndex( i )); |
| |
| switch( rAttrTokenMap.Get( nPrefix, aLocalName ) ) |
| { |
| case XML_TOK_TABLE_NAME: |
| sName = sValue; |
| break; |
| case XML_TOK_TABLE_STYLE_NAME: |
| sStyleName = sValue; |
| break; |
| case XML_TOK_TABLE_PROTECTION: |
| bProtection = IsXMLToken(sValue, XML_TRUE); |
| break; |
| case XML_TOK_TABLE_PRINT_RANGES: |
| sPrintRanges = sValue; |
| break; |
| case XML_TOK_TABLE_PASSWORD: |
| sPassword = sValue; |
| break; |
| case XML_TOK_TABLE_PRINT: |
| { |
| if (IsXMLToken(sValue, XML_FALSE)) |
| bPrintEntireSheet = sal_False; |
| } |
| break; |
| } |
| } |
| |
| rtl::OUString aExtUrl, aExtTabName; |
| if (lcl_isExternalRefCache(sName, aExtUrl, aExtTabName)) |
| { |
| // This is an external ref cache table. |
| pExternalRefInfo.reset(new ScXMLExternalTabData); |
| pExternalRefInfo->maFileUrl = aExtUrl; |
| ScDocument* pDoc = GetScImport().GetDocument(); |
| if (pDoc) |
| { |
| ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager(); |
| pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl); |
| pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName, true); |
| pExternalRefInfo->mpCacheTable->setWholeTableCached(); |
| } |
| } |
| else |
| { |
| // This is a regular table. |
| GetScImport().GetTables().NewSheet(sName, sStyleName, bProtection, sPassword); |
| } |
| } |
| else |
| { |
| GetScImport().GetTables().NewTable(nSpannedCols); |
| } |
| } |
| |
| ScXMLTableContext::~ScXMLTableContext() |
| { |
| } |
| |
| SvXMLImportContext *ScXMLTableContext::CreateChildContext( sal_uInt16 nPrefix, |
| const ::rtl::OUString& rLName, |
| const ::com::sun::star::uno::Reference< |
| ::com::sun::star::xml::sax::XAttributeList>& xAttrList ) |
| { |
| const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap()); |
| sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLName); |
| if (pExternalRefInfo.get()) |
| { |
| // We only care about the table-row and table-source elements for |
| // external cache data. |
| switch (nToken) |
| { |
| case XML_TOK_TABLE_ROW_GROUP: |
| case XML_TOK_TABLE_HEADER_ROWS: |
| case XML_TOK_TABLE_ROWS: |
| // #i101319# don't discard rows in groups or header (repeat range) |
| return new ScXMLExternalRefRowsContext( |
| GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo); |
| case XML_TOK_TABLE_ROW: |
| return new ScXMLExternalRefRowContext( |
| GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo); |
| case XML_TOK_TABLE_SOURCE: |
| return new ScXMLExternalRefTabSourceContext( |
| GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo); |
| default: |
| ; |
| } |
| |
| return new SvXMLImportContext(GetImport(), nPrefix, rLName); |
| } |
| |
| SvXMLImportContext *pContext(0); |
| |
| switch (nToken) |
| { |
| case XML_TOK_TABLE_COL_GROUP: |
| pContext = new ScXMLTableColsContext( GetScImport(), nPrefix, |
| rLName, xAttrList, |
| sal_False, sal_True ); |
| break; |
| case XML_TOK_TABLE_HEADER_COLS: |
| pContext = new ScXMLTableColsContext( GetScImport(), nPrefix, |
| rLName, xAttrList, |
| sal_True, sal_False ); |
| break; |
| case XML_TOK_TABLE_COLS: |
| pContext = new ScXMLTableColsContext( GetScImport(), nPrefix, |
| rLName, xAttrList, |
| sal_False, sal_False ); |
| break; |
| case XML_TOK_TABLE_COL: |
| pContext = new ScXMLTableColContext( GetScImport(), nPrefix, |
| rLName, xAttrList ); |
| break; |
| case XML_TOK_TABLE_ROW_GROUP: |
| pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix, |
| rLName, xAttrList, |
| sal_False, sal_True ); |
| break; |
| case XML_TOK_TABLE_HEADER_ROWS: |
| pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix, |
| rLName, xAttrList, |
| sal_True, sal_False ); |
| break; |
| case XML_TOK_TABLE_ROWS: |
| pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix, |
| rLName, xAttrList, |
| sal_False, sal_False ); |
| break; |
| case XML_TOK_TABLE_ROW: |
| pContext = new ScXMLTableRowContext( GetScImport(), nPrefix, |
| rLName, xAttrList//, |
| //this |
| ); |
| break; |
| case XML_TOK_TABLE_SOURCE: |
| pContext = new ScXMLTableSourceContext( GetScImport(), nPrefix, rLName, xAttrList); |
| break; |
| case XML_TOK_TABLE_SCENARIO: |
| pContext = new ScXMLTableScenarioContext( GetScImport(), nPrefix, rLName, xAttrList); |
| break; |
| case XML_TOK_TABLE_SHAPES: |
| pContext = new ScXMLTableShapesContext( GetScImport(), nPrefix, rLName, xAttrList); |
| break; |
| case XML_TOK_TABLE_FORMS: |
| { |
| GetScImport().GetFormImport()->startPage(GetScImport().GetTables().GetCurrentXDrawPage()); |
| bStartFormPage = sal_True; |
| pContext = GetScImport().GetFormImport()->createOfficeFormsContext( GetScImport(), nPrefix, rLName ); |
| } |
| break; |
| case XML_TOK_TABLE_NAMED_EXPRESSIONS: |
| { |
| SCTAB nCurrentSheet = static_cast<SCTAB>(GetScImport().GetTables().GetCurrentSheet()); |
| pContext = new ScXMLNamedExpressionsContext ( GetScImport(), nPrefix, rLName, xAttrList );//worksheetname |
| static_cast<ScXMLNamedExpressionsContext*>(pContext)->SetScope( nCurrentSheet ); |
| } |
| break; |
| case XML_TOK_TABLE_EVENT_LISTENERS: |
| case XML_TOK_TABLE_EVENT_LISTENERS_EXT: |
| { |
| // use XEventsSupplier interface of the sheet |
| uno::Reference<document::XEventsSupplier> xSupplier( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY ); |
| pContext = new XMLEventsImportContext( GetImport(), nPrefix, rLName, xSupplier ); |
| } |
| break; |
| default: |
| ; |
| } |
| |
| if( !pContext ) |
| pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName ); |
| |
| return pContext; |
| } |
| |
| void ScXMLTableContext::EndElement() |
| { |
| // get end offset in file (if available) |
| // sal_Int32 nEndOffset = GetScImport().GetByteOffset(); |
| |
| GetScImport().LockSolarMutex(); |
| GetScImport().GetStylesImportHelper()->EndTable(); |
| ScDocument* pDoc(GetScImport().GetDocument()); |
| if (pDoc) |
| { |
| if (sPrintRanges.getLength()) |
| { |
| uno::Reference< sheet::XPrintAreas > xPrintAreas( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY ); |
| if( xPrintAreas.is() ) |
| { |
| uno::Sequence< table::CellRangeAddress > aRangeList; |
| ScRangeStringConverter::GetRangeListFromString( aRangeList, sPrintRanges, pDoc, ::formula::FormulaGrammar::CONV_OOO ); |
| xPrintAreas->setPrintAreas( aRangeList ); |
| } |
| } |
| else if (bPrintEntireSheet) pDoc->SetPrintEntireSheet(static_cast<SCTAB>(GetScImport().GetTables().GetCurrentSheet())); |
| |
| ScOutlineTable* pOutlineTable(pDoc->GetOutlineTable(static_cast<SCTAB>(GetScImport().GetTables().GetCurrentSheet()), sal_False)); |
| if (pOutlineTable) |
| { |
| ScOutlineArray* pColArray(pOutlineTable->GetColArray()); |
| sal_Int32 nDepth(pColArray->GetDepth()); |
| sal_Int32 i; |
| for (i = 0; i < nDepth; ++i) |
| { |
| sal_Int32 nCount(pColArray->GetCount(static_cast<sal_uInt16>(i))); |
| for (sal_Int32 j = 0; j < nCount; ++j) |
| { |
| ScOutlineEntry* pEntry(pColArray->GetEntry(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j))); |
| if (pEntry->IsHidden()) |
| pColArray->SetVisibleBelow(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j), sal_False); |
| } |
| } |
| ScOutlineArray* pRowArray(pOutlineTable->GetRowArray()); |
| nDepth = pRowArray->GetDepth(); |
| for (i = 0; i < nDepth; ++i) |
| { |
| sal_Int32 nCount(pRowArray->GetCount(static_cast<sal_uInt16>(i))); |
| for (sal_Int32 j = 0; j < nCount; ++j) |
| { |
| ScOutlineEntry* pEntry(pRowArray->GetEntry(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j))); |
| if (pEntry->IsHidden()) |
| pRowArray->SetVisibleBelow(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j), sal_False); |
| } |
| } |
| } |
| if (GetScImport().GetTables().HasDrawPage()) |
| { |
| if (GetScImport().GetTables().HasXShapes()) |
| { |
| GetScImport().GetShapeImport()->popGroupAndSort(); |
| uno::Reference < drawing::XShapes > xTempShapes(GetScImport().GetTables().GetCurrentXShapes()); |
| GetScImport().GetShapeImport()->endPage(xTempShapes); |
| } |
| if (bStartFormPage) |
| GetScImport().GetFormImport()->endPage(); |
| } |
| |
| 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(); |
| } |
| |