xref: /AOO41X/main/chart2/source/tools/XMLRangeHelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_chart2.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include "XMLRangeHelper.hxx"
32*cdf0e10cSrcweir #include <unotools/charclass.hxx>
33*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir #include <algorithm>
36*cdf0e10cSrcweir #include <functional>
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir using ::rtl::OUString;
39*cdf0e10cSrcweir using ::rtl::OUStringBuffer;
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir // ================================================================================
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir namespace
44*cdf0e10cSrcweir {
45*cdf0e10cSrcweir /** unary function that escapes backslashes and single quotes in a sal_Unicode
46*cdf0e10cSrcweir     array (which you can get from an OUString with getStr()) and puts the result
47*cdf0e10cSrcweir     into the OUStringBuffer given in the CTOR
48*cdf0e10cSrcweir  */
49*cdf0e10cSrcweir class lcl_Escape : public ::std::unary_function< sal_Unicode, void >
50*cdf0e10cSrcweir {
51*cdf0e10cSrcweir public:
52*cdf0e10cSrcweir     lcl_Escape( ::rtl::OUStringBuffer & aResultBuffer ) : m_aResultBuffer( aResultBuffer ) {}
53*cdf0e10cSrcweir     void operator() ( sal_Unicode aChar )
54*cdf0e10cSrcweir     {
55*cdf0e10cSrcweir         static const sal_Unicode m_aQuote( '\'' );
56*cdf0e10cSrcweir         static const sal_Unicode m_aBackslash( '\\' );
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir         if( aChar == m_aQuote ||
59*cdf0e10cSrcweir             aChar == m_aBackslash )
60*cdf0e10cSrcweir             m_aResultBuffer.append( m_aBackslash );
61*cdf0e10cSrcweir         m_aResultBuffer.append( aChar );
62*cdf0e10cSrcweir     }
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir private:
65*cdf0e10cSrcweir     ::rtl::OUStringBuffer & m_aResultBuffer;
66*cdf0e10cSrcweir };
67*cdf0e10cSrcweir 
68*cdf0e10cSrcweir // ----------------------------------------
69*cdf0e10cSrcweir 
70*cdf0e10cSrcweir /** unary function that removes backslash escapes in a sal_Unicode array (which
71*cdf0e10cSrcweir     you can get from an OUString with getStr()) and puts the result into the
72*cdf0e10cSrcweir     OUStringBuffer given in the CTOR
73*cdf0e10cSrcweir  */
74*cdf0e10cSrcweir class lcl_UnEscape : public ::std::unary_function< sal_Unicode, void >
75*cdf0e10cSrcweir {
76*cdf0e10cSrcweir public:
77*cdf0e10cSrcweir     lcl_UnEscape( ::rtl::OUStringBuffer & aResultBuffer ) : m_aResultBuffer( aResultBuffer ) {}
78*cdf0e10cSrcweir     void operator() ( sal_Unicode aChar )
79*cdf0e10cSrcweir     {
80*cdf0e10cSrcweir         static const sal_Unicode m_aBackslash( '\\' );
81*cdf0e10cSrcweir 
82*cdf0e10cSrcweir         if( aChar != m_aBackslash )
83*cdf0e10cSrcweir             m_aResultBuffer.append( aChar );
84*cdf0e10cSrcweir     }
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir private:
87*cdf0e10cSrcweir     ::rtl::OUStringBuffer & m_aResultBuffer;
88*cdf0e10cSrcweir };
89*cdf0e10cSrcweir 
90*cdf0e10cSrcweir // ----------------------------------------
91*cdf0e10cSrcweir 
92*cdf0e10cSrcweir OUStringBuffer lcl_getXMLStringForCell( const ::chart::XMLRangeHelper::Cell & rCell )
93*cdf0e10cSrcweir {
94*cdf0e10cSrcweir     ::rtl::OUStringBuffer aBuffer;
95*cdf0e10cSrcweir     if( rCell.empty())
96*cdf0e10cSrcweir         return aBuffer;
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir     sal_Int32 nCol = rCell.nColumn;
99*cdf0e10cSrcweir     aBuffer.append( (sal_Unicode)'.' );
100*cdf0e10cSrcweir     if( ! rCell.bRelativeColumn )
101*cdf0e10cSrcweir         aBuffer.append( (sal_Unicode)'$' );
102*cdf0e10cSrcweir 
103*cdf0e10cSrcweir     // get A, B, C, ..., AA, AB, ... representation of column number
104*cdf0e10cSrcweir     if( nCol < 26 )
105*cdf0e10cSrcweir         aBuffer.append( (sal_Unicode)('A' + nCol) );
106*cdf0e10cSrcweir     else if( nCol < 702 )
107*cdf0e10cSrcweir     {
108*cdf0e10cSrcweir         aBuffer.append( (sal_Unicode)('A' + nCol / 26 - 1 ));
109*cdf0e10cSrcweir         aBuffer.append( (sal_Unicode)('A' + nCol % 26) );
110*cdf0e10cSrcweir     }
111*cdf0e10cSrcweir     else    // works for nCol <= 18,278
112*cdf0e10cSrcweir     {
113*cdf0e10cSrcweir         aBuffer.append( (sal_Unicode)('A' + nCol / 702 - 1 ));
114*cdf0e10cSrcweir         aBuffer.append( (sal_Unicode)('A' + (nCol % 702) / 26 ));
115*cdf0e10cSrcweir         aBuffer.append( (sal_Unicode)('A' + nCol % 26) );
116*cdf0e10cSrcweir     }
117*cdf0e10cSrcweir 
118*cdf0e10cSrcweir     // write row number as number
119*cdf0e10cSrcweir     if( ! rCell.bRelativeRow )
120*cdf0e10cSrcweir         aBuffer.append( (sal_Unicode)'$' );
121*cdf0e10cSrcweir     aBuffer.append( rCell.nRow + (sal_Int32)1 );
122*cdf0e10cSrcweir 
123*cdf0e10cSrcweir     return aBuffer;
124*cdf0e10cSrcweir }
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir void lcl_getSingleCellAddressFromXMLString(
127*cdf0e10cSrcweir     const ::rtl::OUString& rXMLString,
128*cdf0e10cSrcweir     sal_Int32 nStartPos, sal_Int32 nEndPos,
129*cdf0e10cSrcweir     ::chart::XMLRangeHelper::Cell & rOutCell )
130*cdf0e10cSrcweir {
131*cdf0e10cSrcweir     // expect "\$?[a-zA-Z]+\$?[1-9][0-9]*"
132*cdf0e10cSrcweir     static const sal_Unicode aDollar( '$' );
133*cdf0e10cSrcweir     static const sal_Unicode aLetterA( 'A' );
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir     ::rtl::OUString aCellStr = rXMLString.copy( nStartPos, nEndPos - nStartPos + 1 ).toAsciiUpperCase();
136*cdf0e10cSrcweir     const sal_Unicode* pStrArray = aCellStr.getStr();
137*cdf0e10cSrcweir     sal_Int32 nLength = aCellStr.getLength();
138*cdf0e10cSrcweir     sal_Int32 i = nLength - 1, nColumn = 0;
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir     // parse number for row
141*cdf0e10cSrcweir     while( CharClass::isAsciiDigit( pStrArray[ i ] ) && i >= 0 )
142*cdf0e10cSrcweir         i--;
143*cdf0e10cSrcweir     rOutCell.nRow = (aCellStr.copy( i + 1 )).toInt32() - 1;
144*cdf0e10cSrcweir     // a dollar in XML means absolute (whereas in UI it means relative)
145*cdf0e10cSrcweir     if( pStrArray[ i ] == aDollar )
146*cdf0e10cSrcweir     {
147*cdf0e10cSrcweir         i--;
148*cdf0e10cSrcweir         rOutCell.bRelativeRow = false;
149*cdf0e10cSrcweir     }
150*cdf0e10cSrcweir     else
151*cdf0e10cSrcweir         rOutCell.bRelativeRow = true;
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir     // parse rest for column
154*cdf0e10cSrcweir     sal_Int32 nPower = 1;
155*cdf0e10cSrcweir     while( CharClass::isAsciiAlpha( pStrArray[ i ] ))
156*cdf0e10cSrcweir     {
157*cdf0e10cSrcweir         nColumn += (pStrArray[ i ] - aLetterA + 1) * nPower;
158*cdf0e10cSrcweir         i--;
159*cdf0e10cSrcweir         nPower *= 26;
160*cdf0e10cSrcweir     }
161*cdf0e10cSrcweir     rOutCell.nColumn = nColumn - 1;
162*cdf0e10cSrcweir 
163*cdf0e10cSrcweir     rOutCell.bRelativeColumn = true;
164*cdf0e10cSrcweir     if( i >= 0 &&
165*cdf0e10cSrcweir         pStrArray[ i ] == aDollar )
166*cdf0e10cSrcweir         rOutCell.bRelativeColumn = false;
167*cdf0e10cSrcweir     rOutCell.bIsEmpty = false;
168*cdf0e10cSrcweir }
169*cdf0e10cSrcweir 
170*cdf0e10cSrcweir bool lcl_getCellAddressFromXMLString(
171*cdf0e10cSrcweir     const ::rtl::OUString& rXMLString,
172*cdf0e10cSrcweir     sal_Int32 nStartPos, sal_Int32 nEndPos,
173*cdf0e10cSrcweir     ::chart::XMLRangeHelper::Cell & rOutCell,
174*cdf0e10cSrcweir     ::rtl::OUString& rOutTableName )
175*cdf0e10cSrcweir {
176*cdf0e10cSrcweir     static const sal_Unicode aDot( '.' );
177*cdf0e10cSrcweir     static const sal_Unicode aQuote( '\'' );
178*cdf0e10cSrcweir     static const sal_Unicode aBackslash( '\\' );
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir     sal_Int32 nNextDelimiterPos = nStartPos;
181*cdf0e10cSrcweir 
182*cdf0e10cSrcweir     sal_Int32 nDelimiterPos = nStartPos;
183*cdf0e10cSrcweir     bool bInQuotation = false;
184*cdf0e10cSrcweir     // parse table name
185*cdf0e10cSrcweir     while( nDelimiterPos < nEndPos &&
186*cdf0e10cSrcweir            ( bInQuotation || rXMLString[ nDelimiterPos ] != aDot ))
187*cdf0e10cSrcweir     {
188*cdf0e10cSrcweir         // skip escaped characters (with backslash)
189*cdf0e10cSrcweir         if( rXMLString[ nDelimiterPos ] == aBackslash )
190*cdf0e10cSrcweir             ++nDelimiterPos;
191*cdf0e10cSrcweir         // toggle quotation mode when finding single quotes
192*cdf0e10cSrcweir         else if( rXMLString[ nDelimiterPos ] == aQuote )
193*cdf0e10cSrcweir             bInQuotation = ! bInQuotation;
194*cdf0e10cSrcweir 
195*cdf0e10cSrcweir         ++nDelimiterPos;
196*cdf0e10cSrcweir     }
197*cdf0e10cSrcweir 
198*cdf0e10cSrcweir     if( nDelimiterPos == -1 )
199*cdf0e10cSrcweir         return false;
200*cdf0e10cSrcweir 
201*cdf0e10cSrcweir     if( nDelimiterPos > nStartPos && nDelimiterPos < nEndPos )
202*cdf0e10cSrcweir     {
203*cdf0e10cSrcweir         // there is a table name before the address
204*cdf0e10cSrcweir 
205*cdf0e10cSrcweir         ::rtl::OUStringBuffer aTableNameBuffer;
206*cdf0e10cSrcweir         const sal_Unicode * pTableName = rXMLString.getStr();
207*cdf0e10cSrcweir 
208*cdf0e10cSrcweir         // remove escapes from table name
209*cdf0e10cSrcweir         ::std::for_each( pTableName + nStartPos,
210*cdf0e10cSrcweir                          pTableName + nDelimiterPos,
211*cdf0e10cSrcweir                          lcl_UnEscape( aTableNameBuffer ));
212*cdf0e10cSrcweir 
213*cdf0e10cSrcweir         // unquote quoted table name
214*cdf0e10cSrcweir         const sal_Unicode * pBuf = aTableNameBuffer.getStr();
215*cdf0e10cSrcweir         if( pBuf[ 0 ] == aQuote &&
216*cdf0e10cSrcweir             pBuf[ aTableNameBuffer.getLength() - 1 ] == aQuote )
217*cdf0e10cSrcweir         {
218*cdf0e10cSrcweir             ::rtl::OUString aName = aTableNameBuffer.makeStringAndClear();
219*cdf0e10cSrcweir             rOutTableName = aName.copy( 1, aName.getLength() - 2 );
220*cdf0e10cSrcweir         }
221*cdf0e10cSrcweir         else
222*cdf0e10cSrcweir             rOutTableName = aTableNameBuffer.makeStringAndClear();
223*cdf0e10cSrcweir     }
224*cdf0e10cSrcweir     else
225*cdf0e10cSrcweir         nDelimiterPos = nStartPos;
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir     for( sal_Int32 i = 0;
228*cdf0e10cSrcweir          nNextDelimiterPos < nEndPos;
229*cdf0e10cSrcweir          nDelimiterPos = nNextDelimiterPos, i++ )
230*cdf0e10cSrcweir     {
231*cdf0e10cSrcweir         nNextDelimiterPos = rXMLString.indexOf( aDot, nDelimiterPos + 1 );
232*cdf0e10cSrcweir         if( nNextDelimiterPos == -1 ||
233*cdf0e10cSrcweir             nNextDelimiterPos > nEndPos )
234*cdf0e10cSrcweir             nNextDelimiterPos = nEndPos + 1;
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir         if( i==0 )
237*cdf0e10cSrcweir             // only take first cell
238*cdf0e10cSrcweir             lcl_getSingleCellAddressFromXMLString(
239*cdf0e10cSrcweir                 rXMLString, nDelimiterPos + 1, nNextDelimiterPos - 1, rOutCell );
240*cdf0e10cSrcweir     }
241*cdf0e10cSrcweir 
242*cdf0e10cSrcweir     return true;
243*cdf0e10cSrcweir }
244*cdf0e10cSrcweir 
245*cdf0e10cSrcweir bool lcl_getCellRangeAddressFromXMLString(
246*cdf0e10cSrcweir     const ::rtl::OUString& rXMLString,
247*cdf0e10cSrcweir     sal_Int32 nStartPos, sal_Int32 nEndPos,
248*cdf0e10cSrcweir     ::chart::XMLRangeHelper::CellRange & rOutRange )
249*cdf0e10cSrcweir {
250*cdf0e10cSrcweir     bool bResult = true;
251*cdf0e10cSrcweir     static const sal_Unicode aColon( ':' );
252*cdf0e10cSrcweir     static const sal_Unicode aQuote( '\'' );
253*cdf0e10cSrcweir     static const sal_Unicode aBackslash( '\\' );
254*cdf0e10cSrcweir 
255*cdf0e10cSrcweir     sal_Int32 nDelimiterPos = nStartPos;
256*cdf0e10cSrcweir     bool bInQuotation = false;
257*cdf0e10cSrcweir     // parse table name
258*cdf0e10cSrcweir     while( nDelimiterPos < nEndPos &&
259*cdf0e10cSrcweir            ( bInQuotation || rXMLString[ nDelimiterPos ] != aColon ))
260*cdf0e10cSrcweir     {
261*cdf0e10cSrcweir         // skip escaped characters (with backslash)
262*cdf0e10cSrcweir         if( rXMLString[ nDelimiterPos ] == aBackslash )
263*cdf0e10cSrcweir             ++nDelimiterPos;
264*cdf0e10cSrcweir         // toggle quotation mode when finding single quotes
265*cdf0e10cSrcweir         else if( rXMLString[ nDelimiterPos ] == aQuote )
266*cdf0e10cSrcweir             bInQuotation = ! bInQuotation;
267*cdf0e10cSrcweir 
268*cdf0e10cSrcweir         ++nDelimiterPos;
269*cdf0e10cSrcweir     }
270*cdf0e10cSrcweir 
271*cdf0e10cSrcweir     if( nDelimiterPos == nEndPos )
272*cdf0e10cSrcweir     {
273*cdf0e10cSrcweir         // only one cell
274*cdf0e10cSrcweir         bResult = lcl_getCellAddressFromXMLString( rXMLString, nStartPos, nEndPos,
275*cdf0e10cSrcweir                                                    rOutRange.aUpperLeft,
276*cdf0e10cSrcweir                                                    rOutRange.aTableName );
277*cdf0e10cSrcweir         if( !rOutRange.aTableName.getLength() )
278*cdf0e10cSrcweir             bResult = false;
279*cdf0e10cSrcweir     }
280*cdf0e10cSrcweir     else
281*cdf0e10cSrcweir     {
282*cdf0e10cSrcweir         // range (separated by a colon)
283*cdf0e10cSrcweir         bResult = lcl_getCellAddressFromXMLString( rXMLString, nStartPos, nDelimiterPos - 1,
284*cdf0e10cSrcweir                                                    rOutRange.aUpperLeft,
285*cdf0e10cSrcweir                                                    rOutRange.aTableName );
286*cdf0e10cSrcweir         if( !rOutRange.aTableName.getLength() )
287*cdf0e10cSrcweir             bResult = false;
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir         ::rtl::OUString sTableSecondName;
290*cdf0e10cSrcweir         if( bResult )
291*cdf0e10cSrcweir         {
292*cdf0e10cSrcweir             bResult = lcl_getCellAddressFromXMLString( rXMLString, nDelimiterPos + 1, nEndPos,
293*cdf0e10cSrcweir                                                        rOutRange.aLowerRight,
294*cdf0e10cSrcweir                                                        sTableSecondName );
295*cdf0e10cSrcweir         }
296*cdf0e10cSrcweir         if( bResult &&
297*cdf0e10cSrcweir             sTableSecondName.getLength() &&
298*cdf0e10cSrcweir             ! sTableSecondName.equals( rOutRange.aTableName ))
299*cdf0e10cSrcweir             bResult = false;
300*cdf0e10cSrcweir     }
301*cdf0e10cSrcweir 
302*cdf0e10cSrcweir     return bResult;
303*cdf0e10cSrcweir }
304*cdf0e10cSrcweir 
305*cdf0e10cSrcweir } // anonymous namespace
306*cdf0e10cSrcweir 
307*cdf0e10cSrcweir // ================================================================================
308*cdf0e10cSrcweir 
309*cdf0e10cSrcweir namespace chart
310*cdf0e10cSrcweir {
311*cdf0e10cSrcweir namespace XMLRangeHelper
312*cdf0e10cSrcweir {
313*cdf0e10cSrcweir 
314*cdf0e10cSrcweir CellRange getCellRangeFromXMLString( const OUString & rXMLString )
315*cdf0e10cSrcweir {
316*cdf0e10cSrcweir     static const sal_Unicode aSpace( ' ' );
317*cdf0e10cSrcweir     static const sal_Unicode aQuote( '\'' );
318*cdf0e10cSrcweir //     static const sal_Unicode aDoubleQuote( '\"' );
319*cdf0e10cSrcweir     static const sal_Unicode aDollar( '$' );
320*cdf0e10cSrcweir     static const sal_Unicode aBackslash( '\\' );
321*cdf0e10cSrcweir 
322*cdf0e10cSrcweir     sal_Int32 nStartPos = 0;
323*cdf0e10cSrcweir     sal_Int32 nEndPos = nStartPos;
324*cdf0e10cSrcweir     const sal_Int32 nLength = rXMLString.getLength();
325*cdf0e10cSrcweir 
326*cdf0e10cSrcweir     // reset
327*cdf0e10cSrcweir     CellRange aResult;
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir     // iterate over different ranges
330*cdf0e10cSrcweir     for( sal_Int32 i = 0;
331*cdf0e10cSrcweir          nEndPos < nLength;
332*cdf0e10cSrcweir          nStartPos = ++nEndPos, i++ )
333*cdf0e10cSrcweir     {
334*cdf0e10cSrcweir         // find start point of next range
335*cdf0e10cSrcweir 
336*cdf0e10cSrcweir         // ignore leading '$'
337*cdf0e10cSrcweir         if( rXMLString[ nEndPos ] == aDollar)
338*cdf0e10cSrcweir             nEndPos++;
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir         bool bInQuotation = false;
341*cdf0e10cSrcweir         // parse range
342*cdf0e10cSrcweir         while( nEndPos < nLength &&
343*cdf0e10cSrcweir                ( bInQuotation || rXMLString[ nEndPos ] != aSpace ))
344*cdf0e10cSrcweir         {
345*cdf0e10cSrcweir             // skip escaped characters (with backslash)
346*cdf0e10cSrcweir             if( rXMLString[ nEndPos ] == aBackslash )
347*cdf0e10cSrcweir                 ++nEndPos;
348*cdf0e10cSrcweir             // toggle quotation mode when finding single quotes
349*cdf0e10cSrcweir             else if( rXMLString[ nEndPos ] == aQuote )
350*cdf0e10cSrcweir                 bInQuotation = ! bInQuotation;
351*cdf0e10cSrcweir 
352*cdf0e10cSrcweir             ++nEndPos;
353*cdf0e10cSrcweir         }
354*cdf0e10cSrcweir 
355*cdf0e10cSrcweir         if( ! lcl_getCellRangeAddressFromXMLString(
356*cdf0e10cSrcweir                 rXMLString,
357*cdf0e10cSrcweir                 nStartPos, nEndPos - 1,
358*cdf0e10cSrcweir                 aResult ))
359*cdf0e10cSrcweir         {
360*cdf0e10cSrcweir             // if an error occured, bail out
361*cdf0e10cSrcweir             return CellRange();
362*cdf0e10cSrcweir         }
363*cdf0e10cSrcweir     }
364*cdf0e10cSrcweir 
365*cdf0e10cSrcweir     return aResult;
366*cdf0e10cSrcweir }
367*cdf0e10cSrcweir 
368*cdf0e10cSrcweir OUString getXMLStringFromCellRange( const CellRange & rRange )
369*cdf0e10cSrcweir {
370*cdf0e10cSrcweir     static const sal_Unicode aSpace( ' ' );
371*cdf0e10cSrcweir     static const sal_Unicode aQuote( '\'' );
372*cdf0e10cSrcweir 
373*cdf0e10cSrcweir     ::rtl::OUStringBuffer aBuffer;
374*cdf0e10cSrcweir 
375*cdf0e10cSrcweir     if( (rRange.aTableName).getLength())
376*cdf0e10cSrcweir     {
377*cdf0e10cSrcweir         bool bNeedsEscaping = ( rRange.aTableName.indexOf( aQuote ) > -1 );
378*cdf0e10cSrcweir         bool bNeedsQuoting = bNeedsEscaping || ( rRange.aTableName.indexOf( aSpace ) > -1 );
379*cdf0e10cSrcweir 
380*cdf0e10cSrcweir         // quote table name if it contains spaces or quotes
381*cdf0e10cSrcweir         if( bNeedsQuoting )
382*cdf0e10cSrcweir         {
383*cdf0e10cSrcweir             // leading quote
384*cdf0e10cSrcweir             aBuffer.append( aQuote );
385*cdf0e10cSrcweir 
386*cdf0e10cSrcweir             // escape existing quotes
387*cdf0e10cSrcweir             if( bNeedsEscaping )
388*cdf0e10cSrcweir             {
389*cdf0e10cSrcweir                 const sal_Unicode * pTableNameBeg = rRange.aTableName.getStr();
390*cdf0e10cSrcweir 
391*cdf0e10cSrcweir                 // append the quoted string at the buffer
392*cdf0e10cSrcweir                 ::std::for_each( pTableNameBeg,
393*cdf0e10cSrcweir                                  pTableNameBeg + rRange.aTableName.getLength(),
394*cdf0e10cSrcweir                                  lcl_Escape( aBuffer ) );
395*cdf0e10cSrcweir             }
396*cdf0e10cSrcweir             else
397*cdf0e10cSrcweir                 aBuffer.append( rRange.aTableName );
398*cdf0e10cSrcweir 
399*cdf0e10cSrcweir             // final quote
400*cdf0e10cSrcweir             aBuffer.append( aQuote );
401*cdf0e10cSrcweir         }
402*cdf0e10cSrcweir         else
403*cdf0e10cSrcweir             aBuffer.append( rRange.aTableName );
404*cdf0e10cSrcweir     }
405*cdf0e10cSrcweir     aBuffer.append( lcl_getXMLStringForCell( rRange.aUpperLeft ));
406*cdf0e10cSrcweir 
407*cdf0e10cSrcweir     if( ! rRange.aLowerRight.empty())
408*cdf0e10cSrcweir     {
409*cdf0e10cSrcweir         // we have a range (not a single cell)
410*cdf0e10cSrcweir         aBuffer.append( sal_Unicode( ':' ));
411*cdf0e10cSrcweir         aBuffer.append( lcl_getXMLStringForCell( rRange.aLowerRight ));
412*cdf0e10cSrcweir     }
413*cdf0e10cSrcweir 
414*cdf0e10cSrcweir     return aBuffer.makeStringAndClear();
415*cdf0e10cSrcweir }
416*cdf0e10cSrcweir 
417*cdf0e10cSrcweir } //  namespace XMLRangeHelper
418*cdf0e10cSrcweir } //  namespace chart
419