Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "xmldrani.hxx"
21 : #include "xmlimprt.hxx"
22 : #include "xmlfilti.hxx"
23 : #include "xmlsorti.hxx"
24 : #include "document.hxx"
25 : #include "globstr.hrc"
26 : #include "globalnames.hxx"
27 : #include "docuno.hxx"
28 : #include "dbdata.hxx"
29 : #include "datauno.hxx"
30 : #include "attrib.hxx"
31 : #include "unonames.hxx"
32 : #include "convuno.hxx"
33 : #include "XMLConverter.hxx"
34 : #include "rangeutl.hxx"
35 : #include "queryentry.hxx"
36 :
37 : #include <xmloff/xmltkmap.hxx>
38 : #include <xmloff/nmspmap.hxx>
39 : #include <xmloff/xmltoken.hxx>
40 : #include <xmloff/xmlnmspe.hxx>
41 : #include <xmloff/xmlerror.hxx>
42 :
43 : #include <sax/tools/converter.hxx>
44 :
45 : #include <com/sun/star/sheet/DataImportMode.hpp>
46 : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
47 : #include <com/sun/star/sheet/XDatabaseRanges.hpp>
48 : #include <com/sun/star/sheet/XDatabaseRange.hpp>
49 : #include <com/sun/star/table/CellRangeAddress.hpp>
50 : #include <comphelper/extract.hxx>
51 : #include <com/sun/star/uno/RuntimeException.hpp>
52 : #include <com/sun/star/xml/sax/XLocator.hpp>
53 :
54 : #include <memory>
55 :
56 : #define SC_USERLIST "UserList"
57 :
58 : using namespace com::sun::star;
59 : using namespace xmloff::token;
60 : using ::rtl::OUString;
61 :
62 : //------------------------------------------------------------------
63 :
64 2 : ScXMLDatabaseRangesContext::ScXMLDatabaseRangesContext( ScXMLImport& rImport,
65 : sal_uInt16 nPrfx,
66 : const ::rtl::OUString& rLName,
67 : const ::com::sun::star::uno::Reference<
68 : ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ ) :
69 2 : SvXMLImportContext( rImport, nPrfx, rLName )
70 : {
71 : // has no attributes
72 2 : rImport.LockSolarMutex();
73 2 : }
74 :
75 6 : ScXMLDatabaseRangesContext::~ScXMLDatabaseRangesContext()
76 : {
77 2 : GetScImport().UnlockSolarMutex();
78 4 : }
79 :
80 4 : SvXMLImportContext *ScXMLDatabaseRangesContext::CreateChildContext( sal_uInt16 nPrefix,
81 : const ::rtl::OUString& rLName,
82 : const ::com::sun::star::uno::Reference<
83 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
84 : {
85 4 : SvXMLImportContext *pContext = 0;
86 :
87 4 : const SvXMLTokenMap& rTokenMap = GetScImport().GetDatabaseRangesElemTokenMap();
88 4 : switch( rTokenMap.Get( nPrefix, rLName ) )
89 : {
90 : case XML_TOK_DATABASE_RANGE :
91 : {
92 : pContext = new ScXMLDatabaseRangeContext( GetScImport(), nPrefix,
93 4 : rLName, xAttrList);
94 : }
95 4 : break;
96 : }
97 :
98 4 : if( !pContext )
99 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
100 :
101 4 : return pContext;
102 : }
103 :
104 2 : void ScXMLDatabaseRangesContext::EndElement()
105 : {
106 2 : }
107 :
108 4 : ScXMLDatabaseRangeContext::ScXMLDatabaseRangeContext( ScXMLImport& rImport,
109 : sal_uInt16 nPrfx,
110 : const ::rtl::OUString& rLName,
111 : const ::com::sun::star::uno::Reference<
112 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList) :
113 : SvXMLImportContext( rImport, nPrfx, rLName ),
114 4 : mpQueryParam(new ScQueryParam),
115 : sDatabaseRangeName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)),
116 : aSortSequence(),
117 : nRefresh(0),
118 : nSubTotalsUserListIndex(0),
119 : mbValidRange(true),
120 : bContainsSort(false),
121 : bContainsSubTotal(false),
122 : bNative(true),
123 : bIsSelection(false),
124 : bKeepFormats(false),
125 : bMoveCells(false),
126 : bStripData(false),
127 : bAutoFilter(false),
128 : bSubTotalsBindFormatsToContent(false),
129 : bSubTotalsIsCaseSensitive(false),
130 : bSubTotalsInsertPageBreaks(false),
131 : bSubTotalsSortGroups(false),
132 : bSubTotalsEnabledUserList(false),
133 : bSubTotalsAscending(true),
134 : bFilterConditionSourceRange(false),
135 : bHasHeader(true),
136 : bByRow(false),
137 8 : meRangeType(ScDBCollection::GlobalNamed)
138 : {
139 4 : nSourceType = sheet::DataImportMode_NONE;
140 4 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
141 4 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetDatabaseRangeAttrTokenMap();
142 14 : for( sal_Int16 i=0; i < nAttrCount; ++i )
143 : {
144 10 : const rtl::OUString& sAttrName(xAttrList->getNameByIndex( i ));
145 10 : rtl::OUString aLocalName;
146 10 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
147 10 : sAttrName, &aLocalName );
148 10 : const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
149 :
150 10 : switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
151 : {
152 : case XML_TOK_DATABASE_RANGE_ATTR_NAME :
153 : {
154 4 : sDatabaseRangeName = sValue;
155 : }
156 4 : break;
157 : case XML_TOK_DATABASE_RANGE_ATTR_IS_SELECTION :
158 : {
159 0 : bIsSelection = IsXMLToken(sValue, XML_TRUE);
160 : }
161 0 : break;
162 : case XML_TOK_DATABASE_RANGE_ATTR_ON_UPDATE_KEEP_STYLES :
163 : {
164 0 : bKeepFormats = IsXMLToken(sValue, XML_TRUE);
165 : }
166 0 : break;
167 : case XML_TOK_DATABASE_RANGE_ATTR_ON_UPDATE_KEEP_SIZE :
168 : {
169 0 : bMoveCells = !IsXMLToken(sValue, XML_TRUE);
170 : }
171 0 : break;
172 : case XML_TOK_DATABASE_RANGE_ATTR_HAS_PERSISTENT_DATA :
173 : {
174 0 : bStripData = !IsXMLToken(sValue, XML_TRUE);
175 : }
176 0 : break;
177 : case XML_TOK_DATABASE_RANGE_ATTR_ORIENTATION :
178 : {
179 0 : bByRow = !IsXMLToken(sValue, XML_COLUMN);
180 0 : mpQueryParam->bByRow = bByRow;
181 : }
182 0 : break;
183 : case XML_TOK_DATABASE_RANGE_ATTR_CONTAINS_HEADER :
184 : {
185 1 : bHasHeader = IsXMLToken(sValue, XML_TRUE);
186 1 : mpQueryParam->bHasHeader = bHasHeader;
187 : }
188 1 : break;
189 : case XML_TOK_DATABASE_RANGE_ATTR_DISPLAY_FILTER_BUTTONS :
190 : {
191 1 : bAutoFilter = IsXMLToken(sValue, XML_TRUE);
192 : }
193 1 : break;
194 : case XML_TOK_DATABASE_RANGE_ATTR_TARGET_RANGE_ADDRESS :
195 : {
196 4 : ScDocument* pDoc = GetScImport().GetDocument();
197 4 : sal_Int32 nOffset = 0;
198 4 : if (!ScRangeStringConverter::GetRangeFromString(
199 4 : maRange, sValue, pDoc, ::formula::FormulaGrammar::CONV_OOO, nOffset))
200 0 : mbValidRange = false;
201 : }
202 4 : break;
203 : case XML_TOK_DATABASE_RANGE_ATTR_REFRESH_DELAY :
204 : {
205 : double fTime;
206 0 : if (::sax::Converter::convertDuration( fTime, sValue ))
207 0 : nRefresh = Max( (sal_Int32)(fTime * 86400.0), (sal_Int32)0 );
208 : }
209 0 : break;
210 : }
211 10 : }
212 :
213 4 : mpQueryParam->nTab = maRange.aStart.Tab();
214 4 : mpQueryParam->nCol1 = maRange.aStart.Col();
215 4 : mpQueryParam->nRow1 = maRange.aStart.Row();
216 4 : mpQueryParam->nCol2 = maRange.aEnd.Col();
217 4 : mpQueryParam->nRow2 = maRange.aEnd.Row();
218 :
219 4 : if (sDatabaseRangeName.matchAsciiL(STR_DB_LOCAL_NONAME, strlen(STR_DB_LOCAL_NONAME)))
220 1 : meRangeType = ScDBCollection::SheetAnonymous;
221 3 : else if (sDatabaseRangeName.matchAsciiL(STR_DB_GLOBAL_NONAME, strlen(STR_DB_GLOBAL_NONAME)))
222 0 : meRangeType = ScDBCollection::GlobalAnonymous;
223 4 : }
224 :
225 8 : ScXMLDatabaseRangeContext::~ScXMLDatabaseRangeContext()
226 : {
227 8 : }
228 :
229 1 : SvXMLImportContext *ScXMLDatabaseRangeContext::CreateChildContext( sal_uInt16 nPrefix,
230 : const ::rtl::OUString& rLName,
231 : const ::com::sun::star::uno::Reference<
232 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
233 : {
234 1 : SvXMLImportContext *pContext = 0;
235 :
236 1 : const SvXMLTokenMap& rTokenMap = GetScImport().GetDatabaseRangeElemTokenMap();
237 1 : switch( rTokenMap.Get( nPrefix, rLName ) )
238 : {
239 : case XML_TOK_DATABASE_RANGE_SOURCE_SQL :
240 : {
241 : pContext = new ScXMLSourceSQLContext( GetScImport(), nPrefix,
242 0 : rLName, xAttrList, this);
243 : }
244 0 : break;
245 : case XML_TOK_DATABASE_RANGE_SOURCE_TABLE :
246 : {
247 : pContext = new ScXMLSourceTableContext( GetScImport(), nPrefix,
248 0 : rLName, xAttrList, this);
249 : }
250 0 : break;
251 : case XML_TOK_DATABASE_RANGE_SOURCE_QUERY :
252 : {
253 : pContext = new ScXMLSourceQueryContext( GetScImport(), nPrefix,
254 0 : rLName, xAttrList, this);
255 : }
256 0 : break;
257 : case XML_TOK_FILTER :
258 : {
259 : pContext = new ScXMLFilterContext(
260 1 : GetScImport(), nPrefix, rLName, xAttrList, *mpQueryParam, this);
261 : }
262 1 : break;
263 : case XML_TOK_SORT :
264 : {
265 0 : bContainsSort = true;
266 : pContext = new ScXMLSortContext( GetScImport(), nPrefix,
267 0 : rLName, xAttrList, this);
268 : }
269 0 : break;
270 : case XML_TOK_DATABASE_RANGE_SUBTOTAL_RULES :
271 : {
272 0 : bContainsSubTotal = true;
273 : pContext = new ScXMLSubTotalRulesContext( GetScImport(), nPrefix,
274 0 : rLName, xAttrList, this);
275 : }
276 0 : break;
277 : }
278 :
279 1 : if( !pContext )
280 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
281 :
282 1 : return pContext;
283 : }
284 :
285 4 : ScDBData* ScXMLDatabaseRangeContext::ConvertToDBData(const OUString& rName)
286 : {
287 4 : if (!mbValidRange)
288 0 : return NULL;
289 :
290 4 : ScDocument* pDoc = GetScImport().GetDocument();
291 :
292 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
293 : ::std::auto_ptr<ScDBData> pData(
294 4 : new ScDBData(rName, maRange.aStart.Tab(), maRange.aStart.Col(), maRange.aStart.Row(), maRange.aEnd.Col(), maRange.aEnd.Row(), bByRow, bHasHeader));
295 : SAL_WNODEPRECATED_DECLARATIONS_POP
296 :
297 4 : pData->SetAutoFilter(bAutoFilter);
298 4 : pData->SetKeepFmt(bKeepFormats);
299 4 : pData->SetDoSize(bMoveCells);
300 4 : pData->SetStripData(bStripData);
301 :
302 4 : pData->SetQueryParam(*mpQueryParam);
303 :
304 4 : if (bFilterConditionSourceRange)
305 : {
306 0 : ScRange aAdvSource;
307 0 : ScUnoConversion::FillScRange(aAdvSource, aFilterConditionSourceRangeAddress);
308 0 : pData->SetAdvancedQuerySource(&aAdvSource);
309 : }
310 :
311 : {
312 4 : ScImportParam aParam;
313 4 : aParam.bNative = bNative;
314 4 : aParam.aDBName = sDatabaseName.isEmpty() ? sConnectionResource : sDatabaseName;
315 4 : aParam.aStatement = sSourceObject;
316 4 : sheet::DataImportMode eMode = static_cast<sheet::DataImportMode>(nSourceType);
317 4 : switch (eMode)
318 : {
319 : case sheet::DataImportMode_NONE:
320 4 : aParam.bImport = false;
321 4 : break;
322 : case sheet::DataImportMode_SQL:
323 0 : aParam.bImport = true;
324 0 : aParam.bSql = true;
325 0 : break;
326 : case sheet::DataImportMode_TABLE:
327 0 : aParam.bImport = true;
328 0 : aParam.bSql = false;
329 0 : aParam.nType = ScDbTable;
330 0 : break;
331 : case sheet::DataImportMode_QUERY:
332 0 : aParam.bImport = true;
333 0 : aParam.bSql = false;
334 0 : aParam.nType = ScDbQuery;
335 0 : break;
336 : default:
337 : OSL_FAIL("Unknown data import mode");
338 0 : aParam.bImport = false;
339 : }
340 4 : pData->SetImportParam(aParam);
341 : }
342 :
343 4 : if (bContainsSort)
344 : {
345 0 : size_t nOldSize = aSortSequence.getLength();
346 0 : aSortSequence.realloc(nOldSize + 1);
347 0 : beans::PropertyValue aProperty;
348 0 : aProperty.Name = OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ORIENT));
349 0 : table::TableOrientation eOrient = mpQueryParam->bByRow ?
350 0 : table::TableOrientation_ROWS : table::TableOrientation_COLUMNS;
351 0 : aProperty.Value <<= eOrient;
352 0 : aSortSequence[nOldSize] = aProperty;
353 0 : ScSortParam aParam;
354 0 : ScSortDescriptor::FillSortParam(aParam, aSortSequence);
355 :
356 0 : SCCOLROW nStartPos = aParam.bByRow ? maRange.aStart.Col() : maRange.aStart.Row();
357 0 : for (size_t i = 0; i < aParam.GetSortKeyCount(); ++i)
358 : {
359 0 : if (!aParam.maKeyState[i].bDoSort)
360 0 : break;
361 0 : aParam.maKeyState[i].nField += nStartPos;
362 : }
363 :
364 0 : pData->SetSortParam(aParam);
365 : }
366 :
367 4 : if (bContainsSubTotal)
368 : {
369 0 : ScSubTotalParam aParam;
370 0 : aParam.bIncludePattern = bSubTotalsBindFormatsToContent;
371 0 : aParam.bUserDef = bSubTotalsEnabledUserList;
372 0 : aParam.nUserIndex = nSubTotalsUserListIndex;
373 0 : aParam.bPagebreak = bSubTotalsInsertPageBreaks;
374 0 : aParam.bCaseSens = bSubTotalsIsCaseSensitive;
375 0 : aParam.bDoSort = bSubTotalsSortGroups;
376 0 : aParam.bAscending = bSubTotalsAscending;
377 0 : aParam.bUserDef = bSubTotalsEnabledUserList;
378 0 : aParam.nUserIndex = nSubTotalsUserListIndex;
379 0 : std::vector <ScSubTotalRule>::iterator itr = aSubTotalRules.begin(), itrEnd = aSubTotalRules.end();
380 0 : for (size_t nPos = 0; itr != itrEnd; ++itr, ++nPos)
381 : {
382 0 : if (nPos >= MAXSUBTOTAL)
383 0 : break;
384 :
385 0 : const uno::Sequence<sheet::SubTotalColumn>& rColumns = itr->aSubTotalColumns;
386 0 : sal_Int32 nColCount = rColumns.getLength();
387 0 : sal_Int16 nGroupColumn = itr->nSubTotalRuleGroupFieldNumber;
388 0 : aParam.bGroupActive[nPos] = true;
389 0 : aParam.nField[nPos] = static_cast<SCCOL>(nGroupColumn);
390 :
391 0 : SCCOL nCount = static_cast<SCCOL>(nColCount);
392 0 : aParam.nSubTotals[nPos] = nCount;
393 0 : if (nCount != 0)
394 : {
395 0 : aParam.pSubTotals[nPos] = new SCCOL[nCount];
396 0 : aParam.pFunctions[nPos] = new ScSubTotalFunc[nCount];
397 :
398 0 : const sheet::SubTotalColumn* pAry = rColumns.getConstArray();
399 0 : for (SCCOL i = 0; i < nCount; ++i)
400 : {
401 0 : aParam.pSubTotals[nPos][i] = static_cast<SCCOL>(pAry[i].Column);
402 0 : aParam.pFunctions[nPos][i] =
403 0 : ScDataUnoConversion::GeneralToSubTotal( pAry[i].Function );
404 : }
405 : }
406 : else
407 : {
408 0 : aParam.pSubTotals[nPos] = NULL;
409 0 : aParam.pFunctions[nPos] = NULL;
410 : }
411 : }
412 :
413 0 : pData->SetSubTotalParam(aParam);
414 : }
415 :
416 4 : if (pData->HasImportParam() && !pData->HasImportSelection())
417 : {
418 0 : pData->SetRefreshDelay(nRefresh);
419 0 : pData->SetRefreshHandler(pDoc->GetDBCollection()->GetRefreshHandler());
420 0 : pData->SetRefreshControl(pDoc->GetRefreshTimerControlAddress());
421 : }
422 :
423 4 : return pData.release();
424 : }
425 :
426 : namespace {
427 :
428 4 : bool setAutoFilterFlags(ScDocument& rDoc, const ScDBData& rData)
429 : {
430 4 : if (!rData.HasAutoFilter())
431 3 : return false;
432 :
433 : // Set autofilter flags so that the buttons get displayed.
434 1 : ScRange aRange;
435 1 : rData.GetArea(aRange);
436 : rDoc.ApplyFlagsTab(
437 2 : aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aStart.Row(),
438 3 : aRange.aStart.Tab(), SC_MF_AUTO);
439 1 : return false;
440 : }
441 :
442 : }
443 :
444 4 : void ScXMLDatabaseRangeContext::EndElement()
445 : {
446 4 : ScDocument* pDoc = GetScImport().GetDocument();
447 4 : if (!pDoc)
448 0 : return;
449 :
450 4 : if (meRangeType == ScDBCollection::SheetAnonymous)
451 : {
452 1 : OUString aName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME));
453 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
454 1 : ::std::auto_ptr<ScDBData> pData(ConvertToDBData(aName));
455 : SAL_WNODEPRECATED_DECLARATIONS_POP
456 :
457 1 : if (pData.get())
458 : {
459 1 : ScRange aRange;
460 1 : pData->GetArea(aRange);
461 :
462 1 : setAutoFilterFlags(*pDoc, *pData);
463 1 : pDoc->SetAnonymousDBData(aRange.aStart.Tab(), pData.release());
464 : }
465 1 : return;
466 : }
467 3 : else if (meRangeType == ScDBCollection::GlobalAnonymous)
468 : {
469 0 : OUString aName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_GLOBAL_NONAME));
470 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
471 0 : ::std::auto_ptr<ScDBData> pData(ConvertToDBData(aName));
472 : SAL_WNODEPRECATED_DECLARATIONS_POP
473 :
474 0 : if (pData.get())
475 : {
476 0 : ScRange aRange;
477 0 : pData->GetArea(aRange);
478 :
479 0 : if (setAutoFilterFlags(*pDoc, *pData))
480 0 : pDoc->SetAnonymousDBData(aRange.aStart.Tab(), pData.release());
481 : else
482 0 : pDoc->GetDBCollection()->getAnonDBs().insert(pData.release());
483 : }
484 0 : return;
485 : }
486 3 : else if (meRangeType == ScDBCollection::GlobalNamed)
487 : {
488 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
489 3 : ::std::auto_ptr<ScDBData> pData(ConvertToDBData(sDatabaseRangeName));
490 : SAL_WNODEPRECATED_DECLARATIONS_POP
491 :
492 3 : if (pData.get())
493 : {
494 3 : setAutoFilterFlags(*pDoc, *pData);
495 3 : pDoc->GetDBCollection()->getNamedDBs().insert(pData.release());
496 3 : }
497 : }
498 : }
499 :
500 0 : ScXMLSourceSQLContext::ScXMLSourceSQLContext( ScXMLImport& rImport,
501 : sal_uInt16 nPrfx,
502 : const ::rtl::OUString& rLName,
503 : const ::com::sun::star::uno::Reference<
504 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
505 : ScXMLDatabaseRangeContext* pTempDatabaseRangeContext) :
506 : SvXMLImportContext( rImport, nPrfx, rLName ),
507 0 : pDatabaseRangeContext(pTempDatabaseRangeContext)
508 : {
509 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
510 0 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetDatabaseRangeSourceSQLAttrTokenMap();
511 0 : for( sal_Int16 i=0; i < nAttrCount; ++i )
512 : {
513 0 : const rtl::OUString& sAttrName(xAttrList->getNameByIndex( i ));
514 0 : rtl::OUString aLocalName;
515 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
516 0 : sAttrName, &aLocalName );
517 0 : const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
518 :
519 0 : switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
520 : {
521 : case XML_TOK_SOURCE_SQL_ATTR_DATABASE_NAME :
522 : {
523 0 : sDBName = sValue;
524 : }
525 0 : break;
526 : case XML_TOK_SOURCE_SQL_ATTR_SQL_STATEMENT :
527 : {
528 0 : pDatabaseRangeContext->SetSourceObject(sValue);
529 : }
530 0 : break;
531 : case XML_TOK_SOURCE_SQL_ATTR_PARSE_SQL_STATEMENT :
532 : {
533 0 : pDatabaseRangeContext->SetNative(IsXMLToken(sValue, XML_TRUE));
534 : }
535 0 : break;
536 : }
537 0 : }
538 0 : pDatabaseRangeContext->SetSourceType(sheet::DataImportMode_SQL);
539 0 : }
540 :
541 0 : ScXMLSourceSQLContext::~ScXMLSourceSQLContext()
542 : {
543 0 : }
544 :
545 0 : SvXMLImportContext *ScXMLSourceSQLContext::CreateChildContext( sal_uInt16 nPrefix,
546 : const ::rtl::OUString& rLName,
547 : const ::com::sun::star::uno::Reference<
548 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
549 : {
550 0 : SvXMLImportContext *pContext = 0;
551 :
552 0 : if ( nPrefix == XML_NAMESPACE_FORM )
553 : {
554 0 : if (IsXMLToken(rLName, XML_CONNECTION_RESOURCE) && sDBName.isEmpty())
555 : {
556 : pContext = new ScXMLConResContext( GetScImport(), nPrefix,
557 0 : rLName, xAttrList, pDatabaseRangeContext);
558 : }
559 : }
560 :
561 0 : if( !pContext )
562 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
563 :
564 0 : return pContext;
565 : }
566 :
567 0 : void ScXMLSourceSQLContext::EndElement()
568 : {
569 0 : if (!sDBName.isEmpty())
570 0 : pDatabaseRangeContext->SetDatabaseName(sDBName);
571 0 : }
572 :
573 0 : ScXMLSourceTableContext::ScXMLSourceTableContext( ScXMLImport& rImport,
574 : sal_uInt16 nPrfx,
575 : const ::rtl::OUString& rLName,
576 : const ::com::sun::star::uno::Reference<
577 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
578 : ScXMLDatabaseRangeContext* pTempDatabaseRangeContext) :
579 : SvXMLImportContext( rImport, nPrfx, rLName ),
580 0 : pDatabaseRangeContext(pTempDatabaseRangeContext)
581 : {
582 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
583 0 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetDatabaseRangeSourceTableAttrTokenMap();
584 0 : for( sal_Int16 i=0; i < nAttrCount; ++i )
585 : {
586 0 : const rtl::OUString& sAttrName(xAttrList->getNameByIndex( i ));
587 0 : rtl::OUString aLocalName;
588 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
589 0 : sAttrName, &aLocalName );
590 0 : const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
591 :
592 0 : switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
593 : {
594 : case XML_TOK_SOURCE_TABLE_ATTR_DATABASE_NAME :
595 : {
596 0 : sDBName = sValue;
597 : }
598 0 : break;
599 : case XML_TOK_SOURCE_TABLE_ATTR_TABLE_NAME :
600 : {
601 0 : pDatabaseRangeContext->SetSourceObject(sValue);
602 : }
603 0 : break;
604 : }
605 0 : }
606 0 : pDatabaseRangeContext->SetSourceType(sheet::DataImportMode_TABLE);
607 0 : }
608 :
609 0 : ScXMLSourceTableContext::~ScXMLSourceTableContext()
610 : {
611 0 : }
612 :
613 0 : SvXMLImportContext *ScXMLSourceTableContext::CreateChildContext( sal_uInt16 nPrefix,
614 : const ::rtl::OUString& rLName,
615 : const ::com::sun::star::uno::Reference<
616 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
617 : {
618 0 : SvXMLImportContext *pContext = 0;
619 :
620 0 : if ( nPrefix == XML_NAMESPACE_FORM )
621 : {
622 0 : if (IsXMLToken(rLName, XML_CONNECTION_RESOURCE) && sDBName.isEmpty())
623 : {
624 : pContext = new ScXMLConResContext( GetScImport(), nPrefix,
625 0 : rLName, xAttrList, pDatabaseRangeContext);
626 : }
627 : }
628 :
629 0 : if( !pContext )
630 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
631 :
632 0 : return pContext;
633 : }
634 :
635 0 : void ScXMLSourceTableContext::EndElement()
636 : {
637 0 : if (!sDBName.isEmpty())
638 0 : pDatabaseRangeContext->SetDatabaseName(sDBName);
639 0 : }
640 :
641 0 : ScXMLSourceQueryContext::ScXMLSourceQueryContext( ScXMLImport& rImport,
642 : sal_uInt16 nPrfx,
643 : const ::rtl::OUString& rLName,
644 : const ::com::sun::star::uno::Reference<
645 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
646 : ScXMLDatabaseRangeContext* pTempDatabaseRangeContext) :
647 : SvXMLImportContext( rImport, nPrfx, rLName ),
648 0 : pDatabaseRangeContext(pTempDatabaseRangeContext)
649 : {
650 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
651 0 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetDatabaseRangeSourceQueryAttrTokenMap();
652 0 : for( sal_Int16 i=0; i < nAttrCount; ++i )
653 : {
654 0 : const rtl::OUString& sAttrName(xAttrList->getNameByIndex( i ));
655 0 : rtl::OUString aLocalName;
656 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
657 0 : sAttrName, &aLocalName );
658 0 : const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
659 :
660 0 : switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
661 : {
662 : case XML_TOK_SOURCE_QUERY_ATTR_DATABASE_NAME :
663 : {
664 0 : sDBName = sValue;
665 : }
666 0 : break;
667 : case XML_TOK_SOURCE_QUERY_ATTR_QUERY_NAME :
668 : {
669 0 : pDatabaseRangeContext->SetSourceObject(sValue);
670 : }
671 0 : break;
672 : }
673 0 : }
674 0 : pDatabaseRangeContext->SetSourceType(sheet::DataImportMode_QUERY);
675 0 : }
676 :
677 0 : ScXMLSourceQueryContext::~ScXMLSourceQueryContext()
678 : {
679 0 : }
680 :
681 0 : SvXMLImportContext *ScXMLSourceQueryContext::CreateChildContext( sal_uInt16 nPrefix,
682 : const ::rtl::OUString& rLName,
683 : const ::com::sun::star::uno::Reference<
684 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
685 : {
686 0 : SvXMLImportContext *pContext = 0;
687 :
688 0 : if ( nPrefix == XML_NAMESPACE_FORM )
689 : {
690 0 : if (IsXMLToken(rLName, XML_CONNECTION_RESOURCE) && sDBName.isEmpty())
691 : {
692 : pContext = new ScXMLConResContext( GetScImport(), nPrefix,
693 0 : rLName, xAttrList, pDatabaseRangeContext);
694 : }
695 : }
696 :
697 0 : if( !pContext )
698 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
699 :
700 0 : return pContext;
701 : }
702 :
703 0 : void ScXMLSourceQueryContext::EndElement()
704 : {
705 0 : if (!sDBName.isEmpty())
706 0 : pDatabaseRangeContext->SetDatabaseName(sDBName);
707 0 : }
708 :
709 0 : ScXMLConResContext::ScXMLConResContext( ScXMLImport& rImport,
710 : sal_uInt16 nPrfx,
711 : const ::rtl::OUString& rLName,
712 : const ::com::sun::star::uno::Reference<
713 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
714 : ScXMLDatabaseRangeContext* pTempDatabaseRangeContext) :
715 : SvXMLImportContext( rImport, nPrfx, rLName ),
716 0 : pDatabaseRangeContext( pTempDatabaseRangeContext )
717 : {
718 0 : rtl::OUString sConRes;
719 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
720 0 : for( sal_Int16 i=0; i < nAttrCount; i++ )
721 : {
722 0 : rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
723 0 : rtl::OUString aLocalName;
724 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
725 0 : sAttrName, &aLocalName );
726 0 : rtl::OUString sValue = xAttrList->getValueByIndex( i );
727 :
728 0 : if (nPrefix == XML_NAMESPACE_XLINK)
729 : {
730 0 : if (IsXMLToken(aLocalName, XML_HREF))
731 0 : sConRes = sValue;
732 : }
733 0 : }
734 0 : if (!sConRes.isEmpty())
735 0 : pDatabaseRangeContext->SetConnectionResource(sConRes);
736 0 : }
737 :
738 0 : ScXMLConResContext::~ScXMLConResContext()
739 : {
740 0 : }
741 :
742 0 : SvXMLImportContext *ScXMLConResContext::CreateChildContext( sal_uInt16 nPrefix,
743 : const ::rtl::OUString& rLName,
744 : const ::com::sun::star::uno::Reference<
745 : ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ )
746 : {
747 0 : SvXMLImportContext *pContext = 0;
748 :
749 0 : if( !pContext )
750 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
751 :
752 0 : return pContext;
753 : }
754 :
755 0 : void ScXMLConResContext::EndElement()
756 : {
757 0 : }
758 :
759 0 : ScXMLSubTotalRulesContext::ScXMLSubTotalRulesContext( ScXMLImport& rImport,
760 : sal_uInt16 nPrfx,
761 : const ::rtl::OUString& rLName,
762 : const ::com::sun::star::uno::Reference<
763 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
764 : ScXMLDatabaseRangeContext* pTempDatabaseRangeContext) :
765 : SvXMLImportContext( rImport, nPrfx, rLName ),
766 0 : pDatabaseRangeContext(pTempDatabaseRangeContext)
767 : {
768 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
769 0 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetDatabaseRangeSubTotalRulesAttrTokenMap();
770 0 : for( sal_Int16 i=0; i < nAttrCount; ++i )
771 : {
772 0 : const rtl::OUString& sAttrName(xAttrList->getNameByIndex( i ));
773 0 : rtl::OUString aLocalName;
774 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
775 0 : sAttrName, &aLocalName );
776 0 : const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
777 :
778 0 : switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
779 : {
780 : case XML_TOK_SUBTOTAL_RULES_ATTR_BIND_STYLES_TO_CONTENT :
781 : {
782 0 : pDatabaseRangeContext->SetSubTotalsBindFormatsToContent(IsXMLToken(sValue, XML_TRUE));
783 : }
784 0 : break;
785 : case XML_TOK_SUBTOTAL_RULES_ATTR_CASE_SENSITIVE :
786 : {
787 0 : pDatabaseRangeContext->SetSubTotalsIsCaseSensitive(IsXMLToken(sValue, XML_TRUE));
788 : }
789 0 : break;
790 : case XML_TOK_SUBTOTAL_RULES_ATTR_PAGE_BREAKS_ON_GROUP_CHANGE :
791 : {
792 0 : pDatabaseRangeContext->SetSubTotalsInsertPageBreaks(IsXMLToken(sValue, XML_TRUE));
793 : }
794 0 : break;
795 : }
796 0 : }
797 0 : }
798 :
799 0 : ScXMLSubTotalRulesContext::~ScXMLSubTotalRulesContext()
800 : {
801 0 : }
802 :
803 0 : SvXMLImportContext *ScXMLSubTotalRulesContext::CreateChildContext( sal_uInt16 nPrefix,
804 : const ::rtl::OUString& rLName,
805 : const ::com::sun::star::uno::Reference<
806 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
807 : {
808 0 : SvXMLImportContext *pContext = 0;
809 :
810 0 : const SvXMLTokenMap& rTokenMap = GetScImport().GetDatabaseRangeSubTotalRulesElemTokenMap();
811 0 : switch( rTokenMap.Get( nPrefix, rLName ) )
812 : {
813 : case XML_TOK_SUBTOTAL_RULES_SORT_GROUPS :
814 : {
815 : pContext = new ScXMLSortGroupsContext( GetScImport(), nPrefix,
816 0 : rLName, xAttrList, pDatabaseRangeContext);
817 : }
818 0 : break;
819 : case XML_TOK_SUBTOTAL_RULES_SUBTOTAL_RULE :
820 : {
821 : pContext = new ScXMLSubTotalRuleContext( GetScImport(), nPrefix,
822 0 : rLName, xAttrList, pDatabaseRangeContext);
823 : }
824 0 : break;
825 : }
826 :
827 0 : if( !pContext )
828 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
829 :
830 0 : return pContext;
831 : }
832 :
833 0 : void ScXMLSubTotalRulesContext::EndElement()
834 : {
835 0 : }
836 :
837 0 : ScXMLSortGroupsContext::ScXMLSortGroupsContext( ScXMLImport& rImport,
838 : sal_uInt16 nPrfx,
839 : const ::rtl::OUString& rLName,
840 : const ::com::sun::star::uno::Reference<
841 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
842 : ScXMLDatabaseRangeContext* pTempDatabaseRangeContext) :
843 : SvXMLImportContext( rImport, nPrfx, rLName ),
844 0 : pDatabaseRangeContext(pTempDatabaseRangeContext)
845 : {
846 0 : pDatabaseRangeContext->SetSubTotalsSortGroups(true);
847 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
848 0 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetSubTotalRulesSortGroupsAttrTokenMap();
849 0 : for( sal_Int16 i=0; i < nAttrCount; ++i )
850 : {
851 0 : const rtl::OUString& sAttrName(xAttrList->getNameByIndex( i ));
852 0 : rtl::OUString aLocalName;
853 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
854 0 : sAttrName, &aLocalName );
855 0 : const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
856 :
857 0 : switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
858 : {
859 : case XML_TOK_SORT_GROUPS_ATTR_DATA_TYPE :
860 : {
861 0 : if (sValue.getLength() > 8)
862 : {
863 0 : rtl::OUString sTemp = sValue.copy(0, 8);
864 0 : if (sTemp.compareToAscii(SC_USERLIST) == 0)
865 : {
866 0 : pDatabaseRangeContext->SetSubTotalsEnabledUserList(true);
867 0 : sTemp = sValue.copy(8);
868 0 : pDatabaseRangeContext->SetSubTotalsUserListIndex(static_cast<sal_Int16>(sTemp.toInt32()));
869 : }
870 : else
871 : {
872 : //if (IsXMLToken(sValue, XML_AUTOMATIC))
873 : //aSortField.FieldType = util::SortFieldType_AUTOMATIC;
874 : // is not supported by StarOffice
875 0 : }
876 : }
877 : else
878 : {
879 : //if (IsXMLToken(sValue, XML_TEXT))
880 : //aSortField.FieldType = util::SortFieldType_ALPHANUMERIC;
881 : // is not supported by StarOffice
882 : //else if (IsXMLToken(sValue, XML_NUMBER))
883 : //aSortField.FieldType = util::SortFieldType_NUMERIC;
884 : // is not supported by StarOffice
885 : }
886 : }
887 0 : break;
888 : case XML_TOK_SORT_GROUPS_ATTR_ORDER :
889 : {
890 0 : if (IsXMLToken(sValue, XML_ASCENDING))
891 0 : pDatabaseRangeContext->SetSubTotalsAscending(true);
892 : else
893 0 : pDatabaseRangeContext->SetSubTotalsAscending(false);
894 : }
895 0 : break;
896 : }
897 0 : }
898 0 : }
899 :
900 0 : ScXMLSortGroupsContext::~ScXMLSortGroupsContext()
901 : {
902 0 : }
903 :
904 0 : SvXMLImportContext *ScXMLSortGroupsContext::CreateChildContext( sal_uInt16 nPrefix,
905 : const ::rtl::OUString& rLName,
906 : const ::com::sun::star::uno::Reference<
907 : ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ )
908 : {
909 0 : SvXMLImportContext *pContext = 0;
910 :
911 0 : if( !pContext )
912 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
913 :
914 0 : return pContext;
915 : }
916 :
917 0 : void ScXMLSortGroupsContext::EndElement()
918 : {
919 0 : }
920 :
921 0 : ScXMLSubTotalRuleContext::ScXMLSubTotalRuleContext( ScXMLImport& rImport,
922 : sal_uInt16 nPrfx,
923 : const ::rtl::OUString& rLName,
924 : const ::com::sun::star::uno::Reference<
925 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
926 : ScXMLDatabaseRangeContext* pTempDatabaseRangeContext) :
927 : SvXMLImportContext( rImport, nPrfx, rLName ),
928 0 : pDatabaseRangeContext(pTempDatabaseRangeContext)
929 : {
930 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
931 0 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetSubTotalRulesSubTotalRuleAttrTokenMap();
932 0 : for( sal_Int16 i=0; i < nAttrCount; ++i )
933 : {
934 0 : const rtl::OUString& sAttrName(xAttrList->getNameByIndex( i ));
935 0 : rtl::OUString aLocalName;
936 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
937 0 : sAttrName, &aLocalName );
938 0 : const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
939 :
940 0 : switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
941 : {
942 : case XML_TOK_SUBTOTAL_RULE_ATTR_GROUP_BY_FIELD_NUMBER :
943 : {
944 0 : aSubTotalRule.nSubTotalRuleGroupFieldNumber = static_cast<sal_Int16>(sValue.toInt32());
945 : }
946 0 : break;
947 : }
948 0 : }
949 0 : }
950 :
951 0 : ScXMLSubTotalRuleContext::~ScXMLSubTotalRuleContext()
952 : {
953 0 : }
954 :
955 0 : SvXMLImportContext *ScXMLSubTotalRuleContext::CreateChildContext( sal_uInt16 nPrefix,
956 : const ::rtl::OUString& rLName,
957 : const ::com::sun::star::uno::Reference<
958 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
959 : {
960 0 : SvXMLImportContext *pContext = 0;
961 :
962 0 : const SvXMLTokenMap& rTokenMap = GetScImport().GetSubTotalRulesSubTotalRuleElemTokenMap();
963 0 : switch( rTokenMap.Get( nPrefix, rLName ) )
964 : {
965 : case XML_TOK_SUBTOTAL_RULE_SUBTOTAL_FIELD :
966 : {
967 : pContext = new ScXMLSubTotalFieldContext( GetScImport(), nPrefix,
968 0 : rLName, xAttrList, this);
969 : }
970 0 : break;
971 : }
972 :
973 0 : if( !pContext )
974 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
975 :
976 0 : return pContext;
977 : }
978 :
979 0 : void ScXMLSubTotalRuleContext::EndElement()
980 : {
981 0 : if (pDatabaseRangeContext)
982 0 : pDatabaseRangeContext->AddSubTotalRule(aSubTotalRule);
983 0 : }
984 :
985 0 : ScXMLSubTotalFieldContext::ScXMLSubTotalFieldContext( ScXMLImport& rImport,
986 : sal_uInt16 nPrfx,
987 : const ::rtl::OUString& rLName,
988 : const ::com::sun::star::uno::Reference<
989 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
990 : ScXMLSubTotalRuleContext* pTempSubTotalRuleContext) :
991 : SvXMLImportContext( rImport, nPrfx, rLName ),
992 0 : pSubTotalRuleContext(pTempSubTotalRuleContext)
993 : {
994 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
995 0 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetSubTotalRuleSubTotalFieldAttrTokenMap();
996 0 : for( sal_Int16 i=0; i < nAttrCount; ++i )
997 : {
998 0 : const rtl::OUString& sAttrName(xAttrList->getNameByIndex( i ));
999 0 : rtl::OUString aLocalName;
1000 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
1001 0 : sAttrName, &aLocalName );
1002 0 : const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
1003 :
1004 0 : switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
1005 : {
1006 : case XML_TOK_SUBTOTAL_FIELD_ATTR_FIELD_NUMBER :
1007 : {
1008 0 : sFieldNumber = sValue;
1009 : }
1010 0 : break;
1011 : case XML_TOK_SUBTOTAL_FIELD_ATTR_FUNCTION :
1012 : {
1013 0 : sFunction = sValue;
1014 : }
1015 0 : break;
1016 : }
1017 0 : }
1018 0 : }
1019 :
1020 0 : ScXMLSubTotalFieldContext::~ScXMLSubTotalFieldContext()
1021 : {
1022 0 : }
1023 :
1024 0 : SvXMLImportContext *ScXMLSubTotalFieldContext::CreateChildContext( sal_uInt16 nPrefix,
1025 : const ::rtl::OUString& rLName,
1026 : const ::com::sun::star::uno::Reference<
1027 : ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ )
1028 : {
1029 0 : SvXMLImportContext *pContext = 0;
1030 :
1031 0 : if( !pContext )
1032 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
1033 :
1034 0 : return pContext;
1035 : }
1036 :
1037 0 : void ScXMLSubTotalFieldContext::EndElement()
1038 : {
1039 0 : sheet::SubTotalColumn aSubTotalColumn;
1040 0 : aSubTotalColumn.Column = sFieldNumber.toInt32();
1041 0 : aSubTotalColumn.Function = ScXMLConverter::GetFunctionFromString( sFunction );
1042 0 : pSubTotalRuleContext->AddSubTotalColumn(aSubTotalColumn);
1043 15 : }
1044 :
1045 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|