blob: 9621e8f094c79a873a528a41288eb8bee10c7b81 [file] [log] [blame]
/**************************************************************
*
* 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();
}