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::getUnoTunnelImplementation<ScModelObj>( xModel );
39  return pDocObj ? pDocObj->GetDocument() : nullptr;
40  }
41  return nullptr;
42 }
43 
44 sheet::GeneralFunction ScXMLConverter::GetFunctionFromString( const OUString& 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  OUString& rString,
135  sal_Int16 eFunction )
136 {
137  OUString sFuncStr;
138  switch( eFunction )
139  {
140  case sheet::GeneralFunction2::AUTO: sFuncStr = GetXMLToken( XML_AUTO ); break;
141  case sheet::GeneralFunction2::AVERAGE: sFuncStr = GetXMLToken( XML_AVERAGE ); break;
142  case sheet::GeneralFunction2::MEDIAN: sFuncStr = GetXMLToken( XML_MEDIAN ); break;
143  case sheet::GeneralFunction2::COUNT: sFuncStr = GetXMLToken( XML_COUNT ); break;
144  case sheet::GeneralFunction2::COUNTNUMS: sFuncStr = GetXMLToken( XML_COUNTNUMS ); break;
145  case sheet::GeneralFunction2::MAX: sFuncStr = GetXMLToken( XML_MAX ); break;
146  case sheet::GeneralFunction2::MIN: sFuncStr = GetXMLToken( XML_MIN ); break;
147  case sheet::GeneralFunction2::NONE: sFuncStr = GetXMLToken( XML_NONE ); break;
148  case sheet::GeneralFunction2::PRODUCT: sFuncStr = GetXMLToken( XML_PRODUCT ); break;
149  case sheet::GeneralFunction2::STDEV: sFuncStr = GetXMLToken( XML_STDEV ); break;
150  case sheet::GeneralFunction2::STDEVP: sFuncStr = GetXMLToken( XML_STDEVP ); break;
151  case sheet::GeneralFunction2::SUM: sFuncStr = GetXMLToken( XML_SUM ); break;
152  case sheet::GeneralFunction2::VAR: sFuncStr = GetXMLToken( XML_VAR ); break;
153  case sheet::GeneralFunction2::VARP: sFuncStr = GetXMLToken( XML_VARP ); break;
154  default:
155  {
156  assert(false);
157  }
158  }
159  ScRangeStringConverter::AssignString( rString, sFuncStr, false );
160 }
161 
163  OUString& rString,
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  ScRangeStringConverter::AssignString( rString, sFuncStr, false );
187 }
188 
189 sheet::DataPilotFieldOrientation ScXMLConverter::GetOrientationFromString(
190  const OUString& rString )
191 {
192  if( IsXMLToken(rString, XML_COLUMN ) )
193  return sheet::DataPilotFieldOrientation_COLUMN;
194  if( IsXMLToken(rString, XML_ROW ) )
195  return sheet::DataPilotFieldOrientation_ROW;
196  if( IsXMLToken(rString, XML_PAGE ) )
197  return sheet::DataPilotFieldOrientation_PAGE;
198  if( IsXMLToken(rString, XML_DATA ) )
199  return sheet::DataPilotFieldOrientation_DATA;
200  return sheet::DataPilotFieldOrientation_HIDDEN;
201 }
202 
204  OUString& rString,
205  const sheet::DataPilotFieldOrientation eOrientation )
206 {
207  OUString sOrientStr;
208  switch( eOrientation )
209  {
210  case sheet::DataPilotFieldOrientation_HIDDEN:
211  sOrientStr = GetXMLToken( XML_HIDDEN );
212  break;
213  case sheet::DataPilotFieldOrientation_COLUMN:
214  sOrientStr = GetXMLToken( XML_COLUMN );
215  break;
216  case sheet::DataPilotFieldOrientation_ROW:
217  sOrientStr = GetXMLToken( XML_ROW );
218  break;
219  case sheet::DataPilotFieldOrientation_PAGE:
220  sOrientStr = GetXMLToken( XML_PAGE );
221  break;
222  case sheet::DataPilotFieldOrientation_DATA:
223  sOrientStr = GetXMLToken( XML_DATA );
224  break;
225  default:
226  {
227  // added to avoid warnings
228  }
229  }
230  ScRangeStringConverter::AssignString( rString, sOrientStr, false );
231 }
232 
234 {
235  if( IsXMLToken(rString, XML_FROM_SAME_TABLE ) )
236  return SC_DETOBJ_ARROW;
237  if( IsXMLToken(rString, XML_FROM_ANOTHER_TABLE ) )
238  return SC_DETOBJ_FROMOTHERTAB;
239  if( IsXMLToken(rString, XML_TO_ANOTHER_TABLE ) )
240  return SC_DETOBJ_TOOTHERTAB;
241  return SC_DETOBJ_NONE;
242 }
243 
244 bool ScXMLConverter::GetDetOpTypeFromString( ScDetOpType& rDetOpType, const OUString& rString )
245 {
246  if( IsXMLToken(rString, XML_TRACE_DEPENDENTS ) )
247  rDetOpType = SCDETOP_ADDSUCC;
248  else if( IsXMLToken(rString, XML_TRACE_PRECEDENTS ) )
249  rDetOpType = SCDETOP_ADDPRED;
250  else if( IsXMLToken(rString, XML_TRACE_ERRORS ) )
251  rDetOpType = SCDETOP_ADDERROR;
252  else if( IsXMLToken(rString, XML_REMOVE_DEPENDENTS ) )
253  rDetOpType = SCDETOP_DELSUCC;
254  else if( IsXMLToken(rString, XML_REMOVE_PRECEDENTS ) )
255  rDetOpType = SCDETOP_DELPRED;
256  else
257  return false;
258  return true;
259 }
260 
262  OUString& rString,
263  const ScDetectiveObjType eObjType )
264 {
265  OUString sTypeStr;
266  switch( eObjType )
267  {
268  case SC_DETOBJ_ARROW:
269  sTypeStr = GetXMLToken( XML_FROM_SAME_TABLE );
270  break;
272  sTypeStr = GetXMLToken( XML_FROM_ANOTHER_TABLE );
273  break;
275  sTypeStr = GetXMLToken( XML_TO_ANOTHER_TABLE );
276  break;
277  default:
278  {
279  // added to avoid warnings
280  }
281  }
282  ScRangeStringConverter::AssignString( rString, sTypeStr, false );
283 }
284 
286  OUString& rString,
287  const ScDetOpType eOpType )
288 {
289  OUString sTypeStr;
290  switch( eOpType )
291  {
292  case SCDETOP_ADDSUCC:
293  sTypeStr = GetXMLToken( XML_TRACE_DEPENDENTS );
294  break;
295  case SCDETOP_ADDPRED:
296  sTypeStr = GetXMLToken( XML_TRACE_PRECEDENTS );
297  break;
298  case SCDETOP_ADDERROR:
299  sTypeStr = GetXMLToken( XML_TRACE_ERRORS );
300  break;
301  case SCDETOP_DELSUCC:
302  sTypeStr = GetXMLToken( XML_REMOVE_DEPENDENTS );
303  break;
304  case SCDETOP_DELPRED:
305  sTypeStr = GetXMLToken( XML_REMOVE_PRECEDENTS );
306  break;
307  }
308  ScRangeStringConverter::AssignString( rString, sTypeStr, false );
309 }
310 
312 {
313  OUStringBuffer sBuffer(sFormula.getLength());
314  bool bInQuotationMarks(false);
315  sal_Unicode chPrevious('=');
316  const sal_Unicode* p = sFormula.getStr();
317  const sal_Unicode* const pStop = p + sFormula.getLength();
318  for ( ; p < pStop; ++p)
319  {
320  const sal_Unicode c = *p;
321  if (c == '\'')
322  bInQuotationMarks = !bInQuotationMarks;
323  if (bInQuotationMarks)
324  sBuffer.append(c);
325  else if ((c != '.') ||
326  !((chPrevious == ':') || (chPrevious == ' ') || (chPrevious == '=')))
327  sBuffer.append(c);
328  chPrevious = c;
329  }
330 
331  sFormula = sBuffer.makeStringAndClear();
332 }
333 
334 void ScXMLConverter::ConvertDateTimeToString(const DateTime& aDateTime, OUStringBuffer& sDate)
335 {
336  css::util::DateTime aAPIDateTime = aDateTime.GetUNODateTime();
337  ::sax::Converter::convertDateTime(sDate, aAPIDateTime, nullptr);
338 }
339 
340 namespace {
341 
344 {
345  XML_COND_TYPE_KEYWORD,
346  XML_COND_TYPE_COMPARISON,
347  XML_COND_TYPE_FUNCTION0,
348  XML_COND_TYPE_FUNCTION1,
349  XML_COND_TYPE_FUNCTION2
350 };
351 
352 struct ScXMLConditionInfo
353 {
354  ScXMLConditionToken meToken;
356  sheet::ValidationType meValidation;
357  sheet::ConditionOperator meOperator;
358  const char* mpcIdentifier;
359  sal_Int32 mnIdentLength;
360 };
361 
362 const ScXMLConditionInfo spConditionInfos[] =
363 {
364  { XML_COND_AND, XML_COND_TYPE_KEYWORD, sheet::ValidationType_ANY, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "and" ) },
365  { XML_COND_CELLCONTENT, XML_COND_TYPE_COMPARISON, sheet::ValidationType_ANY, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content" ) },
366  { XML_COND_ISBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_ANY, sheet::ConditionOperator_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-between" ) },
367  { XML_COND_ISNOTBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_ANY, sheet::ConditionOperator_NOT_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-not-between" ) },
368  { XML_COND_ISWHOLENUMBER, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_WHOLE, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-whole-number" ) },
369  { XML_COND_ISDECIMALNUMBER, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_DECIMAL, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-decimal-number" ) },
370  { XML_COND_ISDATE, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_DATE, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-date" ) },
371  { XML_COND_ISTIME, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_TIME, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-time" ) },
372  { XML_COND_ISINLIST, XML_COND_TYPE_FUNCTION1, sheet::ValidationType_LIST, sheet::ConditionOperator_EQUAL, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-in-list" ) },
373  { XML_COND_TEXTLENGTH, XML_COND_TYPE_COMPARISON, sheet::ValidationType_TEXT_LEN, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-text-length" ) },
374  { XML_COND_TEXTLENGTH_ISBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_TEXT_LEN, sheet::ConditionOperator_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-text-length-is-between" ) },
375  { 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" ) },
376  { XML_COND_ISTRUEFORMULA, XML_COND_TYPE_FUNCTION1, sheet::ValidationType_CUSTOM, sheet::ConditionOperator_FORMULA, RTL_CONSTASCII_STRINGPARAM( "is-true-formula" ) }
377 };
378 
379 void lclSkipWhitespace( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
380 {
381  while( (rpcString < pcEnd) && (*rpcString <= ' ') ) ++rpcString;
382 }
383 
384 const ScXMLConditionInfo* lclGetConditionInfo( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
385 {
386  lclSkipWhitespace( rpcString, pcEnd );
387  /* Search the end of an identifier name; assuming that valid identifiers
388  consist of [a-z-] only. */
389  const sal_Unicode* pcIdStart = rpcString;
390  while( (rpcString < pcEnd) && (((*rpcString >= 'a') && (*rpcString <= 'z')) || (*rpcString == '-')) ) ++rpcString;
391  sal_Int32 nLength = static_cast< sal_Int32 >( rpcString - pcIdStart );
392 
393  // search the table for an entry
394  if( nLength > 0 )
395  for(auto const &rInfo : spConditionInfos)
396  if((nLength == rInfo.mnIdentLength)
397  && (::rtl_ustr_ascii_shortenedCompare_WithLength(pcIdStart, nLength, rInfo.mpcIdentifier, nLength) == 0) )
398  return &rInfo;
399 
400  return nullptr;
401 }
402 
403 sheet::ConditionOperator lclGetConditionOperator( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
404 {
405  // check for double-char operators
406  if( (rpcString + 1 < pcEnd) && (rpcString[ 1 ] == '=') )
407  {
408  sheet::ConditionOperator eOperator = sheet::ConditionOperator_NONE;
409  switch( *rpcString )
410  {
411  case '!': eOperator = sheet::ConditionOperator_NOT_EQUAL; break;
412  case '<': eOperator = sheet::ConditionOperator_LESS_EQUAL; break;
413  case '>': eOperator = sheet::ConditionOperator_GREATER_EQUAL; break;
414  }
415  if( eOperator != sheet::ConditionOperator_NONE )
416  {
417  rpcString += 2;
418  return eOperator;
419  }
420  }
421 
422  // check for single-char operators
423  if( rpcString < pcEnd )
424  {
425  sheet::ConditionOperator eOperator = sheet::ConditionOperator_NONE;
426  switch( *rpcString )
427  {
428  case '=': eOperator = sheet::ConditionOperator_EQUAL; break;
429  case '<': eOperator = sheet::ConditionOperator_LESS; break;
430  case '>': eOperator = sheet::ConditionOperator_GREATER; break;
431  }
432  if( eOperator != sheet::ConditionOperator_NONE )
433  {
434  ++rpcString;
435  return eOperator;
436  }
437  }
438 
439  return sheet::ConditionOperator_NONE;
440 }
441 
456 void lclSkipExpressionString( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cQuoteChar )
457 {
458  if( rpcString < pcEnd )
459  {
460  sal_Int32 nLength = static_cast< sal_Int32 >( pcEnd - rpcString );
461  sal_Int32 nNextQuote = ::rtl_ustr_indexOfChar_WithLength( rpcString, nLength, cQuoteChar );
462  if( nNextQuote >= 0 )
463  rpcString += nNextQuote;
464  else
465  rpcString = pcEnd;
466  }
467 }
468 
483 void lclSkipExpression( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cEndChar )
484 {
485  while( rpcString < pcEnd )
486  {
487  if( *rpcString == cEndChar )
488  return;
489  switch( *rpcString )
490  {
491  case '(': lclSkipExpression( ++rpcString, pcEnd, ')' ); break;
492  case '{': lclSkipExpression( ++rpcString, pcEnd, '}' ); break;
493  case '"': lclSkipExpressionString( ++rpcString, pcEnd, '"' ); break;
494  case '\'': lclSkipExpressionString( ++rpcString, pcEnd, '\'' ); break;
495  }
496  if( rpcString < pcEnd ) ++rpcString;
497  }
498 }
499 
520 bool lclSkipEmptyParentheses( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd )
521 {
522  if( (rpcString < pcEnd) && (*rpcString == '(') )
523  {
524  lclSkipWhitespace( ++rpcString, pcEnd );
525  if( (rpcString < pcEnd) && (*rpcString == ')') )
526  {
527  ++rpcString;
528  return true;
529  }
530  }
531  return false;
532 }
533 
534 } // namespace
535 
537  ScXMLConditionParseResult& rParseResult, const OUString& rAttribute, sal_Int32 nStartIndex )
538 {
539  rParseResult.meToken = XML_COND_INVALID;
540  if( (nStartIndex < 0) || (nStartIndex >= rAttribute.getLength()) ) return;
541 
542  // try to find an identifier
543  const sal_Unicode* pcBegin = rAttribute.getStr();
544  const sal_Unicode* pcString = pcBegin + nStartIndex;
545  const sal_Unicode* pcEnd = pcBegin + rAttribute.getLength();
546  const ScXMLConditionInfo* pCondInfo = lclGetConditionInfo( pcString, pcEnd );
547  if( !pCondInfo )
548  return;
549 
550  // insert default values into parse result (may be changed below)
551  rParseResult.meValidation = pCondInfo->meValidation;
552  rParseResult.meOperator = pCondInfo->meOperator;
553  // continue parsing dependent on token type
554  switch( pCondInfo->meType )
555  {
556  case XML_COND_TYPE_KEYWORD:
557  // nothing specific has to follow, success
558  rParseResult.meToken = pCondInfo->meToken;
559  break;
560 
561  case XML_COND_TYPE_COMPARISON:
562  // format is <condition>()<operator><expression>
563  if( lclSkipEmptyParentheses( pcString, pcEnd ) )
564  {
565  rParseResult.meOperator = lclGetConditionOperator( pcString, pcEnd );
566  if( rParseResult.meOperator != sheet::ConditionOperator_NONE )
567  {
568  lclSkipWhitespace( pcString, pcEnd );
569  if( pcString < pcEnd )
570  {
571  rParseResult.meToken = pCondInfo->meToken;
572  // comparison must be at end of attribute, remaining text is the formula
573  rParseResult.maOperand1 = OUString( pcString, static_cast< sal_Int32 >( pcEnd - pcString ) );
574  }
575  }
576  }
577  break;
578 
579  case XML_COND_TYPE_FUNCTION0:
580  // format is <condition>()
581  if( lclSkipEmptyParentheses( pcString, pcEnd ) )
582  rParseResult.meToken = pCondInfo->meToken;
583  break;
584 
585  case XML_COND_TYPE_FUNCTION1:
586  // format is <condition>(<expression>)
587  if( (pcString < pcEnd) && (*pcString == '(') )
588  {
589  rParseResult.maOperand1 = getExpression( ++pcString, pcEnd, ')' );
590  if( !rParseResult.maOperand1.isEmpty() )
591  rParseResult.meToken = pCondInfo->meToken;
592  }
593  break;
594 
595  case XML_COND_TYPE_FUNCTION2:
596  // format is <condition>(<expression1>,<expression2>)
597  if( (pcString < pcEnd) && (*pcString == '(') )
598  {
599  rParseResult.maOperand1 = getExpression( ++pcString, pcEnd, ',' );
600  if( !rParseResult.maOperand1.isEmpty() )
601  {
602  rParseResult.maOperand2 = getExpression( pcString, pcEnd, ')' );
603  if( !rParseResult.maOperand2.isEmpty() )
604  rParseResult.meToken = pCondInfo->meToken;
605  }
606  }
607  break;
608  }
609  rParseResult.mnEndIndex = static_cast< sal_Int32 >( pcString - pcBegin );
610 }
611 
612 OUString ScXMLConditionHelper::getExpression( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cEndChar )
613 {
614  OUString aExp;
615  const sal_Unicode* pcExpStart = rpcString;
616  lclSkipExpression( rpcString, pcEnd, cEndChar );
617  if( rpcString < pcEnd )
618  {
619  aExp = OUString( pcExpStart, static_cast< sal_Int32 >( rpcString - pcExpStart ) ).trim();
620  ++rpcString;
621  }
622  return aExp;
623 }
624 
625 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Token not recognized.
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
static css::sheet::GeneralFunction GetFunctionFromString(const OUString &rString)
function is determined automatically.
The 'cell-content-is-whole-number' token.
The 'cell-content-text-length' token.
static void ConvertDateTimeToString(const DateTime &aDateTime, OUStringBuffer &sDate)
static css::sheet::DataPilotFieldOrientation GetOrientationFromString(const OUString &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...
numerical values are counted.
sum of all numerical values is calculated.
static void GetStringFromDetObjType(OUString &rString, const ScDetectiveObjType eObjType)
product of all numerical values is calculated.
sal_uInt16 sal_Unicode
static ScDetectiveObjType GetDetObjTypeFromString(const OUString &rString)
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
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:331
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:39
average of all numerical values is calculated.
static ScSubTotalFunc GetSubTotalFuncFromString(const OUString &rString)
static void ConvertCellRangeAddress(OUString &sFormula)
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.
The 'cell-content' token.
OUString maOperand1
A comparison operator if existing.
static void GetStringFromDetOpType(OUString &rString, const ScDetOpType eOpType)
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.
ScDetOpType
Definition: detdata.hxx:28
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.
static ScGeneralFunction GetFunctionFromString2(const OUString &rString)
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 void GetStringFromFunction(OUString &rString, const sal_Int16 eFunction)
The 'and' token.
sal_Int32 nLength
The 'cell-content-is-between' token.
ScSubTotalFunc
Definition: global.hxx:844
sal_Int32 mnEndIndex
Second operand of 'between' conditions.
RedlineType meType
css::sheet::ValidationType meValidation
The leading condition token.
static void GetStringFromOrientation(OUString &rString, const css::sheet::DataPilotFieldOrientation eOrientation)
static bool GetDetOpTypeFromString(ScDetOpType &rDetOpType, const OUString &rString)
ScDocument * GetDocument() const
Definition: docuno.cxx:448