LibreOffice Module sc (master) 1
XMLConverter.cxx
Go to the documentation of this file.
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 "XMLConverter.hxx"
21#include <com/sun/star/util/DateTime.hpp>
22#include <com/sun/star/sheet/GeneralFunction2.hpp>
24#include <tools/datetime.hxx>
26#include <xmloff/xmltoken.hxx>
27#include <rangeutl.hxx>
28#include <docuno.hxx>
29#include <generalfunction.hxx>
30
31using namespace ::com::sun::star;
32using namespace xmloff::token;
33
34ScDocument* ScXMLConverter::GetScDocument( const uno::Reference< frame::XModel >& xModel )
35{
36 if (xModel.is())
37 {
38 ScModelObj* pDocObj = comphelper::getFromUnoTunnel<ScModelObj>( xModel );
39 return pDocObj ? pDocObj->GetDocument() : nullptr;
40 }
41 return nullptr;
42}
43
44sheet::GeneralFunction ScXMLConverter::GetFunctionFromString( std::u16string_view sFunction )
45{
46 if( IsXMLToken(sFunction, XML_SUM ) )
47 return sheet::GeneralFunction_SUM;
48 if( IsXMLToken(sFunction, XML_AUTO ) )
49 return sheet::GeneralFunction_AUTO;
50 if( IsXMLToken(sFunction, XML_COUNT ) )
51 return sheet::GeneralFunction_COUNT;
52 if( IsXMLToken(sFunction, XML_COUNTNUMS ) )
53 return sheet::GeneralFunction_COUNTNUMS;
54 if( IsXMLToken(sFunction, XML_PRODUCT ) )
55 return sheet::GeneralFunction_PRODUCT;
56 if( IsXMLToken(sFunction, XML_AVERAGE ) )
57 return sheet::GeneralFunction_AVERAGE;
58 if( IsXMLToken(sFunction, XML_MAX ) )
59 return sheet::GeneralFunction_MAX;
60 if( IsXMLToken(sFunction, XML_MIN ) )
61 return sheet::GeneralFunction_MIN;
62 if( IsXMLToken(sFunction, XML_STDEV ) )
63 return sheet::GeneralFunction_STDEV;
64 if( IsXMLToken(sFunction, XML_STDEVP ) )
65 return sheet::GeneralFunction_STDEVP;
66 if( IsXMLToken(sFunction, XML_VAR ) )
67 return sheet::GeneralFunction_VAR;
68 if( IsXMLToken(sFunction, XML_VARP ) )
69 return sheet::GeneralFunction_VARP;
70 return sheet::GeneralFunction_NONE;
71}
72
74{
75 if( IsXMLToken(sFunction, XML_SUM ) )
77 if( IsXMLToken(sFunction, XML_AUTO ) )
79 if( IsXMLToken(sFunction, XML_COUNT ) )
81 if( IsXMLToken(sFunction, XML_COUNTNUMS ) )
83 if( IsXMLToken(sFunction, XML_PRODUCT ) )
85 if( IsXMLToken(sFunction, XML_AVERAGE ) )
87 if( IsXMLToken(sFunction, XML_MEDIAN ) )
89 if( IsXMLToken(sFunction, XML_MAX ) )
91 if( IsXMLToken(sFunction, XML_MIN ) )
93 if( IsXMLToken(sFunction, XML_STDEV ) )
95 if( IsXMLToken(sFunction, XML_STDEVP ) )
97 if( IsXMLToken(sFunction, XML_VAR ) )
99 if( IsXMLToken(sFunction, XML_VARP ) )
102}
103
105{
106 if( IsXMLToken(sFunction, XML_SUM ) )
107 return SUBTOTAL_FUNC_SUM;
108 if( IsXMLToken(sFunction, XML_COUNT ) )
109 return SUBTOTAL_FUNC_CNT;
110 if( IsXMLToken(sFunction, XML_COUNTNUMS ) )
111 return SUBTOTAL_FUNC_CNT2;
112 if( IsXMLToken(sFunction, XML_PRODUCT ) )
113 return SUBTOTAL_FUNC_PROD;
114 if( IsXMLToken(sFunction, XML_AVERAGE ) )
115 return SUBTOTAL_FUNC_AVE;
116 if( IsXMLToken(sFunction, XML_MEDIAN ) )
117 return SUBTOTAL_FUNC_MED;
118 if( IsXMLToken(sFunction, XML_MAX ) )
119 return SUBTOTAL_FUNC_MAX;
120 if( IsXMLToken(sFunction, XML_MIN ) )
121 return SUBTOTAL_FUNC_MIN;
122 if( IsXMLToken(sFunction, XML_STDEV ) )
123 return SUBTOTAL_FUNC_STD;
124 if( IsXMLToken(sFunction, XML_STDEVP ) )
125 return SUBTOTAL_FUNC_STDP;
126 if( IsXMLToken(sFunction, XML_VAR ) )
127 return SUBTOTAL_FUNC_VAR;
128 if( IsXMLToken(sFunction, XML_VARP ) )
129 return SUBTOTAL_FUNC_VARP;
130 return SUBTOTAL_FUNC_NONE;
131}
132
134 sal_Int16 eFunction )
135{
136 OUString sFuncStr;
137 switch( eFunction )
138 {
139 case sheet::GeneralFunction2::AUTO: sFuncStr = GetXMLToken( XML_AUTO ); break;
140 case sheet::GeneralFunction2::AVERAGE: sFuncStr = GetXMLToken( XML_AVERAGE ); break;
141 case sheet::GeneralFunction2::MEDIAN: sFuncStr = GetXMLToken( XML_MEDIAN ); break;
142 case sheet::GeneralFunction2::COUNT: sFuncStr = GetXMLToken( XML_COUNT ); break;
143 case sheet::GeneralFunction2::COUNTNUMS: sFuncStr = GetXMLToken( XML_COUNTNUMS ); break;
144 case sheet::GeneralFunction2::MAX: sFuncStr = GetXMLToken( XML_MAX ); break;
145 case sheet::GeneralFunction2::MIN: sFuncStr = GetXMLToken( XML_MIN ); break;
146 case sheet::GeneralFunction2::NONE: sFuncStr = GetXMLToken( XML_NONE ); break;
147 case sheet::GeneralFunction2::PRODUCT: sFuncStr = GetXMLToken( XML_PRODUCT ); break;
148 case sheet::GeneralFunction2::STDEV: sFuncStr = GetXMLToken( XML_STDEV ); break;
149 case sheet::GeneralFunction2::STDEVP: sFuncStr = GetXMLToken( XML_STDEVP ); break;
150 case sheet::GeneralFunction2::SUM: sFuncStr = GetXMLToken( XML_SUM ); break;
151 case sheet::GeneralFunction2::VAR: sFuncStr = GetXMLToken( XML_VAR ); break;
152 case sheet::GeneralFunction2::VARP: sFuncStr = GetXMLToken( XML_VARP ); break;
153 default:
154 {
155 assert(false);
156 }
157 }
158 OUString str;
159 ScRangeStringConverter::AssignString( str, sFuncStr, false );
160 return str;
161}
162
164 const ScSubTotalFunc eFunction )
165{
166 OUString sFuncStr;
167 switch( eFunction )
168 {
169 case SUBTOTAL_FUNC_AVE: sFuncStr = GetXMLToken( XML_AVERAGE ); break;
170 case SUBTOTAL_FUNC_MED: sFuncStr = GetXMLToken( XML_MEDIAN ); break;
171 case SUBTOTAL_FUNC_CNT: sFuncStr = GetXMLToken( XML_COUNT ); break;
172 case SUBTOTAL_FUNC_CNT2: sFuncStr = GetXMLToken( XML_COUNTNUMS ); break;
173 case SUBTOTAL_FUNC_MAX: sFuncStr = GetXMLToken( XML_MAX ); break;
174 case SUBTOTAL_FUNC_MIN: sFuncStr = GetXMLToken( XML_MIN ); break;
175 case SUBTOTAL_FUNC_NONE: sFuncStr = GetXMLToken( XML_NONE ); break;
176 case SUBTOTAL_FUNC_PROD: sFuncStr = GetXMLToken( XML_PRODUCT ); break;
177 case SUBTOTAL_FUNC_STD: sFuncStr = GetXMLToken( XML_STDEV ); break;
178 case SUBTOTAL_FUNC_STDP: sFuncStr = GetXMLToken( XML_STDEVP ); break;
179 case SUBTOTAL_FUNC_SUM: sFuncStr = GetXMLToken( XML_SUM ); break;
181 // it is not needed as it is only a UI value and not document content
182
183 case SUBTOTAL_FUNC_VAR: sFuncStr = GetXMLToken( XML_VAR ); break;
184 case SUBTOTAL_FUNC_VARP: sFuncStr = GetXMLToken( XML_VARP ); break;
185 }
186 OUString str;
187 ScRangeStringConverter::AssignString( str, sFuncStr, false );
188 return str;
189}
190
191sheet::DataPilotFieldOrientation ScXMLConverter::GetOrientationFromString(
192 std::u16string_view rString )
193{
194 if( IsXMLToken(rString, XML_COLUMN ) )
195 return sheet::DataPilotFieldOrientation_COLUMN;
196 if( IsXMLToken(rString, XML_ROW ) )
197 return sheet::DataPilotFieldOrientation_ROW;
198 if( IsXMLToken(rString, XML_PAGE ) )
199 return sheet::DataPilotFieldOrientation_PAGE;
200 if( IsXMLToken(rString, XML_DATA ) )
201 return sheet::DataPilotFieldOrientation_DATA;
202 return sheet::DataPilotFieldOrientation_HIDDEN;
203}
204
206 const sheet::DataPilotFieldOrientation eOrientation )
207{
208 OUString sOrientStr;
209 switch( eOrientation )
210 {
211 case sheet::DataPilotFieldOrientation_HIDDEN:
212 sOrientStr = GetXMLToken( XML_HIDDEN );
213 break;
214 case sheet::DataPilotFieldOrientation_COLUMN:
215 sOrientStr = GetXMLToken( XML_COLUMN );
216 break;
217 case sheet::DataPilotFieldOrientation_ROW:
218 sOrientStr = GetXMLToken( XML_ROW );
219 break;
220 case sheet::DataPilotFieldOrientation_PAGE:
221 sOrientStr = GetXMLToken( XML_PAGE );
222 break;
223 case sheet::DataPilotFieldOrientation_DATA:
224 sOrientStr = GetXMLToken( XML_DATA );
225 break;
226 default:
227 {
228 // added to avoid warnings
229 }
230 }
231 OUString str;
232 ScRangeStringConverter::AssignString( str, sOrientStr, false );
233 return str;
234}
235
237{
238 if( IsXMLToken(rString, XML_FROM_SAME_TABLE ) )
239 return SC_DETOBJ_ARROW;
240 if( IsXMLToken(rString, XML_FROM_ANOTHER_TABLE ) )
242 if( IsXMLToken(rString, XML_TO_ANOTHER_TABLE ) )
244 return SC_DETOBJ_NONE;
245}
246
247bool ScXMLConverter::GetDetOpTypeFromString( ScDetOpType& rDetOpType, std::u16string_view rString )
248{
249 if( IsXMLToken(rString, XML_TRACE_DEPENDENTS ) )
250 rDetOpType = SCDETOP_ADDSUCC;
251 else if( IsXMLToken(rString, XML_TRACE_PRECEDENTS ) )
252 rDetOpType = SCDETOP_ADDPRED;
253 else if( IsXMLToken(rString, XML_TRACE_ERRORS ) )
254 rDetOpType = SCDETOP_ADDERROR;
255 else if( IsXMLToken(rString, XML_REMOVE_DEPENDENTS ) )
256 rDetOpType = SCDETOP_DELSUCC;
257 else if( IsXMLToken(rString, XML_REMOVE_PRECEDENTS ) )
258 rDetOpType = SCDETOP_DELPRED;
259 else
260 return false;
261 return true;
262}
263
265 const ScDetectiveObjType eObjType )
266{
267 OUString sTypeStr;
268 switch( eObjType )
269 {
270 case SC_DETOBJ_ARROW:
271 sTypeStr = GetXMLToken( XML_FROM_SAME_TABLE );
272 break;
275 break;
277 sTypeStr = GetXMLToken( XML_TO_ANOTHER_TABLE );
278 break;
279 default:
280 {
281 // added to avoid warnings
282 }
283 }
284 OUString str;
285 ScRangeStringConverter::AssignString( str, sTypeStr, false );
286 return str;
287}
288
290 const ScDetOpType eOpType )
291{
292 OUString sTypeStr;
293 switch( eOpType )
294 {
295 case SCDETOP_ADDSUCC:
296 sTypeStr = GetXMLToken( XML_TRACE_DEPENDENTS );
297 break;
298 case SCDETOP_ADDPRED:
299 sTypeStr = GetXMLToken( XML_TRACE_PRECEDENTS );
300 break;
301 case SCDETOP_ADDERROR:
302 sTypeStr = GetXMLToken( XML_TRACE_ERRORS );
303 break;
304 case SCDETOP_DELSUCC:
306 break;
307 case SCDETOP_DELPRED:
309 break;
310 }
311 OUString str;
312 ScRangeStringConverter::AssignString( str, sTypeStr, false );
313 return str;
314}
315
317{
318 OUStringBuffer sBuffer(sFormula.getLength());
319 bool bInQuotationMarks(false);
320 sal_Unicode chPrevious('=');
321 const sal_Unicode* p = sFormula.getStr();
322 const sal_Unicode* const pStop = p + sFormula.getLength();
323 for ( ; p < pStop; ++p)
324 {
325 const sal_Unicode c = *p;
326 if (c == '\'')
327 bInQuotationMarks = !bInQuotationMarks;
328 if (bInQuotationMarks)
329 sBuffer.append(c);
330 else if ((c != '.') ||
331 !((chPrevious == ':') || (chPrevious == ' ') || (chPrevious == '=')))
332 sBuffer.append(c);
333 chPrevious = c;
334 }
335
336 sFormula = sBuffer.makeStringAndClear();
337}
338
339void ScXMLConverter::ConvertDateTimeToString(const DateTime& aDateTime, OUStringBuffer& sDate)
340{
341 css::util::DateTime aAPIDateTime = aDateTime.GetUNODateTime();
342 ::sax::Converter::convertDateTime(sDate, aAPIDateTime, nullptr);
343}
344
345namespace {
346
348enum ScXMLConditionTokenType
349{
350 XML_COND_TYPE_KEYWORD,
351 XML_COND_TYPE_COMPARISON,
352 XML_COND_TYPE_FUNCTION0,
353 XML_COND_TYPE_FUNCTION1,
354 XML_COND_TYPE_FUNCTION2
355};
356
357struct ScXMLConditionInfo
358{
359 ScXMLConditionToken meToken;
360 ScXMLConditionTokenType meType;
361 sheet::ValidationType meValidation;
362 sheet::ConditionOperator meOperator;
363 const char* mpcIdentifier;
364 sal_Int32 mnIdentLength;
365};
366
367const ScXMLConditionInfo spConditionInfos[] =
368{
369 { XML_COND_AND, XML_COND_TYPE_KEYWORD, sheet::ValidationType_ANY, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "and" ) },
370 { XML_COND_CELLCONTENT, XML_COND_TYPE_COMPARISON, sheet::ValidationType_ANY, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content" ) },
371 { XML_COND_ISBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_ANY, sheet::ConditionOperator_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-between" ) },
372 { XML_COND_ISNOTBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_ANY, sheet::ConditionOperator_NOT_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-not-between" ) },
373 { XML_COND_ISWHOLENUMBER, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_WHOLE, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-whole-number" ) },
374 { XML_COND_ISDECIMALNUMBER, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_DECIMAL, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-decimal-number" ) },
375 { XML_COND_ISDATE, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_DATE, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-date" ) },
376 { XML_COND_ISTIME, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_TIME, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-time" ) },
377 { XML_COND_ISINLIST, XML_COND_TYPE_FUNCTION1, sheet::ValidationType_LIST, sheet::ConditionOperator_EQUAL, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-in-list" ) },
378 { XML_COND_TEXTLENGTH, XML_COND_TYPE_COMPARISON, sheet::ValidationType_TEXT_LEN, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-text-length" ) },
379 { XML_COND_TEXTLENGTH_ISBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_TEXT_LEN, sheet::ConditionOperator_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-text-length-is-between" ) },
380 { XML_COND_TEXTLENGTH_ISNOTBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_TEXT_LEN, sheet::ConditionOperator_NOT_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-text-length-is-not-between" ) },
381 { XML_COND_ISTRUEFORMULA, XML_COND_TYPE_FUNCTION1, sheet::ValidationType_CUSTOM, sheet::ConditionOperator_FORMULA, RTL_CONSTASCII_STRINGPARAM( "is-true-formula" ) }
382};
383
384void lclSkipWhitespace( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
385{
386 while( (rpcString < pcEnd) && (*rpcString <= ' ') ) ++rpcString;
387}
388
389const ScXMLConditionInfo* lclGetConditionInfo( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
390{
391 lclSkipWhitespace( rpcString, pcEnd );
392 /* Search the end of an identifier name; assuming that valid identifiers
393 consist of [a-z-] only. */
394 const sal_Unicode* pcIdStart = rpcString;
395 while( (rpcString < pcEnd) && (((*rpcString >= 'a') && (*rpcString <= 'z')) || (*rpcString == '-')) ) ++rpcString;
396 sal_Int32 nLength = static_cast< sal_Int32 >( rpcString - pcIdStart );
397
398 // search the table for an entry
399 if( nLength > 0 )
400 for(auto const &rInfo : spConditionInfos)
401 if((nLength == rInfo.mnIdentLength)
402 && (::rtl_ustr_ascii_shortenedCompare_WithLength(pcIdStart, nLength, rInfo.mpcIdentifier, nLength) == 0) )
403 return &rInfo;
404
405 return nullptr;
406}
407
408sheet::ConditionOperator lclGetConditionOperator( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
409{
410 // check for double-char operators
411 if( (rpcString + 1 < pcEnd) && (rpcString[ 1 ] == '=') )
412 {
413 sheet::ConditionOperator eOperator = sheet::ConditionOperator_NONE;
414 switch( *rpcString )
415 {
416 case '!': eOperator = sheet::ConditionOperator_NOT_EQUAL; break;
417 case '<': eOperator = sheet::ConditionOperator_LESS_EQUAL; break;
418 case '>': eOperator = sheet::ConditionOperator_GREATER_EQUAL; break;
419 }
420 if( eOperator != sheet::ConditionOperator_NONE )
421 {
422 rpcString += 2;
423 return eOperator;
424 }
425 }
426
427 // check for single-char operators
428 if( rpcString < pcEnd )
429 {
430 sheet::ConditionOperator eOperator = sheet::ConditionOperator_NONE;
431 switch( *rpcString )
432 {
433 case '=': eOperator = sheet::ConditionOperator_EQUAL; break;
434 case '<': eOperator = sheet::ConditionOperator_LESS; break;
435 case '>': eOperator = sheet::ConditionOperator_GREATER; break;
436 }
437 if( eOperator != sheet::ConditionOperator_NONE )
438 {
439 ++rpcString;
440 return eOperator;
441 }
442 }
443
444 return sheet::ConditionOperator_NONE;
445}
446
461void lclSkipExpressionString( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cQuoteChar )
462{
463 if( rpcString < pcEnd )
464 {
465 sal_Int32 nLength = static_cast< sal_Int32 >( pcEnd - rpcString );
466 sal_Int32 nNextQuote = ::rtl_ustr_indexOfChar_WithLength( rpcString, nLength, cQuoteChar );
467 if( nNextQuote >= 0 )
468 rpcString += nNextQuote;
469 else
470 rpcString = pcEnd;
471 }
472}
473
488void lclSkipExpression( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cEndChar )
489{
490 while( rpcString < pcEnd )
491 {
492 if( *rpcString == cEndChar )
493 return;
494 switch( *rpcString )
495 {
496 case '(': lclSkipExpression( ++rpcString, pcEnd, ')' ); break;
497 case '{': lclSkipExpression( ++rpcString, pcEnd, '}' ); break;
498 case '"': lclSkipExpressionString( ++rpcString, pcEnd, '"' ); break;
499 case '\'': lclSkipExpressionString( ++rpcString, pcEnd, '\'' ); break;
500 }
501 if( rpcString < pcEnd ) ++rpcString;
502 }
503}
504
525bool lclSkipEmptyParentheses( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
526{
527 if( (rpcString < pcEnd) && (*rpcString == '(') )
528 {
529 lclSkipWhitespace( ++rpcString, pcEnd );
530 if( (rpcString < pcEnd) && (*rpcString == ')') )
531 {
532 ++rpcString;
533 return true;
534 }
535 }
536 return false;
537}
538
539} // namespace
540
542 ScXMLConditionParseResult& rParseResult, const OUString& rAttribute, sal_Int32 nStartIndex )
543{
544 rParseResult.meToken = XML_COND_INVALID;
545 if( (nStartIndex < 0) || (nStartIndex >= rAttribute.getLength()) ) return;
546
547 // try to find an identifier
548 const sal_Unicode* pcBegin = rAttribute.getStr();
549 const sal_Unicode* pcString = pcBegin + nStartIndex;
550 const sal_Unicode* pcEnd = pcBegin + rAttribute.getLength();
551 const ScXMLConditionInfo* pCondInfo = lclGetConditionInfo( pcString, pcEnd );
552 if( !pCondInfo )
553 return;
554
555 // insert default values into parse result (may be changed below)
556 rParseResult.meValidation = pCondInfo->meValidation;
557 rParseResult.meOperator = pCondInfo->meOperator;
558 // continue parsing dependent on token type
559 switch( pCondInfo->meType )
560 {
561 case XML_COND_TYPE_KEYWORD:
562 // nothing specific has to follow, success
563 rParseResult.meToken = pCondInfo->meToken;
564 break;
565
566 case XML_COND_TYPE_COMPARISON:
567 // format is <condition>()<operator><expression>
568 if( lclSkipEmptyParentheses( pcString, pcEnd ) )
569 {
570 rParseResult.meOperator = lclGetConditionOperator( pcString, pcEnd );
571 if( rParseResult.meOperator != sheet::ConditionOperator_NONE )
572 {
573 lclSkipWhitespace( pcString, pcEnd );
574 if( pcString < pcEnd )
575 {
576 rParseResult.meToken = pCondInfo->meToken;
577 // comparison must be at end of attribute, remaining text is the formula
578 rParseResult.maOperand1 = OUString( pcString, static_cast< sal_Int32 >( pcEnd - pcString ) );
579 }
580 }
581 }
582 break;
583
584 case XML_COND_TYPE_FUNCTION0:
585 // format is <condition>()
586 if( lclSkipEmptyParentheses( pcString, pcEnd ) )
587 rParseResult.meToken = pCondInfo->meToken;
588 break;
589
590 case XML_COND_TYPE_FUNCTION1:
591 // format is <condition>(<expression>)
592 if( (pcString < pcEnd) && (*pcString == '(') )
593 {
594 rParseResult.maOperand1 = getExpression( ++pcString, pcEnd, ')' );
595 if( !rParseResult.maOperand1.isEmpty() )
596 rParseResult.meToken = pCondInfo->meToken;
597 }
598 break;
599
600 case XML_COND_TYPE_FUNCTION2:
601 // format is <condition>(<expression1>,<expression2>)
602 if( (pcString < pcEnd) && (*pcString == '(') )
603 {
604 rParseResult.maOperand1 = getExpression( ++pcString, pcEnd, ',' );
605 if( !rParseResult.maOperand1.isEmpty() )
606 {
607 rParseResult.maOperand2 = getExpression( pcString, pcEnd, ')' );
608 if( !rParseResult.maOperand2.isEmpty() )
609 rParseResult.meToken = pCondInfo->meToken;
610 }
611 }
612 break;
613 }
614 rParseResult.mnEndIndex = static_cast< sal_Int32 >( pcString - pcBegin );
615}
616
617OUString ScXMLConditionHelper::getExpression( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cEndChar )
618{
619 OUString aExp;
620 const sal_Unicode* pcExpStart = rpcString;
621 lclSkipExpression( rpcString, pcEnd, cEndChar );
622 if( rpcString < pcEnd )
623 {
624 aExp = OUString( pcExpStart, static_cast< sal_Int32 >( rpcString - pcExpStart ) ).trim();
625 ++rpcString;
626 }
627 return aExp;
628}
629
630/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScXMLConditionToken
@ XML_COND_ISNOTBETWEEN
The 'cell-content-is-between' token.
@ XML_COND_ISTIME
The 'cell-content-is-date' token.
@ XML_COND_AND
Token not recognized.
@ XML_COND_CELLCONTENT
The 'and' token.
@ XML_COND_TEXTLENGTH
The 'cell-content-is-in-list' token.
@ XML_COND_TEXTLENGTH_ISBETWEEN
The 'cell-content-text-length' token.
@ XML_COND_ISTRUEFORMULA
The 'cell-content-text-length-is-not-between' token.
@ XML_COND_ISWHOLENUMBER
The 'cell-content-is-not-between' token.
@ XML_COND_ISINLIST
The 'cell-content-is-time' token.
@ XML_COND_ISBETWEEN
The 'cell-content' token.
@ XML_COND_ISDATE
The 'cell-content-is-decimal-number' token.
@ XML_COND_INVALID
@ XML_COND_ISDECIMALNUMBER
The 'cell-content-is-whole-number' token.
@ XML_COND_TEXTLENGTH_ISNOTBETWEEN
The 'cell-content-text-length-is-between' token.
css::util::DateTime GetUNODateTime() const
ScDocument * GetDocument() const
Definition: docuno.cxx:438
static void AssignString(OUString &rString, const OUString &rNewStr, bool bAppendStr, sal_Unicode cSeparator=' ')
helper methods
Definition: rangeutl.cxx:355
static ScSubTotalFunc GetSubTotalFuncFromString(std::u16string_view rString)
static OUString GetStringFromOrientation(const css::sheet::DataPilotFieldOrientation eOrientation)
static OUString GetStringFromFunction(const sal_Int16 eFunction)
static void ConvertDateTimeToString(const DateTime &aDateTime, OUStringBuffer &sDate)
static css::sheet::GeneralFunction GetFunctionFromString(std::u16string_view rString)
static void ConvertCellRangeAddress(OUString &sFormula)
static css::sheet::DataPilotFieldOrientation GetOrientationFromString(std::u16string_view rString)
static ScDocument * GetScDocument(const css::uno::Reference< css::frame::XModel > &xModel)
static bool GetDetOpTypeFromString(ScDetOpType &rDetOpType, std::u16string_view rString)
static OUString GetStringFromDetObjType(const ScDetectiveObjType eObjType)
static ScGeneralFunction GetFunctionFromString2(std::u16string_view rString)
static OUString GetStringFromDetOpType(const ScDetOpType eOpType)
static ScDetectiveObjType GetDetObjTypeFromString(std::u16string_view rString)
static void convertDateTime(OUStringBuffer &rBuffer, const css::util::DateTime &rDateTime, sal_Int16 const *pTimeZoneOffset, bool bAddTimeIf0AM=false)
ScDetOpType
Definition: detdata.hxx:27
@ SCDETOP_DELPRED
Definition: detdata.hxx:31
@ SCDETOP_DELSUCC
Definition: detdata.hxx:29
@ SCDETOP_ADDPRED
Definition: detdata.hxx:30
@ SCDETOP_ADDSUCC
Definition: detdata.hxx:28
@ SCDETOP_ADDERROR
Definition: detdata.hxx:32
ScDetectiveObjType
Definition: detfunc.hxx:39
@ SC_DETOBJ_NONE
Definition: detfunc.hxx:40
@ SC_DETOBJ_TOOTHERTAB
Definition: detfunc.hxx:43
@ SC_DETOBJ_ARROW
Definition: detfunc.hxx:41
@ SC_DETOBJ_FROMOTHERTAB
Definition: detfunc.hxx:42
OString sFormula
ScGeneralFunction
the css::sheet::GeneralFunction enum is extended by constants in GeneralFunction2,...
@ AVERAGE
average of all numerical values is calculated.
@ PRODUCT
product of all numerical values is calculated.
@ MAX
maximum value of all numerical values is calculated.
@ COUNT
all values, including non-numerical values, are counted.
@ VARP
variance is calculated based on the entire population.
@ SUM
sum of all numerical values is calculated.
@ STDEVP
standard deviation is calculated based on the entire population.
@ MEDIAN
median of all numerical values is calculated.
@ COUNTNUMS
numerical values are counted.
@ NONE
nothing is calculated.
@ MIN
minimum value of all numerical values is calculated.
@ VAR
variance is calculated based on a sample.
@ AUTO
function is determined automatically.
@ STDEV
standard deviation is calculated based on a sample.
ScSubTotalFunc
Definition: global.hxx:860
@ SUBTOTAL_FUNC_STDP
Definition: global.hxx:869
@ SUBTOTAL_FUNC_MAX
Definition: global.hxx:865
@ SUBTOTAL_FUNC_CNT2
Definition: global.hxx:864
@ SUBTOTAL_FUNC_AVE
Definition: global.hxx:862
@ SUBTOTAL_FUNC_VARP
Definition: global.hxx:872
@ SUBTOTAL_FUNC_VAR
Definition: global.hxx:871
@ SUBTOTAL_FUNC_NONE
Definition: global.hxx:861
@ SUBTOTAL_FUNC_SELECTION_COUNT
Definition: global.hxx:874
@ SUBTOTAL_FUNC_SUM
Definition: global.hxx:870
@ SUBTOTAL_FUNC_MED
Definition: global.hxx:873
@ SUBTOTAL_FUNC_STD
Definition: global.hxx:868
@ SUBTOTAL_FUNC_MIN
Definition: global.hxx:866
@ SUBTOTAL_FUNC_CNT
Definition: global.hxx:863
@ SUBTOTAL_FUNC_PROD
Definition: global.hxx:867
void * p
void parseCondition(ScXMLConditionParseResult &rParseResult, const OUString &rAttribute, sal_Int32 nStartIndex)
Parses the next condition in a 'condition' attribute value of e.g.
OUString getExpression(const sal_Unicode *&rpcString, const sal_Unicode *pcEnd, sal_Unicode cEndChar)
XML_FROM_SAME_TABLE
XML_STDEV
XML_VARP
XML_AUTO
XML_PAGE
XML_TRACE_ERRORS
XML_MEDIAN
XML_COLUMN
XML_MIN
XML_ROW
XML_VAR
XML_NONE
XML_DATA
XML_REMOVE_DEPENDENTS
XML_AVERAGE
XML_MAX
XML_COUNTNUMS
XML_SUM
XML_COUNT
XML_HIDDEN
XML_PRODUCT
XML_FROM_ANOTHER_TABLE
XML_TRACE_DEPENDENTS
XML_TO_ANOTHER_TABLE
XML_REMOVE_PRECEDENTS
XML_TRACE_PRECEDENTS
XML_STDEVP
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
const int COUNT
Definition: sheetevents.cxx:56
Result of an attempt to parse a single condition in a 'condition' attribute value of e....
OUString maOperand2
First operand of the token or comparison value.
css::sheet::ValidationType meValidation
The leading condition token.
OUString maOperand1
A comparison operator if existing.
css::sheet::ConditionOperator meOperator
A data validation type if existing.
sal_Int32 mnEndIndex
Second operand of 'between' conditions.
ScXMLConditionToken meToken
Reference< XModel > xModel
sal_uInt16 sal_Unicode
RedlineType meType
sal_Int32 nLength