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>
25 #include <sax/tools/converter.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <rangeutl.hxx>
28 #include <docuno.hxx>
29 #include <generalfunction.hxx>
30 
31 using namespace ::com::sun::star;
32 using namespace xmloff::token;
33 
34 ScDocument* 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 
44 sheet::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;
180  case SUBTOTAL_FUNC_SELECTION_COUNT: 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 
191 sheet::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 ) )
241  return SC_DETOBJ_FROMOTHERTAB;
242  if( IsXMLToken(rString, XML_TO_ANOTHER_TABLE ) )
243  return SC_DETOBJ_TOOTHERTAB;
244  return SC_DETOBJ_NONE;
245 }
246 
247 bool 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;
274  sTypeStr = GetXMLToken( XML_FROM_ANOTHER_TABLE );
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:
305  sTypeStr = GetXMLToken( XML_REMOVE_DEPENDENTS );
306  break;
307  case SCDETOP_DELPRED:
308  sTypeStr = GetXMLToken( XML_REMOVE_PRECEDENTS );
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 
339 void ScXMLConverter::ConvertDateTimeToString(const DateTime& aDateTime, OUStringBuffer& sDate)
340 {
341  css::util::DateTime aAPIDateTime = aDateTime.GetUNODateTime();
342  ::sax::Converter::convertDateTime(sDate, aAPIDateTime, nullptr);
343 }
344 
345 namespace {
346 
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 
357 struct ScXMLConditionInfo
358 {
359  ScXMLConditionToken meToken;
361  sheet::ValidationType meValidation;
362  sheet::ConditionOperator meOperator;
363  const char* mpcIdentifier;
364  sal_Int32 mnIdentLength;
365 };
366 
367 const 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 
384 void lclSkipWhitespace( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
385 {
386  while( (rpcString < pcEnd) && (*rpcString <= ' ') ) ++rpcString;
387 }
388 
389 const 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 
408 sheet::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 
461 void 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 
488 void 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 
525 bool 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 
617 OUString 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: */
Token not recognized.
function is determined automatically.
static OUString GetStringFromFunction(const sal_Int16 eFunction)
The 'cell-content-is-whole-number' token.
The 'cell-content-text-length' token.
static void ConvertDateTimeToString(const DateTime &aDateTime, OUStringBuffer &sDate)
static ScSubTotalFunc GetSubTotalFuncFromString(std::u16string_view rString)
The 'cell-content-is-in-list' token.
ScXMLConditionToken
ScXMLConditionTokenType
Enumerates different types of condition tokens.
static ScDocument * GetScDocument(const css::uno::Reference< css::frame::XModel > &xModel)
css::sheet::ConditionOperator meOperator
A data validation type if existing.
Result of an attempt to parse a single condition in a 'condition' attribute value of e...
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
numerical values are counted.
sum of all numerical values is calculated.
product of all numerical values is calculated.
sal_uInt16 sal_Unicode
variance is calculated based on the entire population.
The 'cell-content-text-length-is-between' token.
maximum value of all numerical values is calculated.
css::util::DateTime GetUNODateTime() const
static void AssignString(OUString &rString, const OUString &rNewStr, bool bAppendStr, sal_Unicode cSeparator= ' ')
helper methods
Definition: rangeutl.cxx:355
The 'cell-content-is-decimal-number' token.
standard deviation is calculated based on the entire population.
The 'cell-content-text-length-is-not-between' token.
ScXMLConditionToken meToken
ScDetectiveObjType
Definition: detfunc.hxx:38
average of all numerical values is calculated.
static css::sheet::DataPilotFieldOrientation GetOrientationFromString(std::u16string_view rString)
static void ConvertCellRangeAddress(OUString &sFormula)
static ScDetectiveObjType GetDetObjTypeFromString(std::u16string_view rString)
static void convertDateTime(OUStringBuffer &rBuffer, const css::util::DateTime &rDateTime, sal_Int16 const *pTimeZoneOffset, bool bAddTimeIf0AM=false)
const int COUNT
Definition: sheetevents.cxx:56
The 'cell-content-is-time' token.
OUString maOperand2
First operand of the token or comparison value.
static bool GetDetOpTypeFromString(ScDetOpType &rDetOpType, std::u16string_view rString)
The 'cell-content' token.
OUString maOperand1
A comparison operator if existing.
static css::sheet::GeneralFunction GetFunctionFromString(std::u16string_view rString)
median of all numerical values is calculated.
void parseCondition(ScXMLConditionParseResult &rParseResult, const OUString &rAttribute, sal_Int32 nStartIndex)
Parses the next condition in a 'condition' attribute value of e.g.
static OUString GetStringFromDetOpType(const ScDetOpType eOpType)
ScDetOpType
Definition: detdata.hxx:26
static ScGeneralFunction GetFunctionFromString2(std::u16string_view rString)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
OUString getExpression(const sal_Unicode *&rpcString, const sal_Unicode *pcEnd, sal_Unicode cEndChar)
ScGeneralFunction
the css::sheet::GeneralFunction enum is extended by constants in GeneralFunction2, which causes some type-safety issues.
variance is calculated based on a sample.
all values, including non-numerical values, are counted.
nothing is calculated.
void * p
The 'cell-content-is-not-between' token.
The 'cell-content-is-date' token.
minimum value of all numerical values is calculated.
standard deviation is calculated based on a sample.
static OUString GetStringFromDetObjType(const ScDetectiveObjType eObjType)
The 'and' token.
sal_Int32 nLength
The 'cell-content-is-between' token.
ScSubTotalFunc
Definition: global.hxx:843
sal_Int32 mnEndIndex
Second operand of 'between' conditions.
static OUString GetStringFromOrientation(const css::sheet::DataPilotFieldOrientation eOrientation)
RedlineType meType
css::sheet::ValidationType meValidation
The leading condition token.
ScDocument * GetDocument() const
Definition: docuno.cxx:441