Line data Source code
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 "addressconverter.hxx"
21 :
22 : #include <com/sun/star/container/XIndexAccess.hpp>
23 : #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
24 : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
25 : #include <osl/diagnose.h>
26 : #include <rtl/strbuf.hxx>
27 : #include <rtl/ustrbuf.hxx>
28 : #include "oox/core/filterbase.hxx"
29 : #include "biffinputstream.hxx"
30 :
31 : namespace oox {
32 : namespace xls {
33 :
34 : // ============================================================================
35 :
36 : using namespace ::com::sun::star::container;
37 : using namespace ::com::sun::star::sheet;
38 : using namespace ::com::sun::star::table;
39 : using namespace ::com::sun::star::uno;
40 :
41 : using ::rtl::OStringBuffer;
42 : using ::rtl::OUString;
43 : using ::rtl::OUStringBuffer;
44 : using ::rtl::OUStringToOString;
45 :
46 : // ============================================================================
47 :
48 : namespace {
49 :
50 : //! TODO: this limit may change, is there a way to obtain it via API?
51 : const sal_Int16 API_MAXTAB = MAXTAB;
52 :
53 : const sal_Int32 OOX_MAXCOL = static_cast< sal_Int32 >( (1 << 14) - 1 );
54 : const sal_Int32 OOX_MAXROW = static_cast< sal_Int32 >( (1 << 20) - 1 );
55 : const sal_Int16 OOX_MAXTAB = static_cast< sal_Int16 >( (1 << 15) - 1 );
56 :
57 : const sal_Int32 BIFF2_MAXCOL = 255;
58 : const sal_Int32 BIFF2_MAXROW = 16383;
59 : const sal_Int16 BIFF2_MAXTAB = 0;
60 :
61 : const sal_Int32 BIFF3_MAXCOL = BIFF2_MAXCOL;
62 : const sal_Int32 BIFF3_MAXROW = BIFF2_MAXROW;
63 : const sal_Int16 BIFF3_MAXTAB = BIFF2_MAXTAB;
64 :
65 : const sal_Int32 BIFF4_MAXCOL = BIFF3_MAXCOL;
66 : const sal_Int32 BIFF4_MAXROW = BIFF3_MAXROW;
67 : const sal_Int16 BIFF4_MAXTAB = 32767;
68 :
69 : const sal_Int32 BIFF5_MAXCOL = BIFF4_MAXCOL;
70 : const sal_Int32 BIFF5_MAXROW = BIFF4_MAXROW;
71 : const sal_Int16 BIFF5_MAXTAB = BIFF4_MAXTAB;
72 :
73 : const sal_Int32 BIFF8_MAXCOL = BIFF5_MAXCOL;
74 : const sal_Int32 BIFF8_MAXROW = 65535;
75 : const sal_Int16 BIFF8_MAXTAB = BIFF5_MAXTAB;
76 :
77 : const sal_Unicode BIFF_URL_DRIVE = '\x01'; /// DOS drive letter or UNC path.
78 : const sal_Unicode BIFF_URL_ROOT = '\x02'; /// Root directory of current drive.
79 : const sal_Unicode BIFF_URL_SUBDIR = '\x03'; /// Subdirectory delimiter.
80 : const sal_Unicode BIFF_URL_PARENT = '\x04'; /// Parent directory.
81 : const sal_Unicode BIFF_URL_RAW = '\x05'; /// Unencoded URL.
82 : const sal_Unicode BIFF_URL_INSTALL = '\x06'; /// Application installation directory.
83 : const sal_Unicode BIFF_URL_INSTALL2 = '\x07'; /// Alternative application installation directory.
84 : const sal_Unicode BIFF_URL_LIBRARY = '\x08'; /// Library directory in application installation.
85 : const sal_Unicode BIFF4_URL_SHEET = '\x09'; /// BIFF4 internal sheet.
86 : const sal_Unicode BIFF_URL_UNC = '@'; /// UNC path root.
87 :
88 : const sal_Unicode BIFF_DCON_ENCODED = '\x01'; /// First character of an encoded path from DCON* records.
89 : const sal_Unicode BIFF_DCON_INTERN = '\x02'; /// First character of an encoded sheet name from DCON* records.
90 :
91 : } // namespace
92 :
93 : // ============================================================================
94 : // ============================================================================
95 :
96 166 : CellAddress ApiCellRangeList::getBaseAddress() const
97 : {
98 166 : if( empty() )
99 0 : return CellAddress();
100 166 : return CellAddress( front().Sheet, front().StartColumn, front().StartRow );
101 : }
102 :
103 : // ============================================================================
104 :
105 0 : void BinAddress::read( SequenceInputStream& rStrm )
106 : {
107 0 : rStrm >> mnRow >> mnCol;
108 0 : }
109 :
110 0 : void BinAddress::read( BiffInputStream& rStrm, bool bCol16Bit, bool bRow32Bit )
111 : {
112 0 : mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16();
113 0 : mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8();
114 0 : }
115 :
116 : // ============================================================================
117 :
118 0 : void BinRange::read( SequenceInputStream& rStrm )
119 : {
120 0 : rStrm >> maFirst.mnRow >> maLast.mnRow >> maFirst.mnCol >> maLast.mnCol;
121 0 : }
122 :
123 0 : void BinRange::read( BiffInputStream& rStrm, bool bCol16Bit, bool bRow32Bit )
124 : {
125 0 : maFirst.mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16();
126 0 : maLast.mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16();
127 0 : maFirst.mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8();
128 0 : maLast.mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8();
129 0 : }
130 :
131 : // ============================================================================
132 :
133 0 : void BinRangeList::read( SequenceInputStream& rStrm )
134 : {
135 0 : sal_Int32 nCount = rStrm.readInt32();
136 0 : resize( getLimitedValue< size_t, sal_Int64 >( nCount, 0, rStrm.getRemaining() / 16 ) );
137 0 : for( iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
138 0 : aIt->read( rStrm );
139 0 : }
140 :
141 : // ============================================================================
142 :
143 22 : AddressConverter::AddressConverter( const WorkbookHelper& rHelper ) :
144 : WorkbookHelper( rHelper ),
145 : mbColOverflow( false ),
146 : mbRowOverflow( false ),
147 22 : mbTabOverflow( false )
148 : {
149 22 : maDConChars.set( 0xFFFF, '\x01', 0xFFFF, '\x02', 0xFFFF );
150 22 : switch( getFilterType() )
151 : {
152 : case FILTER_OOXML:
153 22 : initializeMaxPos( OOX_MAXTAB, OOX_MAXCOL, OOX_MAXROW );
154 22 : break;
155 0 : case FILTER_BIFF: switch( getBiff() )
156 : {
157 : case BIFF2:
158 0 : initializeMaxPos( BIFF2_MAXTAB, BIFF2_MAXCOL, BIFF2_MAXROW );
159 0 : maLinkChars.set( 0xFFFF, '\x01', '\x02', 0xFFFF, 0xFFFF );
160 0 : break;
161 : case BIFF3:
162 0 : initializeMaxPos( BIFF3_MAXTAB, BIFF3_MAXCOL, BIFF3_MAXROW );
163 0 : maLinkChars.set( 0xFFFF, '\x01', '\x02', 0xFFFF, 0xFFFF );
164 0 : break;
165 : case BIFF4:
166 0 : initializeMaxPos( BIFF4_MAXTAB, BIFF4_MAXCOL, BIFF4_MAXROW );
167 0 : maLinkChars.set( 0xFFFF, '\x01', '\x02', 0xFFFF, '\x00' );
168 0 : break;
169 : case BIFF5:
170 0 : initializeMaxPos( BIFF5_MAXTAB, BIFF5_MAXCOL, BIFF5_MAXROW );
171 0 : maLinkChars.set( '\x04', '\x01', '\x02', '\x03', '\x00' );
172 0 : break;
173 : case BIFF8:
174 0 : initializeMaxPos( BIFF8_MAXTAB, BIFF8_MAXCOL, BIFF8_MAXROW );
175 0 : maLinkChars.set( '\x04', '\x01', 0xFFFF, '\x02', '\x00' );
176 0 : break;
177 0 : case BIFF_UNKNOWN: break;
178 : }
179 0 : break;
180 0 : case FILTER_UNKNOWN: break;
181 : }
182 22 : }
183 :
184 : // ----------------------------------------------------------------------------
185 :
186 1718 : bool AddressConverter::parseOoxAddress2d(
187 : sal_Int32& ornColumn, sal_Int32& ornRow,
188 : const OUString& rString, sal_Int32 nStart, sal_Int32 nLength )
189 : {
190 1718 : ornColumn = ornRow = 0;
191 1718 : if( (nStart < 0) || (nStart >= rString.getLength()) || (nLength < 2) )
192 14 : return false;
193 :
194 1704 : const sal_Unicode* pcChar = rString.getStr() + nStart;
195 1704 : const sal_Unicode* pcEndChar = pcChar + ::std::min( nLength, rString.getLength() - nStart );
196 :
197 1704 : enum { STATE_COL, STATE_ROW } eState = STATE_COL;
198 9274 : while( pcChar < pcEndChar )
199 : {
200 5866 : sal_Unicode cChar = *pcChar;
201 5866 : switch( eState )
202 : {
203 : case STATE_COL:
204 : {
205 3408 : if( ('a' <= cChar) && (cChar <= 'z') )
206 0 : (cChar -= 'a') += 'A';
207 3408 : if( ('A' <= cChar) && (cChar <= 'Z') )
208 : {
209 : /* Return, if 1-based column index is already 6 characters
210 : long (12356631 is column index for column AAAAAA). */
211 1704 : if( ornColumn >= 12356631 )
212 0 : return false;
213 1704 : (ornColumn *= 26) += (cChar - 'A' + 1);
214 : }
215 1704 : else if( ornColumn > 0 )
216 : {
217 1704 : --pcChar;
218 1704 : eState = STATE_ROW;
219 : }
220 : else
221 0 : return false;
222 : }
223 3408 : break;
224 :
225 : case STATE_ROW:
226 : {
227 2458 : if( ('0' <= cChar) && (cChar <= '9') )
228 : {
229 : // return, if 1-based row is already 9 digits long
230 2458 : if( ornRow >= 100000000 )
231 0 : return false;
232 2458 : (ornRow *= 10) += (cChar - '0');
233 : }
234 : else
235 0 : return false;
236 : }
237 2458 : break;
238 : }
239 5866 : ++pcChar;
240 : }
241 :
242 1704 : --ornColumn;
243 1704 : --ornRow;
244 1704 : return (ornColumn >= 0) && (ornRow >= 0);
245 : }
246 :
247 222 : bool AddressConverter::parseOoxRange2d(
248 : sal_Int32& ornStartColumn, sal_Int32& ornStartRow,
249 : sal_Int32& ornEndColumn, sal_Int32& ornEndRow,
250 : const OUString& rString, sal_Int32 nStart, sal_Int32 nLength )
251 : {
252 222 : ornStartColumn = ornStartRow = ornEndColumn = ornEndRow = 0;
253 222 : if( (nStart < 0) || (nStart >= rString.getLength()) || (nLength < 2) )
254 66 : return false;
255 :
256 156 : sal_Int32 nEnd = nStart + ::std::min( nLength, rString.getLength() - nStart );
257 156 : sal_Int32 nColonPos = rString.indexOf( ':', nStart );
258 156 : if( (nStart < nColonPos) && (nColonPos + 1 < nEnd) )
259 : {
260 : return
261 88 : parseOoxAddress2d( ornStartColumn, ornStartRow, rString, nStart, nColonPos - nStart ) &&
262 88 : parseOoxAddress2d( ornEndColumn, ornEndRow, rString, nColonPos + 1, nLength - nColonPos - 1 );
263 : }
264 :
265 68 : if( parseOoxAddress2d( ornStartColumn, ornStartRow, rString, nStart, nLength ) )
266 : {
267 68 : ornEndColumn = ornStartColumn;
268 68 : ornEndRow = ornStartRow;
269 68 : return true;
270 : }
271 :
272 0 : return false;
273 : }
274 :
275 : // ----------------------------------------------------------------------------
276 :
277 1934 : bool AddressConverter::checkCol( sal_Int32 nCol, bool bTrackOverflow )
278 : {
279 1934 : bool bValid = (0 <= nCol) && (nCol <= maMaxPos.Column);
280 1934 : if( !bValid && bTrackOverflow )
281 34 : mbColOverflow = true;
282 1934 : return bValid;
283 : }
284 :
285 2112 : bool AddressConverter::checkRow( sal_Int32 nRow, bool bTrackOverflow )
286 : {
287 2112 : bool bValid = (0 <= nRow) && (nRow <= maMaxPos.Row);
288 2112 : if( !bValid && bTrackOverflow )
289 0 : mbRowOverflow = true;
290 2112 : return bValid;
291 : }
292 :
293 1634 : bool AddressConverter::checkTab( sal_Int16 nSheet, bool bTrackOverflow )
294 : {
295 1634 : bool bValid = (0 <= nSheet) && (nSheet <= maMaxPos.Sheet);
296 1634 : if( !bValid && bTrackOverflow )
297 0 : mbTabOverflow |= (nSheet > maMaxPos.Sheet); // do not warn for deleted refs (-1)
298 1634 : return bValid;
299 : }
300 :
301 : // ----------------------------------------------------------------------------
302 :
303 1466 : bool AddressConverter::checkCellAddress( const CellAddress& rAddress, bool bTrackOverflow )
304 : {
305 : return
306 1466 : checkTab( rAddress.Sheet, bTrackOverflow ) &&
307 1466 : checkCol( rAddress.Column, bTrackOverflow ) &&
308 2932 : checkRow( rAddress.Row, bTrackOverflow );
309 : }
310 :
311 1474 : bool AddressConverter::convertToCellAddressUnchecked( CellAddress& orAddress,
312 : const OUString& rString, sal_Int16 nSheet )
313 : {
314 1474 : orAddress.Sheet = nSheet;
315 1474 : return parseOoxAddress2d( orAddress.Column, orAddress.Row, rString );
316 : }
317 :
318 1474 : bool AddressConverter::convertToCellAddress( CellAddress& orAddress,
319 : const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
320 : {
321 : return
322 1474 : convertToCellAddressUnchecked( orAddress, rString, nSheet ) &&
323 1474 : checkCellAddress( orAddress, bTrackOverflow );
324 : }
325 :
326 92 : CellAddress AddressConverter::createValidCellAddress(
327 : const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
328 : {
329 92 : CellAddress aAddress;
330 92 : if( !convertToCellAddress( aAddress, rString, nSheet, bTrackOverflow ) )
331 : {
332 14 : aAddress.Sheet = getLimitedValue< sal_Int16, sal_Int16 >( nSheet, 0, maMaxPos.Sheet );
333 14 : aAddress.Column = ::std::min( aAddress.Column, maMaxPos.Column );
334 14 : aAddress.Row = ::std::min( aAddress.Row, maMaxPos.Row );
335 : }
336 92 : return aAddress;
337 : }
338 :
339 4 : void AddressConverter::convertToCellAddressUnchecked( CellAddress& orAddress,
340 : const BinAddress& rBinAddress, sal_Int16 nSheet )
341 : {
342 4 : orAddress.Sheet = nSheet;
343 4 : orAddress.Column = rBinAddress.mnCol;
344 4 : orAddress.Row = rBinAddress.mnRow;
345 4 : }
346 :
347 4 : bool AddressConverter::convertToCellAddress( CellAddress& orAddress,
348 : const BinAddress& rBinAddress, sal_Int16 nSheet, bool bTrackOverflow )
349 : {
350 4 : convertToCellAddressUnchecked( orAddress, rBinAddress, nSheet );
351 4 : return checkCellAddress( orAddress, bTrackOverflow );
352 : }
353 :
354 4 : CellAddress AddressConverter::createValidCellAddress(
355 : const BinAddress& rBinAddress, sal_Int16 nSheet, bool bTrackOverflow )
356 : {
357 4 : CellAddress aAddress;
358 4 : if( !convertToCellAddress( aAddress, rBinAddress, nSheet, bTrackOverflow ) )
359 : {
360 0 : aAddress.Sheet = getLimitedValue< sal_Int16, sal_Int16 >( nSheet, 0, maMaxPos.Sheet );
361 0 : aAddress.Column = getLimitedValue< sal_Int32, sal_Int32 >( rBinAddress.mnCol, 0, maMaxPos.Column );
362 0 : aAddress.Row = getLimitedValue< sal_Int32, sal_Int32 >( rBinAddress.mnRow, 0, maMaxPos.Row );
363 : }
364 4 : return aAddress;
365 : }
366 :
367 : // ----------------------------------------------------------------------------
368 :
369 168 : bool AddressConverter::checkCellRange( const CellRangeAddress& rRange, bool bAllowOverflow, bool bTrackOverflow )
370 : {
371 : return
372 168 : (checkCol( rRange.EndColumn, bTrackOverflow ) || bAllowOverflow) && // bAllowOverflow after checkCol to track overflow!
373 168 : (checkRow( rRange.EndRow, bTrackOverflow ) || bAllowOverflow) && // bAllowOverflow after checkRow to track overflow!
374 168 : checkTab( rRange.Sheet, bTrackOverflow ) &&
375 168 : checkCol( rRange.StartColumn, bTrackOverflow ) &&
376 672 : checkRow( rRange.StartRow, bTrackOverflow );
377 : }
378 :
379 168 : bool AddressConverter::validateCellRange( CellRangeAddress& orRange, bool bAllowOverflow, bool bTrackOverflow )
380 : {
381 168 : if( orRange.StartColumn > orRange.EndColumn )
382 0 : ::std::swap( orRange.StartColumn, orRange.EndColumn );
383 168 : if( orRange.StartRow > orRange.EndRow )
384 0 : ::std::swap( orRange.StartRow, orRange.EndRow );
385 168 : if( !checkCellRange( orRange, bAllowOverflow, bTrackOverflow ) )
386 0 : return false;
387 168 : if( orRange.EndColumn > maMaxPos.Column )
388 0 : orRange.EndColumn = maMaxPos.Column;
389 168 : if( orRange.EndRow > maMaxPos.Row )
390 0 : orRange.EndRow = maMaxPos.Row;
391 168 : return true;
392 : }
393 :
394 222 : bool AddressConverter::convertToCellRangeUnchecked( CellRangeAddress& orRange,
395 : const OUString& rString, sal_Int16 nSheet )
396 : {
397 222 : orRange.Sheet = nSheet;
398 222 : return parseOoxRange2d( orRange.StartColumn, orRange.StartRow, orRange.EndColumn, orRange.EndRow, rString );
399 : }
400 :
401 168 : bool AddressConverter::convertToCellRange( CellRangeAddress& orRange,
402 : const OUString& rString, sal_Int16 nSheet, bool bAllowOverflow, bool bTrackOverflow )
403 : {
404 : return
405 168 : convertToCellRangeUnchecked( orRange, rString, nSheet ) &&
406 168 : validateCellRange( orRange, bAllowOverflow, bTrackOverflow );
407 : }
408 :
409 0 : void AddressConverter::convertToCellRangeUnchecked( CellRangeAddress& orRange,
410 : const BinRange& rBinRange, sal_Int16 nSheet )
411 : {
412 0 : orRange.Sheet = nSheet;
413 0 : orRange.StartColumn = rBinRange.maFirst.mnCol;
414 0 : orRange.StartRow = rBinRange.maFirst.mnRow;
415 0 : orRange.EndColumn = rBinRange.maLast.mnCol;
416 0 : orRange.EndRow = rBinRange.maLast.mnRow;
417 0 : }
418 :
419 0 : bool AddressConverter::convertToCellRange( CellRangeAddress& orRange,
420 : const BinRange& rBinRange, sal_Int16 nSheet, bool bAllowOverflow, bool bTrackOverflow )
421 : {
422 0 : convertToCellRangeUnchecked( orRange, rBinRange, nSheet );
423 0 : return validateCellRange( orRange, bAllowOverflow, bTrackOverflow );
424 : }
425 :
426 : // ----------------------------------------------------------------------------
427 :
428 0 : void AddressConverter::validateCellRangeList( ApiCellRangeList& orRanges, bool bTrackOverflow )
429 : {
430 0 : for( size_t nIndex = orRanges.size(); nIndex > 0; --nIndex )
431 0 : if( !validateCellRange( orRanges[ nIndex - 1 ], true, bTrackOverflow ) )
432 0 : orRanges.erase( orRanges.begin() + nIndex - 1 );
433 0 : }
434 :
435 98 : void AddressConverter::convertToCellRangeList( ApiCellRangeList& orRanges,
436 : const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
437 : {
438 98 : sal_Int32 nPos = 0;
439 98 : sal_Int32 nLen = rString.getLength();
440 98 : CellRangeAddress aRange;
441 294 : while( (0 <= nPos) && (nPos < nLen) )
442 : {
443 98 : OUString aToken = rString.getToken( 0, ' ', nPos );
444 98 : if( !aToken.isEmpty() && convertToCellRange( aRange, aToken, nSheet, true, bTrackOverflow ) )
445 98 : orRanges.push_back( aRange );
446 98 : }
447 98 : }
448 :
449 0 : void AddressConverter::convertToCellRangeList( ApiCellRangeList& orRanges,
450 : const BinRangeList& rBinRanges, sal_Int16 nSheet, bool bTrackOverflow )
451 : {
452 0 : CellRangeAddress aRange;
453 0 : for( BinRangeList::const_iterator aIt = rBinRanges.begin(), aEnd = rBinRanges.end(); aIt != aEnd; ++aIt )
454 0 : if( convertToCellRange( aRange, *aIt, nSheet, true, bTrackOverflow ) )
455 0 : orRanges.push_back( aRange );
456 0 : }
457 :
458 : // private --------------------------------------------------------------------
459 :
460 22 : void AddressConverter::ControlCharacters::set(
461 : sal_Unicode cThisWorkbook, sal_Unicode cExternal,
462 : sal_Unicode cThisSheet, sal_Unicode cInternal, sal_Unicode cSameSheet )
463 : {
464 22 : mcThisWorkbook = cThisWorkbook;
465 22 : mcExternal = cExternal;
466 22 : mcThisSheet = cThisSheet;
467 22 : mcInternal = cInternal;
468 22 : mcSameSheet = cSameSheet;
469 22 : }
470 :
471 22 : void AddressConverter::initializeMaxPos(
472 : sal_Int16 nMaxXlsTab, sal_Int32 nMaxXlsCol, sal_Int32 nMaxXlsRow )
473 : {
474 22 : maMaxXlsPos.Sheet = nMaxXlsTab;
475 22 : maMaxXlsPos.Column = nMaxXlsCol;
476 22 : maMaxXlsPos.Row = nMaxXlsRow;
477 :
478 : // maximum cell position in Calc
479 : try
480 : {
481 22 : Reference< XIndexAccess > xSheetsIA( getDocument()->getSheets(), UNO_QUERY_THROW );
482 22 : Reference< XCellRangeAddressable > xAddressable( xSheetsIA->getByIndex( 0 ), UNO_QUERY_THROW );
483 22 : CellRangeAddress aRange = xAddressable->getRangeAddress();
484 22 : maMaxApiPos = CellAddress( API_MAXTAB, aRange.EndColumn, aRange.EndRow );
485 22 : maMaxPos = getBaseFilter().isImportFilter() ? maMaxApiPos : maMaxXlsPos;
486 : }
487 0 : catch( Exception& )
488 : {
489 : OSL_FAIL( "AddressConverter::AddressConverter - cannot get sheet limits" );
490 : }
491 22 : }
492 :
493 : // ============================================================================
494 :
495 : } // namespace xls
496 24 : } // namespace oox
497 :
498 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|