diff options
Diffstat (limited to 'sc/source/filter/xml/XMLExportDatabaseRanges.cxx')
-rw-r--r-- | sc/source/filter/xml/XMLExportDatabaseRanges.cxx | 752 |
1 files changed, 752 insertions, 0 deletions
diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx new file mode 100644 index 000000000..61c01d236 --- /dev/null +++ b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx @@ -0,0 +1,752 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <memory> +#include "XMLExportDatabaseRanges.hxx" +#include <xmloff/xmltoken.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/namespacemap.hxx> +#include <sax/tools/converter.hxx> +#include "xmlexprt.hxx" +#include "XMLExportIterator.hxx" +#include "XMLConverter.hxx" +#include <unonames.hxx> +#include <dbdata.hxx> +#include <document.hxx> +#include <globalnames.hxx> +#include "XMLExportSharedData.hxx" +#include <rangeutl.hxx> +#include <subtotalparam.hxx> +#include <queryparam.hxx> +#include <queryentry.hxx> +#include <sortparam.hxx> + +#include <svx/dataaccessdescriptor.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/sheet/DataImportMode.hpp> +#include <com/sun/star/sheet/XDatabaseRanges.hpp> +#include <com/sun/star/sheet/XDatabaseRange.hpp> +#include <comphelper/extract.hxx> +#include <osl/diagnose.h> + +#include <map> + +//! not found in unonames.hxx +constexpr OUStringLiteral SC_USERLIST = u"UserList"; + +using namespace com::sun::star; +using namespace xmloff::token; + +void writeSort(ScXMLExport& mrExport, const ScSortParam& aParam, const ScRange& aRange, const ScDocument* mpDoc) +{ + // Count sort items first. + size_t nSortCount = 0; + for (; nSortCount < aParam.GetSortKeyCount(); ++nSortCount) + { + if (!aParam.maKeyState[nSortCount].bDoSort) + break; + } + + if (!nSortCount) + // Nothing to export. + return; + + ScAddress aOutPos(aParam.nDestCol, aParam.nDestRow, aParam.nDestTab); + + if (!aParam.aDataAreaExtras.mbCellFormats) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_BIND_STYLES_TO_CONTENT, XML_FALSE); + + if (!aParam.bInplace) + { + OUString aStr; + ScRangeStringConverter::GetStringFromAddress( + aStr, aOutPos, mpDoc, ::formula::FormulaGrammar::CONV_OOO); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aStr); + } + + if (aParam.bCaseSens) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE); + + mrExport.AddLanguageTagAttributes( XML_NAMESPACE_TABLE, XML_NAMESPACE_TABLE, aParam.aCollatorLocale, false); + if (!aParam.aCollatorAlgorithm.isEmpty()) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ALGORITHM, aParam.aCollatorAlgorithm); + + SvXMLElementExport aElemS(mrExport, XML_NAMESPACE_TABLE, XML_SORT, true, true); + + SCCOLROW nFieldStart = aParam.bByRow ? aRange.aStart.Col() : aRange.aStart.Row(); + + for (size_t i = 0; i < nSortCount; ++i) + { + // Convert field value from absolute to relative. + SCCOLROW nField = aParam.maKeyState[i].nField - nFieldStart; + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(nField)); + + if (!aParam.maKeyState[i].bAscending) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORDER, XML_DESCENDING); + + if (aParam.bUserDef) + { + OUString aBuf = SC_USERLIST + OUString::number(static_cast<sal_Int32>(aParam.nUserIndex)); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, aBuf); + } + else + { + // Right now we only support automatic field type. In the + // future we may support numeric or alphanumeric field type. + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, XML_AUTOMATIC); + } + + SvXMLElementExport aElemSb(mrExport, XML_NAMESPACE_TABLE, XML_SORT_BY, true, true); + } +} + +ScXMLExportDatabaseRanges::ScXMLExportDatabaseRanges(ScXMLExport& rTempExport) + : rExport(rTempExport), + pDoc( nullptr ) +{ +} + +ScMyEmptyDatabaseRangesContainer ScXMLExportDatabaseRanges::GetEmptyDatabaseRanges() +{ + ScMyEmptyDatabaseRangesContainer aSkipRanges; + if (rExport.GetModel().is()) + { + uno::Reference <beans::XPropertySet> xPropertySet (rExport.GetModel(), uno::UNO_QUERY); + if (xPropertySet.is()) + { + uno::Reference <sheet::XDatabaseRanges> xDatabaseRanges(xPropertySet->getPropertyValue(SC_UNO_DATABASERNG), uno::UNO_QUERY); + rExport.CheckAttrList(); + if (xDatabaseRanges.is()) + { + const uno::Sequence <OUString> aRanges(xDatabaseRanges->getElementNames()); + for (const OUString& sDatabaseRangeName : aRanges) + { + uno::Reference <sheet::XDatabaseRange> xDatabaseRange(xDatabaseRanges->getByName(sDatabaseRangeName), uno::UNO_QUERY); + if (xDatabaseRange.is()) + { + uno::Reference <beans::XPropertySet> xDatabaseRangePropertySet (xDatabaseRange, uno::UNO_QUERY); + if (xDatabaseRangePropertySet.is() && + ::cppu::any2bool(xDatabaseRangePropertySet->getPropertyValue(SC_UNONAME_STRIPDAT))) + { + const uno::Sequence <beans::PropertyValue> aImportProperties(xDatabaseRange->getImportDescriptor()); + sheet::DataImportMode nSourceType = sheet::DataImportMode_NONE; + for (const auto& rProp : aImportProperties) + if ( rProp.Name == SC_UNONAME_SRCTYPE ) + rProp.Value >>= nSourceType; + if (nSourceType != sheet::DataImportMode_NONE) + { + table::CellRangeAddress aArea = xDatabaseRange->getDataArea(); + aSkipRanges.AddNewEmptyDatabaseRange(aArea); + + // #105276#; set last row/column so default styles are collected + rExport.GetSharedData()->SetLastColumn(aArea.Sheet, aArea.EndColumn); + rExport.GetSharedData()->SetLastRow(aArea.Sheet, aArea.EndRow); + } + } + } + } + } + } + } + return aSkipRanges; +} + +namespace { + +class WriteDatabaseRange +{ + ScXMLExport& mrExport; + ScDocument* mpDoc; + sal_Int32 mnCounter; + ScDBCollection::RangeType meRangeType; +public: + + WriteDatabaseRange(ScXMLExport& rExport, ScDocument* pDoc) : + mrExport(rExport), mpDoc(pDoc), mnCounter(0), meRangeType(ScDBCollection::GlobalNamed) {} + + void setRangeType(ScDBCollection::RangeType eNew) + { + meRangeType = eNew; + } + + void operator() (const ::std::pair<SCTAB, const ScDBData*>& r) + { + if (meRangeType != ScDBCollection::SheetAnonymous) + return; + + // name + OUString aBuf = STR_DB_LOCAL_NONAME + + OUString::number(static_cast<sal_Int32>(r.first)); // appended number equals sheet index on import. + + write(aBuf, *r.second); + } + + void operator() (const ScDBData& rData) + { + if (meRangeType == ScDBCollection::GlobalAnonymous) + { + // name + OUString aBuf = STR_DB_GLOBAL_NONAME + OUString::number(++mnCounter); // 1-based, for entirely arbitrary reasons. The numbers are ignored on import. + + write(aBuf, rData); + } + else if (meRangeType == ScDBCollection::GlobalNamed) + write(rData.GetName(), rData); + } + + void operator() (std::unique_ptr<ScDBData> const& p) + { + return operator()(*p); + } + +private: + void write(const OUString& rName, const ScDBData& rData) + { + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, rName); + + // range + ScRange aRange; + rData.GetArea(aRange); + OUString aRangeStr; + ScRangeStringConverter::GetStringFromRange( + aRangeStr, aRange, mpDoc, ::formula::FormulaGrammar::CONV_OOO); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aRangeStr); + + // various boolean flags. + if (rData.HasImportSelection()) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IS_SELECTION, XML_TRUE); + if (rData.HasAutoFilter()) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_FILTER_BUTTONS, XML_TRUE); + if (rData.IsKeepFmt()) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ON_UPDATE_KEEP_STYLES, XML_TRUE); + if (rData.IsDoSize()) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ON_UPDATE_KEEP_SIZE, XML_FALSE); + if (rData.IsStripData()) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_HAS_PERSISTENT_DATA, XML_FALSE); + + ScQueryParam aQueryParam; + rData.GetQueryParam(aQueryParam); + if (!aQueryParam.bHasHeader) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONTAINS_HEADER, XML_FALSE); + + ScSortParam aSortParam; + rData.GetSortParam(aSortParam); + if (!aSortParam.bByRow) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORIENTATION, XML_COLUMN); + + sal_Int32 nRefreshDelaySeconds = rData.GetRefreshDelaySeconds(); + if (nRefreshDelaySeconds) + { + OUStringBuffer aBuf; + ::sax::Converter::convertDuration(aBuf, + static_cast<double>(nRefreshDelaySeconds) / 86400.0); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_REFRESH_DELAY, aBuf.makeStringAndClear()); + } + + SvXMLElementExport aElemDR(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_RANGE, true, true); + + ScSortParam aParam; + rData.GetSortParam(aParam); + + writeImport(rData); + writeFilter(rData); + writeSort(mrExport, aParam, aRange, mpDoc); + writeSubtotals(rData); + } + + void writeImport(const ScDBData& rData) + { + ScImportParam aParam; + rData.GetImportParam(aParam); + + OUString sDatabaseName; + OUString sConRes; + + svx::ODataAccessDescriptor aDescriptor; + aDescriptor.setDataSource(aParam.aDBName); + if (aDescriptor.has(svx::DataAccessDescriptorProperty::DataSource)) + { + sDatabaseName = aParam.aDBName; + } + else if (aDescriptor.has(svx::DataAccessDescriptorProperty::ConnectionResource)) + { + sConRes = aParam.aDBName; + } + + sheet::DataImportMode nSourceType = sheet::DataImportMode_NONE; + if (aParam.bImport) + { + if (aParam.bSql) + nSourceType = sheet::DataImportMode_SQL; + else if (aParam.nType == ScDbQuery) + nSourceType = sheet::DataImportMode_QUERY; + else + nSourceType = sheet::DataImportMode_TABLE; + } + + switch (nSourceType) + { + case sheet::DataImportMode_NONE : break; + case sheet::DataImportMode_QUERY : + { + if (!sDatabaseName.isEmpty()) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_QUERY_NAME, aParam.aStatement); + SvXMLElementExport aElemID(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_QUERY, true, true); + if (!sConRes.isEmpty()) + { + mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes ); + SvXMLElementExport aElemCR(mrExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, true, true); + } + } + break; + case sheet::DataImportMode_TABLE : + { + if (!sDatabaseName.isEmpty()) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_TABLE_NAME, aParam.aStatement); + SvXMLElementExport aElemID(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_TABLE, true, true); + if (!sConRes.isEmpty()) + { + mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes ); + SvXMLElementExport aElemCR(mrExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, true, true); + } + } + break; + case sheet::DataImportMode_SQL : + { + if (!sDatabaseName.isEmpty()) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, sDatabaseName); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SQL_STATEMENT, aParam.aStatement); + if (!aParam.bNative) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PARSE_SQL_STATEMENT, XML_TRUE); + SvXMLElementExport aElemID(mrExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_SQL, true, true); + if (!sConRes.isEmpty()) + { + mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sConRes ); + SvXMLElementExport aElemCR(mrExport, XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE, true, true); + } + } + break; + default: + { + // added to avoid warnings + } + } + } + + static OUString getOperatorXML(const ScQueryEntry& rEntry, utl::SearchParam::SearchType eSearchType) + { + switch (rEntry.eOp) + { + case SC_BEGINS_WITH: + return GetXMLToken(XML_BEGINS_WITH); + case SC_BOTPERC: + return GetXMLToken(XML_BOTTOM_PERCENT); + case SC_BOTVAL: + return GetXMLToken(XML_BOTTOM_VALUES); + case SC_CONTAINS: + return GetXMLToken(XML_CONTAINS); + case SC_DOES_NOT_BEGIN_WITH: + return GetXMLToken(XML_DOES_NOT_BEGIN_WITH); + case SC_DOES_NOT_CONTAIN: + return GetXMLToken(XML_DOES_NOT_CONTAIN); + case SC_DOES_NOT_END_WITH: + return GetXMLToken(XML_DOES_NOT_END_WITH); + case SC_ENDS_WITH: + return GetXMLToken(XML_ENDS_WITH); + case SC_EQUAL: + { + if (rEntry.IsQueryByEmpty()) + return GetXMLToken(XML_EMPTY); + else if (rEntry.IsQueryByNonEmpty()) + return GetXMLToken(XML_NOEMPTY); + + if (eSearchType == utl::SearchParam::SearchType::Regexp) + return GetXMLToken(XML_MATCH); + else + return "="; + } + case SC_GREATER: + return ">"; + case SC_GREATER_EQUAL: + return ">="; + case SC_LESS: + return "<"; + case SC_LESS_EQUAL: + return "<="; + case SC_NOT_EQUAL: + if (eSearchType == utl::SearchParam::SearchType::Regexp) + return GetXMLToken(XML_NOMATCH); + else + return "!="; + case SC_TOPPERC: + return GetXMLToken(XML_TOP_PERCENT); + case SC_TOPVAL: + return GetXMLToken(XML_TOP_VALUES); + default: + ; + } + return "="; + } + + class WriteSetItem + { + ScXMLExport& mrExport; + public: + explicit WriteSetItem(ScXMLExport& r) : mrExport(r) {} + void operator() (const ScQueryEntry::Item& rItem) const + { + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString()); + SvXMLElementExport aElem(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_SET_ITEM, true, true); + } + }; + + void writeCondition(const ScQueryEntry& rEntry, SCCOLROW nFieldStart, bool bCaseSens, + utl::SearchParam::SearchType eSearchType) + { + const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems(); + if (rItems.empty()) + { + OSL_FAIL("Query entry has no items at all! It must have at least one!"); + return; + } + + if (rItems.size() == 1) + { + // Single item condition. + const ScQueryEntry::Item& rItem = rItems.front(); + if (rItem.meType == ScQueryEntry::ByString) + { + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString()); + } + else if (rItem.meType == ScQueryEntry::ByDate) + { + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString()); + } + else if (rItem.meType == ScQueryEntry::ByTextColor + || rItem.meType == ScQueryEntry::ByBackgroundColor) + { + if (mrExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) + { + if (rItem.meType == ScQueryEntry::ByTextColor) + mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATA_TYPE, XML_TEXT_COLOR); + else + mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATA_TYPE, + XML_BACKGROUND_COLOR); + } + + OUString colorValue; + if (rItem.maColor == COL_AUTO) // tdf#142965 + { + colorValue = rItem.meType == ScQueryEntry::ByTextColor + ? GetXMLToken(XML_WINDOW_FONT_COLOR) + : GetXMLToken(XML_TRANSPARENT); + } + else + { + OUStringBuffer buffer; + sax::Converter::convertColor(buffer, rItem.maColor); + colorValue = buffer.makeStringAndClear(); + } + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, colorValue); + } + else + { + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, XML_NUMBER); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString()); + } + + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, getOperatorXML(rEntry, eSearchType)); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(rEntry.nField - nFieldStart)); + if (bCaseSens) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE); + SvXMLElementExport aElemC(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, true, true); + } + else + { + // Multi-item condition. + assert( rItems.size() > 1 && "rItems should have more than 1 element"); + + // Store the 1st value for backward compatibility. + const ScQueryEntry::Item& rItem = rItems.front(); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString()); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, OUString("=")); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(rEntry.nField - nFieldStart)); + if (bCaseSens) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE); + SvXMLElementExport aElemC(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, true, true); + + std::for_each(rItems.begin(), rItems.end(), WriteSetItem(mrExport)); + } + } + + void writeFilter(const ScDBData& rData) + { + ScQueryParam aParam; + rData.GetQueryParam(aParam); + size_t nCount = 0; + for (size_t n = aParam.GetEntryCount(); nCount < n; ++nCount) + { + if (!aParam.GetEntry(nCount).bDoQuery) + break; + } + + if (!nCount) + // No filter criteria to save. Bail out. + return; + + if (!aParam.bInplace) + { + OUString aAddrStr; + ScRangeStringConverter::GetStringFromAddress( + aAddrStr, ScAddress(aParam.nDestCol, aParam.nDestRow, aParam.nDestTab), mpDoc, ::formula::FormulaGrammar::CONV_OOO); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, aAddrStr); + } + + ScRange aAdvSource; + if (rData.GetAdvancedQuerySource(aAdvSource)) + { + OUString aAddrStr; + ScRangeStringConverter::GetStringFromRange( + aAddrStr, aAdvSource, mpDoc, ::formula::FormulaGrammar::CONV_OOO); + if (!aAddrStr.isEmpty()) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONDITION_SOURCE_RANGE_ADDRESS, aAddrStr); + } + + if (!aParam.bDuplicate) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_DUPLICATES, XML_FALSE); + + SvXMLElementExport aElemF(mrExport, XML_NAMESPACE_TABLE, XML_FILTER, true, true); + + bool bAnd = false; + bool bOr = false; + + for (size_t i = 0; i < nCount; ++i) + { + const ScQueryEntry& rEntry = aParam.GetEntry(i); + if (rEntry.eConnect == SC_AND) + bAnd = true; + else + bOr = true; + } + + // Note that export field index values are relative to the first field. + ScRange aRange; + rData.GetArea(aRange); + SCCOLROW nFieldStart = aParam.bByRow ? aRange.aStart.Col() : aRange.aStart.Row(); + + if (bOr && !bAnd) + { + SvXMLElementExport aElemOr(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, true, true); + for (size_t i = 0; i < nCount; ++i) + writeCondition(aParam.GetEntry(i), nFieldStart, aParam.bCaseSens, aParam.eSearchType); + } + else if (bAnd && !bOr) + { + SvXMLElementExport aElemAnd(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_AND, true, true); + for (size_t i = 0; i < nCount; ++i) + writeCondition(aParam.GetEntry(i), nFieldStart, aParam.bCaseSens, aParam.eSearchType); + } + else if (nCount == 1) + { + writeCondition(aParam.GetEntry(0), nFieldStart, aParam.bCaseSens, aParam.eSearchType); + } + else + { + SvXMLElementExport aElemC(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, true, true); + ScQueryEntry aPrevEntry = aParam.GetEntry(0); + ScQueryConnect eConnect = aParam.GetEntry(1).eConnect; + bool bOpenAndElement = false; + OUString aName = mrExport.GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TABLE, GetXMLToken(XML_FILTER_AND)); + + if (eConnect == SC_AND) + { + mrExport.StartElement(aName, true); + bOpenAndElement = true; + } + else + bOpenAndElement = false; + + for (size_t i = 1; i < nCount; ++i) + { + const ScQueryEntry& rEntry = aParam.GetEntry(i); + if (eConnect != rEntry.eConnect) + { + eConnect = rEntry.eConnect; + if (rEntry.eConnect == SC_AND) + { + mrExport.StartElement(aName, true ); + bOpenAndElement = true; + writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType); + aPrevEntry = rEntry; + if (i == nCount - 1) + { + writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType); + mrExport.EndElement(aName, true); + bOpenAndElement = false; + } + } + else + { + writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType); + aPrevEntry = rEntry; + if (bOpenAndElement) + { + mrExport.EndElement(aName, true); + bOpenAndElement = false; + } + if (i == nCount - 1) + writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType); + } + } + else + { + writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType); + aPrevEntry = rEntry; + if (i == nCount - 1) + writeCondition(aPrevEntry, nFieldStart, aParam.bCaseSens, aParam.eSearchType); + } + } + if(bOpenAndElement) + mrExport.EndElement(aName, true); + } + } + + void writeSubtotals(const ScDBData& rData) + { + ScSubTotalParam aParam; + rData.GetSubTotalParam(aParam); + + size_t nCount = 0; + for (; nCount < MAXSUBTOTAL; ++nCount) + { + if (!aParam.bGroupActive[nCount]) + break; + } + + if (!nCount) + return; + + if (!aParam.bIncludePattern) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_BIND_STYLES_TO_CONTENT, XML_FALSE); + + if (aParam.bPagebreak) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PAGE_BREAKS_ON_GROUP_CHANGE, XML_TRUE); + + if (aParam.bCaseSens) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE); + + SvXMLElementExport aElemSTRs(mrExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_RULES, true, true); + + if (aParam.bDoSort) + { + if (!aParam.bAscending) + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORDER, XML_DESCENDING); + + if (aParam.bUserDef) + { + OUString aBuf = SC_USERLIST + OUString::number(static_cast<sal_Int32>(aParam.nUserIndex)); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, aBuf); + } + SvXMLElementExport aElemSGs(mrExport, XML_NAMESPACE_TABLE, XML_SORT_GROUPS, true, true); + } + + for (size_t i = 0; i < MAXSUBTOTAL; ++i) + { + if (!aParam.bGroupActive[i]) + // We're done! + break; + + sal_Int32 nFieldCol = static_cast<sal_Int32>(aParam.nField[i]); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUP_BY_FIELD_NUMBER, OUString::number(nFieldCol)); + SvXMLElementExport aElemSTR(mrExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_RULE, true, true); + + for (SCCOL j = 0, n = aParam.nSubTotals[i]; j < n; ++j) + { + sal_Int32 nCol = static_cast<sal_Int32>(aParam.pSubTotals[i][j]); + ScSubTotalFunc eFunc = aParam.pFunctions[i][j]; + + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(nCol)); + OUString aFuncStr = ScXMLConverter::GetStringFromFunction(eFunc); + mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FUNCTION, aFuncStr); + + SvXMLElementExport aElemSTF(mrExport, XML_NAMESPACE_TABLE, XML_SUBTOTAL_FIELD, true, true); + } + } + } +}; + +} + +void ScXMLExportDatabaseRanges::WriteDatabaseRanges() +{ + pDoc = rExport.GetDocument(); + if (!pDoc) + return; + + // Get sheet-local anonymous ranges. + SCTAB nTabCount = pDoc->GetTableCount(); + std::map<SCTAB, const ScDBData*> aSheetDBs; + for (SCTAB i = 0; i < nTabCount; ++i) + { + const ScDBData* p = pDoc->GetAnonymousDBData(i); + if (p) + aSheetDBs.emplace(i, p); + } + + bool bHasRanges = !aSheetDBs.empty(); + + // See if we have global ranges. + ScDBCollection* pDBCollection = pDoc->GetDBCollection(); + if (pDBCollection) + { + if (!pDBCollection->getNamedDBs().empty() || !pDBCollection->getAnonDBs().empty()) + bHasRanges = true; + } + + if (!bHasRanges) + // No ranges to export. Bail out. + return; + + SvXMLElementExport aElemDRs(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_RANGES, true, true); + + WriteDatabaseRange func(rExport, pDoc); + + if (pDBCollection) + { + // Write global named ranges. + func.setRangeType(ScDBCollection::GlobalNamed); + const ScDBCollection::NamedDBs& rNamedDBs = pDBCollection->getNamedDBs(); + ::std::for_each(rNamedDBs.begin(), rNamedDBs.end(), func); + + // Add global anonymous DB ranges. + func.setRangeType(ScDBCollection::GlobalAnonymous); + const ScDBCollection::AnonDBs& rAnonDBs = pDBCollection->getAnonDBs(); + ::std::for_each(rAnonDBs.begin(), rAnonDBs.end(), func); + } + + // Write sheet-local ranges. + func.setRangeType(ScDBCollection::SheetAnonymous); + ::std::for_each(aSheetDBs.begin(), aSheetDBs.end(), func); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |