xref: /AOO41X/main/sc/source/core/tool/doubleref.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
1*b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*b3f79822SAndrew Rist  * distributed with this work for additional information
6*b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9*b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15*b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17*b3f79822SAndrew Rist  * specific language governing permissions and limitations
18*b3f79822SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*b3f79822SAndrew Rist  *************************************************************/
21*b3f79822SAndrew Rist 
22*b3f79822SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "doubleref.hxx"
30cdf0e10cSrcweir #include "cell.hxx"
31cdf0e10cSrcweir #include "global.hxx"
32cdf0e10cSrcweir #include "document.hxx"
33cdf0e10cSrcweir #include "queryparam.hxx"
34cdf0e10cSrcweir #include "globstr.hrc"
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #include <memory>
37cdf0e10cSrcweir #include <vector>
38cdf0e10cSrcweir 
39cdf0e10cSrcweir using ::rtl::OUString;
40cdf0e10cSrcweir using ::std::auto_ptr;
41cdf0e10cSrcweir using ::std::vector;
42cdf0e10cSrcweir 
43cdf0e10cSrcweir namespace {
44cdf0e10cSrcweir 
lcl_toUpper(OUString & rStr)45cdf0e10cSrcweir void lcl_toUpper(OUString& rStr)
46cdf0e10cSrcweir {
47cdf0e10cSrcweir     rStr = ScGlobal::pCharClass->toUpper(rStr.trim(), 0, static_cast<xub_StrLen>(rStr.getLength()));
48cdf0e10cSrcweir }
49cdf0e10cSrcweir 
lcl_createStarQuery(ScQueryParamBase * pParam,const ScDBRangeBase * pDBRef,const ScDBRangeBase * pQueryRef)50cdf0e10cSrcweir bool lcl_createStarQuery(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
51cdf0e10cSrcweir {
52cdf0e10cSrcweir     // A valid StarQuery must be at least 4 columns wide. To be precise it
53cdf0e10cSrcweir     // should be exactly 4 columns ...
54cdf0e10cSrcweir     // Additionally, if this wasn't checked, a formula pointing to a valid 1-3
55cdf0e10cSrcweir     // column Excel style query range immediately left to itself would result
56cdf0e10cSrcweir     // in a circular reference when the field name or operator or value (first
57cdf0e10cSrcweir     // to third query range column) is obtained (#i58354#). Furthermore, if the
58cdf0e10cSrcweir     // range wasn't sufficiently specified data changes wouldn't flag formula
59cdf0e10cSrcweir     // cells for recalculation.
60cdf0e10cSrcweir 
61cdf0e10cSrcweir     if (pQueryRef->getColSize() < 4)
62cdf0e10cSrcweir         return false;
63cdf0e10cSrcweir 
64cdf0e10cSrcweir     sal_Bool bValid;
65cdf0e10cSrcweir     sal_Bool bFound;
66cdf0e10cSrcweir     OUString aCellStr;
67cdf0e10cSrcweir     SCSIZE nIndex = 0;
68cdf0e10cSrcweir     SCROW nRow = 0;
69cdf0e10cSrcweir     SCROW nRows = pDBRef->getRowSize();
70cdf0e10cSrcweir     SCSIZE nNewEntries = static_cast<SCSIZE>(nRows);
71cdf0e10cSrcweir     pParam->Resize(nNewEntries);
72cdf0e10cSrcweir 
73cdf0e10cSrcweir     do
74cdf0e10cSrcweir     {
75cdf0e10cSrcweir         ScQueryEntry& rEntry = pParam->GetEntry(nIndex);
76cdf0e10cSrcweir 
77cdf0e10cSrcweir         bValid = sal_False;
78cdf0e10cSrcweir 
79cdf0e10cSrcweir         if (nIndex > 0)
80cdf0e10cSrcweir         {
81cdf0e10cSrcweir             // For all entries after the first one, check the and/or connector in the first column.
82cdf0e10cSrcweir             aCellStr = pQueryRef->getString(0, nRow);
83cdf0e10cSrcweir             lcl_toUpper(aCellStr);
84cdf0e10cSrcweir             if ( aCellStr.equals(ScGlobal::GetRscString(STR_TABLE_UND)) )
85cdf0e10cSrcweir             {
86cdf0e10cSrcweir                 rEntry.eConnect = SC_AND;
87cdf0e10cSrcweir                 bValid = sal_True;
88cdf0e10cSrcweir             }
89cdf0e10cSrcweir             else if ( aCellStr.equals(ScGlobal::GetRscString(STR_TABLE_ODER)) )
90cdf0e10cSrcweir             {
91cdf0e10cSrcweir                 rEntry.eConnect = SC_OR;
92cdf0e10cSrcweir                 bValid = sal_True;
93cdf0e10cSrcweir             }
94cdf0e10cSrcweir         }
95cdf0e10cSrcweir 
96cdf0e10cSrcweir         if ((nIndex < 1) || bValid)
97cdf0e10cSrcweir         {
98cdf0e10cSrcweir             // field name in the 2nd column.
99cdf0e10cSrcweir             bFound = sal_False;
100cdf0e10cSrcweir             aCellStr = pQueryRef->getString(1, nRow);
101cdf0e10cSrcweir             SCCOL nField = pDBRef->findFieldColumn(aCellStr); // TODO: must be case insensitive comparison.
102cdf0e10cSrcweir             if (ValidCol(nField))
103cdf0e10cSrcweir             {
104cdf0e10cSrcweir                 rEntry.nField = nField;
105cdf0e10cSrcweir                 bValid = true;
106cdf0e10cSrcweir             }
107cdf0e10cSrcweir             else
108cdf0e10cSrcweir                 bValid = false;
109cdf0e10cSrcweir         }
110cdf0e10cSrcweir 
111cdf0e10cSrcweir         if (bValid)
112cdf0e10cSrcweir         {
113cdf0e10cSrcweir             // equality, non-equality operator in the 3rd column.
114cdf0e10cSrcweir             bFound = sal_False;
115cdf0e10cSrcweir             aCellStr = pQueryRef->getString(2, nRow);
116cdf0e10cSrcweir             lcl_toUpper(aCellStr);
117cdf0e10cSrcweir             const sal_Unicode* p = aCellStr.getStr();
118cdf0e10cSrcweir             if (p[0] == sal_Unicode('<'))
119cdf0e10cSrcweir             {
120cdf0e10cSrcweir                 if (p[1] == sal_Unicode('>'))
121cdf0e10cSrcweir                     rEntry.eOp = SC_NOT_EQUAL;
122cdf0e10cSrcweir                 else if (p[1] == sal_Unicode('='))
123cdf0e10cSrcweir                     rEntry.eOp = SC_LESS_EQUAL;
124cdf0e10cSrcweir                 else
125cdf0e10cSrcweir                     rEntry.eOp = SC_LESS;
126cdf0e10cSrcweir             }
127cdf0e10cSrcweir             else if (p[0] == sal_Unicode('>'))
128cdf0e10cSrcweir             {
129cdf0e10cSrcweir                 if (p[1] == sal_Unicode('='))
130cdf0e10cSrcweir                     rEntry.eOp = SC_GREATER_EQUAL;
131cdf0e10cSrcweir                 else
132cdf0e10cSrcweir                     rEntry.eOp = SC_GREATER;
133cdf0e10cSrcweir             }
134cdf0e10cSrcweir             else if (p[0] == sal_Unicode('='))
135cdf0e10cSrcweir                 rEntry.eOp = SC_EQUAL;
136cdf0e10cSrcweir 
137cdf0e10cSrcweir         }
138cdf0e10cSrcweir 
139cdf0e10cSrcweir         if (bValid)
140cdf0e10cSrcweir         {
141cdf0e10cSrcweir             // Finally, the right-hand-side value in the 4th column.
142cdf0e10cSrcweir             *rEntry.pStr = pQueryRef->getString(3, nRow);
143cdf0e10cSrcweir             rEntry.bDoQuery = sal_True;
144cdf0e10cSrcweir         }
145cdf0e10cSrcweir         nIndex++;
146cdf0e10cSrcweir         nRow++;
147cdf0e10cSrcweir     }
148cdf0e10cSrcweir     while (bValid && (nRow < nRows) /* && (nIndex < MAXQUERY) */ );
149cdf0e10cSrcweir     return bValid;
150cdf0e10cSrcweir }
151cdf0e10cSrcweir 
lcl_createExcelQuery(ScQueryParamBase * pParam,const ScDBRangeBase * pDBRef,const ScDBRangeBase * pQueryRef)152cdf0e10cSrcweir bool lcl_createExcelQuery(
153cdf0e10cSrcweir     ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
154cdf0e10cSrcweir {
155cdf0e10cSrcweir     bool bValid = true;
156cdf0e10cSrcweir     SCCOL nCols = pQueryRef->getColSize();
157cdf0e10cSrcweir     SCROW nRows = pQueryRef->getRowSize();
158cdf0e10cSrcweir     vector<SCCOL> aFields(nCols);
159cdf0e10cSrcweir     SCCOL nCol = 0;
160cdf0e10cSrcweir     while (bValid && (nCol < nCols))
161cdf0e10cSrcweir     {
162cdf0e10cSrcweir         OUString aQueryStr = pQueryRef->getString(nCol, 0);
163cdf0e10cSrcweir         SCCOL nField = pDBRef->findFieldColumn(aQueryStr);
164cdf0e10cSrcweir         if (ValidCol(nField))
165cdf0e10cSrcweir             aFields[nCol] = nField;
166cdf0e10cSrcweir         else
167cdf0e10cSrcweir             bValid = false;
168cdf0e10cSrcweir         ++nCol;
169cdf0e10cSrcweir     }
170cdf0e10cSrcweir 
171cdf0e10cSrcweir     if (bValid)
172cdf0e10cSrcweir     {
173cdf0e10cSrcweir //      sal_uLong nVisible = 0;
174cdf0e10cSrcweir //      for ( nCol=nCol1; nCol<=nCol2; nCol++ )
175cdf0e10cSrcweir //          nVisible += aCol[nCol].VisibleCount( nRow1+1, nRow2 );
176cdf0e10cSrcweir 
177cdf0e10cSrcweir         // Count the number of visible cells (excluding the header row).  Each
178cdf0e10cSrcweir         // visible cell corresponds with a single query.
179cdf0e10cSrcweir         SCSIZE nVisible = pQueryRef->getVisibleDataCellCount();
180cdf0e10cSrcweir         if ( nVisible > SCSIZE_MAX / sizeof(void*) )
181cdf0e10cSrcweir         {
182cdf0e10cSrcweir             DBG_ERROR("zu viele Filterkritierien");
183cdf0e10cSrcweir             nVisible = 0;
184cdf0e10cSrcweir         }
185cdf0e10cSrcweir 
186cdf0e10cSrcweir         SCSIZE nNewEntries = nVisible;
187cdf0e10cSrcweir         pParam->Resize( nNewEntries );
188cdf0e10cSrcweir 
189cdf0e10cSrcweir         SCSIZE nIndex = 0;
190cdf0e10cSrcweir         SCROW nRow = 1;
191cdf0e10cSrcweir         String aCellStr;
192cdf0e10cSrcweir         while (nRow < nRows)
193cdf0e10cSrcweir         {
194cdf0e10cSrcweir             nCol = 0;
195cdf0e10cSrcweir             while (nCol < nCols)
196cdf0e10cSrcweir             {
197cdf0e10cSrcweir                 aCellStr = pQueryRef->getString(nCol, nRow);
198cdf0e10cSrcweir                 ScGlobal::pCharClass->toUpper( aCellStr );
199cdf0e10cSrcweir                 if (aCellStr.Len() > 0)
200cdf0e10cSrcweir                 {
201cdf0e10cSrcweir                     if (nIndex < nNewEntries)
202cdf0e10cSrcweir                     {
203cdf0e10cSrcweir                         pParam->GetEntry(nIndex).nField = aFields[nCol];
204cdf0e10cSrcweir                         pParam->FillInExcelSyntax(aCellStr, nIndex);
205cdf0e10cSrcweir                         nIndex++;
206cdf0e10cSrcweir                         if (nIndex < nNewEntries)
207cdf0e10cSrcweir                             pParam->GetEntry(nIndex).eConnect = SC_AND;
208cdf0e10cSrcweir                     }
209cdf0e10cSrcweir                     else
210cdf0e10cSrcweir                         bValid = sal_False;
211cdf0e10cSrcweir                 }
212cdf0e10cSrcweir                 nCol++;
213cdf0e10cSrcweir             }
214cdf0e10cSrcweir             nRow++;
215cdf0e10cSrcweir             if (nIndex < nNewEntries)
216cdf0e10cSrcweir                 pParam->GetEntry(nIndex).eConnect = SC_OR;
217cdf0e10cSrcweir         }
218cdf0e10cSrcweir     }
219cdf0e10cSrcweir     return bValid;
220cdf0e10cSrcweir }
221cdf0e10cSrcweir 
lcl_fillQueryEntries(ScQueryParamBase * pParam,const ScDBRangeBase * pDBRef,const ScDBRangeBase * pQueryRef)222cdf0e10cSrcweir bool lcl_fillQueryEntries(
223cdf0e10cSrcweir     ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
224cdf0e10cSrcweir {
225cdf0e10cSrcweir     SCSIZE nCount = pParam->GetEntryCount();
226cdf0e10cSrcweir     for (SCSIZE i = 0; i < nCount; ++i)
227cdf0e10cSrcweir         pParam->GetEntry(i).Clear();
228cdf0e10cSrcweir 
229cdf0e10cSrcweir     // Standard QueryTabelle
230cdf0e10cSrcweir     bool bValid = lcl_createStarQuery(pParam, pDBRef, pQueryRef);
231cdf0e10cSrcweir     // Excel QueryTabelle
232cdf0e10cSrcweir     if (!bValid)
233cdf0e10cSrcweir         bValid = lcl_createExcelQuery(pParam, pDBRef, pQueryRef);
234cdf0e10cSrcweir 
235cdf0e10cSrcweir     nCount = pParam->GetEntryCount();
236cdf0e10cSrcweir     if (bValid)
237cdf0e10cSrcweir     {
238cdf0e10cSrcweir         //  bQueryByString muss gesetzt sein
239cdf0e10cSrcweir         for (SCSIZE i = 0; i < nCount; ++i)
240cdf0e10cSrcweir             pParam->GetEntry(i).bQueryByString = true;
241cdf0e10cSrcweir     }
242cdf0e10cSrcweir     else
243cdf0e10cSrcweir     {
244cdf0e10cSrcweir         //  nix
245cdf0e10cSrcweir         for (SCSIZE i = 0; i < nCount; ++i)
246cdf0e10cSrcweir             pParam->GetEntry(i).Clear();
247cdf0e10cSrcweir     }
248cdf0e10cSrcweir     return bValid;
249cdf0e10cSrcweir }
250cdf0e10cSrcweir 
251cdf0e10cSrcweir }
252cdf0e10cSrcweir 
253cdf0e10cSrcweir // ============================================================================
254cdf0e10cSrcweir 
ScDBRangeBase(ScDocument * pDoc,RefType eType)255cdf0e10cSrcweir ScDBRangeBase::ScDBRangeBase(ScDocument* pDoc, RefType eType) :
256cdf0e10cSrcweir     mpDoc(pDoc), meType(eType)
257cdf0e10cSrcweir {
258cdf0e10cSrcweir }
259cdf0e10cSrcweir 
~ScDBRangeBase()260cdf0e10cSrcweir ScDBRangeBase::~ScDBRangeBase()
261cdf0e10cSrcweir {
262cdf0e10cSrcweir }
263cdf0e10cSrcweir 
fillQueryEntries(ScQueryParamBase * pParam,const ScDBRangeBase * pDBRef) const264cdf0e10cSrcweir bool ScDBRangeBase::fillQueryEntries(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef) const
265cdf0e10cSrcweir {
266cdf0e10cSrcweir     if (!pDBRef)
267cdf0e10cSrcweir         return false;
268cdf0e10cSrcweir 
269cdf0e10cSrcweir     return lcl_fillQueryEntries(pParam, pDBRef, this);
270cdf0e10cSrcweir }
271cdf0e10cSrcweir 
fillQueryOptions(ScQueryParamBase * pParam)272cdf0e10cSrcweir void ScDBRangeBase::fillQueryOptions(ScQueryParamBase* pParam)
273cdf0e10cSrcweir {
274cdf0e10cSrcweir     pParam->bHasHeader = true;
275cdf0e10cSrcweir     pParam->bByRow = true;
276cdf0e10cSrcweir     pParam->bInplace = true;
277cdf0e10cSrcweir     pParam->bCaseSens = false;
278cdf0e10cSrcweir     pParam->bRegExp = false;
279cdf0e10cSrcweir     pParam->bDuplicate = true;
280cdf0e10cSrcweir     pParam->bMixedComparison = false;
281cdf0e10cSrcweir }
282cdf0e10cSrcweir 
getDoc() const283cdf0e10cSrcweir ScDocument* ScDBRangeBase::getDoc() const
284cdf0e10cSrcweir {
285cdf0e10cSrcweir     return mpDoc;
286cdf0e10cSrcweir }
287cdf0e10cSrcweir 
288cdf0e10cSrcweir // ============================================================================
289cdf0e10cSrcweir 
ScDBInternalRange(ScDocument * pDoc,const ScRange & rRange)290cdf0e10cSrcweir ScDBInternalRange::ScDBInternalRange(ScDocument* pDoc, const ScRange& rRange) :
291cdf0e10cSrcweir     ScDBRangeBase(pDoc, INTERNAL), maRange(rRange)
292cdf0e10cSrcweir {
293cdf0e10cSrcweir }
294cdf0e10cSrcweir 
~ScDBInternalRange()295cdf0e10cSrcweir ScDBInternalRange::~ScDBInternalRange()
296cdf0e10cSrcweir {
297cdf0e10cSrcweir }
298cdf0e10cSrcweir 
getRange() const299cdf0e10cSrcweir const ScRange& ScDBInternalRange::getRange() const
300cdf0e10cSrcweir {
301cdf0e10cSrcweir     return maRange;
302cdf0e10cSrcweir }
303cdf0e10cSrcweir 
getColSize() const304cdf0e10cSrcweir SCCOL ScDBInternalRange::getColSize() const
305cdf0e10cSrcweir {
306cdf0e10cSrcweir     return maRange.aEnd.Col() - maRange.aStart.Col() + 1;
307cdf0e10cSrcweir }
308cdf0e10cSrcweir 
getRowSize() const309cdf0e10cSrcweir SCROW ScDBInternalRange::getRowSize() const
310cdf0e10cSrcweir {
311cdf0e10cSrcweir     return maRange.aEnd.Row() - maRange.aStart.Row() + 1;
312cdf0e10cSrcweir }
313cdf0e10cSrcweir 
getVisibleDataCellCount() const314cdf0e10cSrcweir SCSIZE ScDBInternalRange::getVisibleDataCellCount() const
315cdf0e10cSrcweir {
316cdf0e10cSrcweir     SCCOL nCols = getColSize();
317cdf0e10cSrcweir     SCROW nRows = getRowSize();
318cdf0e10cSrcweir     if (nRows <= 1)
319cdf0e10cSrcweir         return 0;
320cdf0e10cSrcweir 
321cdf0e10cSrcweir     return (nRows-1)*nCols;
322cdf0e10cSrcweir }
323cdf0e10cSrcweir 
getString(SCCOL nCol,SCROW nRow) const324cdf0e10cSrcweir OUString ScDBInternalRange::getString(SCCOL nCol, SCROW nRow) const
325cdf0e10cSrcweir {
326cdf0e10cSrcweir     String aStr;
327cdf0e10cSrcweir     const ScAddress& s = maRange.aStart;
328cdf0e10cSrcweir     // #i109200# this is used in formula calculation, use GetInputString, not GetString
329cdf0e10cSrcweir     // (consistent with ScDBInternalRange::getCellString)
330cdf0e10cSrcweir     // GetStringForFormula is not used here, to allow querying for date values.
331cdf0e10cSrcweir     getDoc()->GetInputString(s.Col() + nCol, s.Row() + nRow, maRange.aStart.Tab(), aStr);
332cdf0e10cSrcweir     return aStr;
333cdf0e10cSrcweir }
334cdf0e10cSrcweir 
getFirstFieldColumn() const335cdf0e10cSrcweir SCCOL ScDBInternalRange::getFirstFieldColumn() const
336cdf0e10cSrcweir {
337cdf0e10cSrcweir     return getRange().aStart.Col();
338cdf0e10cSrcweir }
339cdf0e10cSrcweir 
findFieldColumn(SCCOL nIndex) const340cdf0e10cSrcweir SCCOL ScDBInternalRange::findFieldColumn(SCCOL nIndex) const
341cdf0e10cSrcweir {
342cdf0e10cSrcweir     const ScRange& rRange = getRange();
343cdf0e10cSrcweir     const ScAddress& s = rRange.aStart;
344cdf0e10cSrcweir     const ScAddress& e = rRange.aEnd;
345cdf0e10cSrcweir 
346cdf0e10cSrcweir     SCCOL nDBCol1 = s.Col();
347cdf0e10cSrcweir     SCCOL nDBCol2 = e.Col();
348cdf0e10cSrcweir 
349cdf0e10cSrcweir     if ( nIndex <= 0 || nIndex > (nDBCol2 - nDBCol1 + 1) )
350cdf0e10cSrcweir         return nDBCol1;
351cdf0e10cSrcweir 
352cdf0e10cSrcweir     return Min(nDBCol2, static_cast<SCCOL>(nDBCol1 + nIndex - 1));
353cdf0e10cSrcweir }
354cdf0e10cSrcweir 
findFieldColumn(const OUString & rStr,sal_uInt16 * pErr) const355cdf0e10cSrcweir SCCOL ScDBInternalRange::findFieldColumn(const OUString& rStr, sal_uInt16* pErr) const
356cdf0e10cSrcweir {
357cdf0e10cSrcweir     const ScAddress& s = maRange.aStart;
358cdf0e10cSrcweir     const ScAddress& e = maRange.aEnd;
359cdf0e10cSrcweir     OUString aUpper = rStr;
360cdf0e10cSrcweir     lcl_toUpper(aUpper);
361cdf0e10cSrcweir 
362cdf0e10cSrcweir     SCCOL nDBCol1 = s.Col();
363cdf0e10cSrcweir     SCROW nDBRow1 = s.Row();
364cdf0e10cSrcweir     SCTAB nDBTab1 = s.Tab();
365cdf0e10cSrcweir     SCCOL nDBCol2 = e.Col();
366cdf0e10cSrcweir 
367cdf0e10cSrcweir     SCCOL   nField = nDBCol1;
368cdf0e10cSrcweir     sal_Bool    bFound = sal_True;
369cdf0e10cSrcweir 
370cdf0e10cSrcweir     bFound = sal_False;
371cdf0e10cSrcweir     OUString aCellStr;
372cdf0e10cSrcweir     ScAddress aLook( nDBCol1, nDBRow1, nDBTab1 );
373cdf0e10cSrcweir     while (!bFound && (aLook.Col() <= nDBCol2))
374cdf0e10cSrcweir     {
375cdf0e10cSrcweir         sal_uInt16 nErr = getDoc()->GetStringForFormula( aLook, aCellStr );
376cdf0e10cSrcweir         if (pErr)
377cdf0e10cSrcweir             *pErr = nErr;
378cdf0e10cSrcweir         lcl_toUpper(aCellStr);
379cdf0e10cSrcweir         bFound = ScGlobal::GetpTransliteration()->isEqual(aCellStr, aUpper);
380cdf0e10cSrcweir         if (!bFound)
381cdf0e10cSrcweir             aLook.IncCol();
382cdf0e10cSrcweir     }
383cdf0e10cSrcweir     nField = aLook.Col();
384cdf0e10cSrcweir 
385cdf0e10cSrcweir     return bFound ? nField : -1;
386cdf0e10cSrcweir }
387cdf0e10cSrcweir 
createQueryParam(const ScDBRangeBase * pQueryRef) const388cdf0e10cSrcweir ScDBQueryParamBase* ScDBInternalRange::createQueryParam(const ScDBRangeBase* pQueryRef) const
389cdf0e10cSrcweir {
390cdf0e10cSrcweir     auto_ptr<ScDBQueryParamInternal> pParam(new ScDBQueryParamInternal);
391cdf0e10cSrcweir 
392cdf0e10cSrcweir     // Set the database range first.
393cdf0e10cSrcweir     const ScAddress& s = maRange.aStart;
394cdf0e10cSrcweir     const ScAddress& e = maRange.aEnd;
395cdf0e10cSrcweir     pParam->nCol1 = s.Col();
396cdf0e10cSrcweir     pParam->nRow1 = s.Row();
397cdf0e10cSrcweir     pParam->nCol2 = e.Col();
398cdf0e10cSrcweir     pParam->nRow2 = e.Row();
399cdf0e10cSrcweir     pParam->nTab  = s.Tab();
400cdf0e10cSrcweir 
401cdf0e10cSrcweir     fillQueryOptions(pParam.get());
402cdf0e10cSrcweir 
403cdf0e10cSrcweir     // Now construct the query entries from the query range.
404cdf0e10cSrcweir     if (!pQueryRef->fillQueryEntries(pParam.get(), this))
405cdf0e10cSrcweir         return NULL;
406cdf0e10cSrcweir 
407cdf0e10cSrcweir     return pParam.release();
408cdf0e10cSrcweir }
409cdf0e10cSrcweir 
isRangeEqual(const ScRange & rRange) const410cdf0e10cSrcweir bool ScDBInternalRange::isRangeEqual(const ScRange& rRange) const
411cdf0e10cSrcweir {
412cdf0e10cSrcweir     return maRange == rRange;
413cdf0e10cSrcweir }
414cdf0e10cSrcweir 
415cdf0e10cSrcweir // ============================================================================
416cdf0e10cSrcweir 
ScDBExternalRange(ScDocument * pDoc,const ScMatrixRef & pMat)417cdf0e10cSrcweir ScDBExternalRange::ScDBExternalRange(ScDocument* pDoc, const ScMatrixRef& pMat) :
418cdf0e10cSrcweir     ScDBRangeBase(pDoc, EXTERNAL), mpMatrix(pMat)
419cdf0e10cSrcweir {
420cdf0e10cSrcweir     SCSIZE nC, nR;
421cdf0e10cSrcweir     mpMatrix->GetDimensions(nC, nR);
422cdf0e10cSrcweir     mnCols = static_cast<SCCOL>(nC);
423cdf0e10cSrcweir     mnRows = static_cast<SCROW>(nR);
424cdf0e10cSrcweir }
425cdf0e10cSrcweir 
~ScDBExternalRange()426cdf0e10cSrcweir ScDBExternalRange::~ScDBExternalRange()
427cdf0e10cSrcweir {
428cdf0e10cSrcweir }
429cdf0e10cSrcweir 
getColSize() const430cdf0e10cSrcweir SCCOL ScDBExternalRange::getColSize() const
431cdf0e10cSrcweir {
432cdf0e10cSrcweir     return mnCols;
433cdf0e10cSrcweir }
434cdf0e10cSrcweir 
getRowSize() const435cdf0e10cSrcweir SCROW ScDBExternalRange::getRowSize() const
436cdf0e10cSrcweir {
437cdf0e10cSrcweir     return mnRows;
438cdf0e10cSrcweir }
439cdf0e10cSrcweir 
getVisibleDataCellCount() const440cdf0e10cSrcweir SCSIZE ScDBExternalRange::getVisibleDataCellCount() const
441cdf0e10cSrcweir {
442cdf0e10cSrcweir     SCCOL nCols = getColSize();
443cdf0e10cSrcweir     SCROW nRows = getRowSize();
444cdf0e10cSrcweir     if (nRows <= 1)
445cdf0e10cSrcweir         return 0;
446cdf0e10cSrcweir 
447cdf0e10cSrcweir     return (nRows-1)*nCols;
448cdf0e10cSrcweir }
449cdf0e10cSrcweir 
getString(SCCOL nCol,SCROW nRow) const450cdf0e10cSrcweir OUString ScDBExternalRange::getString(SCCOL nCol, SCROW nRow) const
451cdf0e10cSrcweir {
452cdf0e10cSrcweir     if (nCol >= mnCols || nRow >= mnRows)
453cdf0e10cSrcweir         return OUString();
454cdf0e10cSrcweir 
455cdf0e10cSrcweir     return mpMatrix->GetString(nCol, nRow);
456cdf0e10cSrcweir }
457cdf0e10cSrcweir 
getFirstFieldColumn() const458cdf0e10cSrcweir SCCOL ScDBExternalRange::getFirstFieldColumn() const
459cdf0e10cSrcweir {
460cdf0e10cSrcweir     return 0;
461cdf0e10cSrcweir }
462cdf0e10cSrcweir 
findFieldColumn(SCCOL nIndex) const463cdf0e10cSrcweir SCCOL ScDBExternalRange::findFieldColumn(SCCOL nIndex) const
464cdf0e10cSrcweir {
465cdf0e10cSrcweir     if (nIndex < 1)
466cdf0e10cSrcweir         // 1st field
467cdf0e10cSrcweir         return 0;
468cdf0e10cSrcweir 
469cdf0e10cSrcweir     if (nIndex > mnCols)
470cdf0e10cSrcweir         // last field
471cdf0e10cSrcweir         return mnCols - 1;
472cdf0e10cSrcweir 
473cdf0e10cSrcweir     return nIndex - 1;
474cdf0e10cSrcweir }
475cdf0e10cSrcweir 
findFieldColumn(const OUString & rStr,sal_uInt16 * pErr) const476cdf0e10cSrcweir SCCOL ScDBExternalRange::findFieldColumn(const OUString& rStr, sal_uInt16* pErr) const
477cdf0e10cSrcweir {
478cdf0e10cSrcweir     if (pErr)
479cdf0e10cSrcweir         pErr = 0;
480cdf0e10cSrcweir 
481cdf0e10cSrcweir     OUString aUpper = rStr;
482cdf0e10cSrcweir     lcl_toUpper(aUpper);
483cdf0e10cSrcweir     for (SCCOL i = 0; i < mnCols; ++i)
484cdf0e10cSrcweir     {
485cdf0e10cSrcweir         OUString aUpperVal = mpMatrix->GetString(i, 0);
486cdf0e10cSrcweir         lcl_toUpper(aUpperVal);
487cdf0e10cSrcweir         if (aUpper.equals(aUpperVal))
488cdf0e10cSrcweir             return i;
489cdf0e10cSrcweir     }
490cdf0e10cSrcweir     return -1;
491cdf0e10cSrcweir }
492cdf0e10cSrcweir 
createQueryParam(const ScDBRangeBase * pQueryRef) const493cdf0e10cSrcweir ScDBQueryParamBase* ScDBExternalRange::createQueryParam(const ScDBRangeBase* pQueryRef) const
494cdf0e10cSrcweir {
495cdf0e10cSrcweir     auto_ptr<ScDBQueryParamMatrix> pParam(new ScDBQueryParamMatrix);
496cdf0e10cSrcweir     pParam->mpMatrix = mpMatrix;
497cdf0e10cSrcweir     fillQueryOptions(pParam.get());
498cdf0e10cSrcweir 
499cdf0e10cSrcweir     // Now construct the query entries from the query range.
500cdf0e10cSrcweir     if (!pQueryRef->fillQueryEntries(pParam.get(), this))
501cdf0e10cSrcweir         return NULL;
502cdf0e10cSrcweir 
503cdf0e10cSrcweir     return pParam.release();
504cdf0e10cSrcweir }
505cdf0e10cSrcweir 
isRangeEqual(const ScRange &) const506cdf0e10cSrcweir bool ScDBExternalRange::isRangeEqual(const ScRange& /*rRange*/) const
507cdf0e10cSrcweir {
508cdf0e10cSrcweir     return false;
509cdf0e10cSrcweir }
510cdf0e10cSrcweir 
511