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