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 83 : CellAddress ApiCellRangeList::getBaseAddress() const
97 : {
98 83 : if( empty() )
99 0 : return CellAddress();
100 83 : 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 11 : AddressConverter::AddressConverter( const WorkbookHelper& rHelper ) :
144 : WorkbookHelper( rHelper ),
145 : mbColOverflow( false ),
146 : mbRowOverflow( false ),
147 11 : mbTabOverflow( false )
148 : {
149 11 : maDConChars.set( 0xFFFF, '\x01', 0xFFFF, '\x02', 0xFFFF );
150 11 : switch( getFilterType() )
151 : {
152 : case FILTER_OOXML:
153 11 : initializeMaxPos( OOX_MAXTAB, OOX_MAXCOL, OOX_MAXROW );
154 11 : 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 11 : }
183 :
184 : // ----------------------------------------------------------------------------
185 :
186 859 : bool AddressConverter::parseOoxAddress2d(
187 : sal_Int32& ornColumn, sal_Int32& ornRow,
188 : const OUString& rString, sal_Int32 nStart, sal_Int32 nLength )
189 : {
190 859 : ornColumn = ornRow = 0;
191 859 : if( (nStart < 0) || (nStart >= rString.getLength()) || (nLength < 2) )
192 7 : return false;
193 :
194 852 : const sal_Unicode* pcChar = rString.getStr() + nStart;
195 852 : const sal_Unicode* pcEndChar = pcChar + ::std::min( nLength, rString.getLength() - nStart );
196 :
197 852 : enum { STATE_COL, STATE_ROW } eState = STATE_COL;
198 4637 : while( pcChar < pcEndChar )
199 : {
200 2933 : sal_Unicode cChar = *pcChar;
201 2933 : switch( eState )
202 : {
203 : case STATE_COL:
204 : {
205 1704 : if( ('a' <= cChar) && (cChar <= 'z') )
206 0 : (cChar -= 'a') += 'A';
207 1704 : 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 852 : if( ornColumn >= 12356631 )
212 0 : return false;
213 852 : (ornColumn *= 26) += (cChar - 'A' + 1);
214 : }
215 852 : else if( ornColumn > 0 )
216 : {
217 852 : --pcChar;
218 852 : eState = STATE_ROW;
219 : }
220 : else
221 0 : return false;
222 : }
223 1704 : break;
224 :
225 : case STATE_ROW:
226 : {
227 1229 : if( ('0' <= cChar) && (cChar <= '9') )
228 : {
229 : // return, if 1-based row is already 9 digits long
230 1229 : if( ornRow >= 100000000 )
231 0 : return false;
232 1229 : (ornRow *= 10) += (cChar - '0');
233 : }
234 : else
235 0 : return false;
236 : }
237 1229 : break;
238 : }
239 2933 : ++pcChar;
240 : }
241 :
242 852 : --ornColumn;
243 852 : --ornRow;
244 852 : return (ornColumn >= 0) && (ornRow >= 0);
245 : }
246 :
247 111 : 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 111 : ornStartColumn = ornStartRow = ornEndColumn = ornEndRow = 0;
253 111 : if( (nStart < 0) || (nStart >= rString.getLength()) || (nLength < 2) )
254 33 : return false;
255 :
256 78 : sal_Int32 nEnd = nStart + ::std::min( nLength, rString.getLength() - nStart );
257 78 : sal_Int32 nColonPos = rString.indexOf( ':', nStart );
258 78 : if( (nStart < nColonPos) && (nColonPos + 1 < nEnd) )
259 : {
260 : return
261 44 : parseOoxAddress2d( ornStartColumn, ornStartRow, rString, nStart, nColonPos - nStart ) &&
262 44 : parseOoxAddress2d( ornEndColumn, ornEndRow, rString, nColonPos + 1, nLength - nColonPos - 1 );
263 : }
264 :
265 34 : if( parseOoxAddress2d( ornStartColumn, ornStartRow, rString, nStart, nLength ) )
266 : {
267 34 : ornEndColumn = ornStartColumn;
268 34 : ornEndRow = ornStartRow;
269 34 : return true;
270 : }
271 :
272 0 : return false;
273 : }
274 :
275 : // ----------------------------------------------------------------------------
276 :
277 967 : bool AddressConverter::checkCol( sal_Int32 nCol, bool bTrackOverflow )
278 : {
279 967 : bool bValid = (0 <= nCol) && (nCol <= maMaxPos.Column);
280 967 : if( !bValid && bTrackOverflow )
281 17 : mbColOverflow = true;
282 967 : return bValid;
283 : }
284 :
285 1056 : bool AddressConverter::checkRow( sal_Int32 nRow, bool bTrackOverflow )
286 : {
287 1056 : bool bValid = (0 <= nRow) && (nRow <= maMaxPos.Row);
288 1056 : if( !bValid && bTrackOverflow )
289 0 : mbRowOverflow = true;
290 1056 : return bValid;
291 : }
292 :
293 817 : bool AddressConverter::checkTab( sal_Int16 nSheet, bool bTrackOverflow )
294 : {
295 817 : bool bValid = (0 <= nSheet) && (nSheet <= maMaxPos.Sheet);
296 817 : if( !bValid && bTrackOverflow )
297 0 : mbTabOverflow |= (nSheet > maMaxPos.Sheet); // do not warn for deleted refs (-1)
298 817 : return bValid;
299 : }
300 :
301 : // ----------------------------------------------------------------------------
302 :
303 733 : bool AddressConverter::checkCellAddress( const CellAddress& rAddress, bool bTrackOverflow )
304 : {
305 : return
306 733 : checkTab( rAddress.Sheet, bTrackOverflow ) &&
307 733 : checkCol( rAddress.Column, bTrackOverflow ) &&
308 1466 : checkRow( rAddress.Row, bTrackOverflow );
309 : }
310 :
311 737 : bool AddressConverter::convertToCellAddressUnchecked( CellAddress& orAddress,
312 : const OUString& rString, sal_Int16 nSheet )
313 : {
314 737 : orAddress.Sheet = nSheet;
315 737 : return parseOoxAddress2d( orAddress.Column, orAddress.Row, rString );
316 : }
317 :
318 737 : bool AddressConverter::convertToCellAddress( CellAddress& orAddress,
319 : const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
320 : {
321 : return
322 737 : convertToCellAddressUnchecked( orAddress, rString, nSheet ) &&
323 737 : checkCellAddress( orAddress, bTrackOverflow );
324 : }
325 :
326 46 : CellAddress AddressConverter::createValidCellAddress(
327 : const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
328 : {
329 46 : CellAddress aAddress;
330 46 : if( !convertToCellAddress( aAddress, rString, nSheet, bTrackOverflow ) )
331 : {
332 7 : aAddress.Sheet = getLimitedValue< sal_Int16, sal_Int16 >( nSheet, 0, maMaxPos.Sheet );
333 7 : aAddress.Column = ::std::min( aAddress.Column, maMaxPos.Column );
334 7 : aAddress.Row = ::std::min( aAddress.Row, maMaxPos.Row );
335 : }
336 46 : return aAddress;
337 : }
338 :
339 2 : void AddressConverter::convertToCellAddressUnchecked( CellAddress& orAddress,
340 : const BinAddress& rBinAddress, sal_Int16 nSheet )
341 : {
342 2 : orAddress.Sheet = nSheet;
343 2 : orAddress.Column = rBinAddress.mnCol;
344 2 : orAddress.Row = rBinAddress.mnRow;
345 2 : }
346 :
347 2 : bool AddressConverter::convertToCellAddress( CellAddress& orAddress,
348 : const BinAddress& rBinAddress, sal_Int16 nSheet, bool bTrackOverflow )
349 : {
350 2 : convertToCellAddressUnchecked( orAddress, rBinAddress, nSheet );
351 2 : return checkCellAddress( orAddress, bTrackOverflow );
352 : }
353 :
354 2 : CellAddress AddressConverter::createValidCellAddress(
355 : const BinAddress& rBinAddress, sal_Int16 nSheet, bool bTrackOverflow )
356 : {
357 2 : CellAddress aAddress;
358 2 : 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 2 : return aAddress;
365 : }
366 :
367 : // ----------------------------------------------------------------------------
368 :
369 84 : bool AddressConverter::checkCellRange( const CellRangeAddress& rRange, bool bAllowOverflow, bool bTrackOverflow )
370 : {
371 : return
372 84 : (checkCol( rRange.EndColumn, bTrackOverflow ) || bAllowOverflow) && // bAllowOverflow after checkCol to track overflow!
373 84 : (checkRow( rRange.EndRow, bTrackOverflow ) || bAllowOverflow) && // bAllowOverflow after checkRow to track overflow!
374 84 : checkTab( rRange.Sheet, bTrackOverflow ) &&
375 84 : checkCol( rRange.StartColumn, bTrackOverflow ) &&
376 336 : checkRow( rRange.StartRow, bTrackOverflow );
377 : }
378 :
379 84 : bool AddressConverter::validateCellRange( CellRangeAddress& orRange, bool bAllowOverflow, bool bTrackOverflow )
380 : {
381 84 : if( orRange.StartColumn > orRange.EndColumn )
382 0 : ::std::swap( orRange.StartColumn, orRange.EndColumn );
383 84 : if( orRange.StartRow > orRange.EndRow )
384 0 : ::std::swap( orRange.StartRow, orRange.EndRow );
385 84 : if( !checkCellRange( orRange, bAllowOverflow, bTrackOverflow ) )
386 0 : return false;
387 84 : if( orRange.EndColumn > maMaxPos.Column )
388 0 : orRange.EndColumn = maMaxPos.Column;
389 84 : if( orRange.EndRow > maMaxPos.Row )
390 0 : orRange.EndRow = maMaxPos.Row;
391 84 : return true;
392 : }
393 :
394 111 : bool AddressConverter::convertToCellRangeUnchecked( CellRangeAddress& orRange,
395 : const OUString& rString, sal_Int16 nSheet )
396 : {
397 111 : orRange.Sheet = nSheet;
398 111 : return parseOoxRange2d( orRange.StartColumn, orRange.StartRow, orRange.EndColumn, orRange.EndRow, rString );
399 : }
400 :
401 84 : bool AddressConverter::convertToCellRange( CellRangeAddress& orRange,
402 : const OUString& rString, sal_Int16 nSheet, bool bAllowOverflow, bool bTrackOverflow )
403 : {
404 : return
405 84 : convertToCellRangeUnchecked( orRange, rString, nSheet ) &&
406 84 : 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 49 : void AddressConverter::convertToCellRangeList( ApiCellRangeList& orRanges,
436 : const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
437 : {
438 49 : sal_Int32 nPos = 0;
439 49 : sal_Int32 nLen = rString.getLength();
440 49 : CellRangeAddress aRange;
441 147 : while( (0 <= nPos) && (nPos < nLen) )
442 : {
443 49 : OUString aToken = rString.getToken( 0, ' ', nPos );
444 49 : if( !aToken.isEmpty() && convertToCellRange( aRange, aToken, nSheet, true, bTrackOverflow ) )
445 49 : orRanges.push_back( aRange );
446 49 : }
447 49 : }
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 11 : void AddressConverter::ControlCharacters::set(
461 : sal_Unicode cThisWorkbook, sal_Unicode cExternal,
462 : sal_Unicode cThisSheet, sal_Unicode cInternal, sal_Unicode cSameSheet )
463 : {
464 11 : mcThisWorkbook = cThisWorkbook;
465 11 : mcExternal = cExternal;
466 11 : mcThisSheet = cThisSheet;
467 11 : mcInternal = cInternal;
468 11 : mcSameSheet = cSameSheet;
469 11 : }
470 :
471 11 : void AddressConverter::initializeMaxPos(
472 : sal_Int16 nMaxXlsTab, sal_Int32 nMaxXlsCol, sal_Int32 nMaxXlsRow )
473 : {
474 11 : maMaxXlsPos.Sheet = nMaxXlsTab;
475 11 : maMaxXlsPos.Column = nMaxXlsCol;
476 11 : maMaxXlsPos.Row = nMaxXlsRow;
477 :
478 : // maximum cell position in Calc
479 : try
480 : {
481 11 : Reference< XIndexAccess > xSheetsIA( getDocument()->getSheets(), UNO_QUERY_THROW );
482 11 : Reference< XCellRangeAddressable > xAddressable( xSheetsIA->getByIndex( 0 ), UNO_QUERY_THROW );
483 11 : CellRangeAddress aRange = xAddressable->getRangeAddress();
484 11 : maMaxApiPos = CellAddress( API_MAXTAB, aRange.EndColumn, aRange.EndRow );
485 11 : maMaxPos = getBaseFilter().isImportFilter() ? maMaxApiPos : maMaxXlsPos;
486 : }
487 0 : catch( Exception& )
488 : {
489 : OSL_FAIL( "AddressConverter::AddressConverter - cannot get sheet limits" );
490 : }
491 11 : }
492 :
493 : // ============================================================================
494 :
495 : } // namespace xls
496 9 : } // namespace oox
497 :
498 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|