merge the formfield patch from ooo-build
[ooovba.git] / oox / source / xls / defnamesbuffer.cxx
blobb2c724b6728d10100289c57e0efc2d4cf1ab342d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: defnamesbuffer.cxx,v $
10 * $Revision: 1.5.4.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/xls/defnamesbuffer.hxx"
32 #include <rtl/ustrbuf.hxx>
33 #include <com/sun/star/sheet/ComplexReference.hpp>
34 #include <com/sun/star/sheet/ExternalReference.hpp>
35 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
36 #include <com/sun/star/sheet/ReferenceFlags.hpp>
37 #include <com/sun/star/sheet/SingleReference.hpp>
38 #include <com/sun/star/sheet/XFormulaTokens.hpp>
39 #include <com/sun/star/sheet/XPrintAreas.hpp>
40 #include "properties.hxx"
41 #include "oox/helper/attributelist.hxx"
42 #include "oox/helper/propertyset.hxx"
43 #include "oox/xls/addressconverter.hxx"
44 #include "oox/xls/biffinputstream.hxx"
45 #include "oox/xls/externallinkbuffer.hxx"
46 #include "oox/xls/formulaparser.hxx"
47 #include "oox/xls/worksheetbuffer.hxx"
49 using ::rtl::OUString;
50 using ::rtl::OUStringBuffer;
51 using ::com::sun::star::uno::Any;
52 using ::com::sun::star::uno::Reference;
53 using ::com::sun::star::uno::UNO_QUERY;
54 using ::com::sun::star::table::CellAddress;
55 using ::com::sun::star::table::CellRangeAddress;
56 using ::com::sun::star::sheet::ComplexReference;
57 using ::com::sun::star::sheet::ExternalReference;
58 using ::com::sun::star::sheet::SingleReference;
59 using ::com::sun::star::sheet::XFormulaTokens;
60 using ::com::sun::star::sheet::XPrintAreas;
62 namespace oox {
63 namespace xls {
65 // ============================================================================
67 namespace {
69 const sal_uInt32 OOBIN_DEFNAME_HIDDEN = 0x00000001;
70 const sal_uInt32 OOBIN_DEFNAME_FUNC = 0x00000002;
71 const sal_uInt32 OOBIN_DEFNAME_VBNAME = 0x00000004;
72 const sal_uInt32 OOBIN_DEFNAME_MACRO = 0x00000008;
73 const sal_uInt32 OOBIN_DEFNAME_CALCEXP = 0x00000010;
74 const sal_uInt32 OOBIN_DEFNAME_BUILTIN = 0x00000020;
75 const sal_uInt32 OOBIN_DEFNAME_PUBLISHED = 0x00008000;
76 const sal_uInt32 OOBIN_DEFNAME_WBPARAM = 0x00010000;
78 const sal_uInt16 BIFF_DEFNAME_HIDDEN = 0x0001;
79 const sal_uInt16 BIFF_DEFNAME_FUNC = 0x0002;
80 const sal_uInt16 BIFF_DEFNAME_VBNAME = 0x0004;
81 const sal_uInt16 BIFF_DEFNAME_MACRO = 0x0008;
82 const sal_uInt16 BIFF_DEFNAME_CALCEXP = 0x0010;
83 const sal_uInt16 BIFF_DEFNAME_BUILTIN = 0x0020;
84 const sal_uInt16 BIFF_DEFNAME_BIG = 0x1000;
86 const sal_uInt8 BIFF2_DEFNAME_FUNC = 0x02; /// BIFF2 function/command flag.
88 const sal_uInt16 BIFF_DEFNAME_GLOBAL = 0; /// 0 = Globally defined name.
90 // ----------------------------------------------------------------------------
92 const sal_Char* const spcLegacyPrefix = "Excel_BuiltIn_";
93 const sal_Char* const spcOoxPrefix = "_xlnm.";
95 const sal_Char* const sppcBaseNames[] =
97 "Consolidate_Area", /* OOX */
98 "Auto_Open",
99 "Auto_Close",
100 "Extract", /* OOX */
101 "Database", /* OOX */
102 "Criteria", /* OOX */
103 "Print_Area", /* OOX */
104 "Print_Titles", /* OOX */
105 "Recorder",
106 "Data_Form",
107 "Auto_Activate",
108 "Auto_Deactivate",
109 "Sheet_Title", /* OOX */
110 "_FilterDatabase" /* OOX */
113 /** Localized names for _xlnm._FilterDatabase as used in BIFF5. */
114 const sal_Char* const sppcFilterDbNames[] =
116 "_FilterDatabase", // English
117 "_FilterDatenbank" // German
120 OUString lclGetBaseName( sal_Unicode cBuiltinId )
122 OSL_ENSURE( cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ), "lclGetBaseName - unknown builtin name" );
123 OUStringBuffer aBuffer;
124 if( cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ) )
125 aBuffer.appendAscii( sppcBaseNames[ cBuiltinId ] );
126 else
127 aBuffer.append( static_cast< sal_Int32 >( cBuiltinId ) );
128 return aBuffer.makeStringAndClear();
131 OUString lclGetBuiltinName( sal_Unicode cBuiltinId )
133 return OUStringBuffer().appendAscii( spcOoxPrefix ).append( lclGetBaseName( cBuiltinId ) ).makeStringAndClear();
136 sal_Unicode lclGetBuiltinIdFromOox( const OUString& rOoxName )
138 OUString aPrefix = OUString::createFromAscii( spcOoxPrefix );
139 sal_Int32 nPrefixLen = aPrefix.getLength();
140 if( rOoxName.matchIgnoreAsciiCase( aPrefix ) )
142 for( sal_Unicode cBuiltinId = 0; cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ); ++cBuiltinId )
144 OUString aBaseName = lclGetBaseName( cBuiltinId );
145 sal_Int32 nBaseNameLen = aBaseName.getLength();
146 if( (rOoxName.getLength() == nPrefixLen + nBaseNameLen) && rOoxName.matchIgnoreAsciiCase( aBaseName, nPrefixLen ) )
147 return cBuiltinId;
150 return OOX_DEFNAME_UNKNOWN;
153 sal_Unicode lclGetBuiltinIdFromOob( const OUString& rOobName )
155 for( sal_Unicode cBuiltinId = 0; cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ); ++cBuiltinId )
156 if( rOobName.equalsIgnoreAsciiCaseAscii( sppcBaseNames[ cBuiltinId ] ) )
157 return cBuiltinId;
158 return OOX_DEFNAME_UNKNOWN;
161 bool lclIsFilterDatabaseName( const OUString& rName )
163 for( const sal_Char* const* ppcName = sppcFilterDbNames; ppcName < STATIC_ARRAY_END( sppcFilterDbNames ); ++ppcName )
164 if( rName.equalsIgnoreAsciiCaseAscii( *ppcName ) )
165 return true;
166 return false;
169 } // namespace
171 // ============================================================================
173 DefinedNameModel::DefinedNameModel() :
174 mnSheet( -1 ),
175 mnFuncGroupId( -1 ),
176 mbMacro( false ),
177 mbFunction( false ),
178 mbVBName( false ),
179 mbHidden( false )
183 // ============================================================================
185 namespace {
187 const sal_uInt16 BIFF_REFFLAG_COL1REL = 0x0001;
188 const sal_uInt16 BIFF_REFFLAG_ROW1REL = 0x0002;
189 const sal_uInt16 BIFF_REFFLAG_COL2REL = 0x0004;
190 const sal_uInt16 BIFF_REFFLAG_ROW2REL = 0x0008;
192 void lclConvertRefFlags( sal_Int32& ornFlags, sal_Int32& ornAbsPos, sal_Int32& ornRelPos, sal_Int32 nBasePos, sal_Int32 nApiRelFlag, bool bRel )
194 if( getFlag( ornFlags, nApiRelFlag ) && !bRel )
196 // convert relative to absolute
197 setFlag( ornFlags, nApiRelFlag, false );
198 ornAbsPos = nBasePos + ornRelPos;
200 else if( !getFlag( ornFlags, nApiRelFlag ) && bRel )
202 // convert absolute to relative
203 setFlag( ornFlags, nApiRelFlag, true );
204 ornRelPos = ornAbsPos - nBasePos;
208 void lclConvertSingleRefFlags( SingleReference& orApiRef, const CellAddress& rBaseAddress, bool bColRel, bool bRowRel )
210 using namespace ::com::sun::star::sheet::ReferenceFlags;
211 lclConvertRefFlags(
212 orApiRef.Flags, orApiRef.Column, orApiRef.RelativeColumn,
213 rBaseAddress.Column, COLUMN_RELATIVE, bColRel );
214 lclConvertRefFlags(
215 orApiRef.Flags, orApiRef.Row, orApiRef.RelativeRow,
216 rBaseAddress.Row, ROW_RELATIVE, bRowRel );
219 Any lclConvertReference( const Any& rRefAny, const CellAddress& rBaseAddress, sal_uInt16 nRelFlags )
221 if( rRefAny.has< SingleReference >() && !getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ) && !getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) )
223 SingleReference aApiRef;
224 rRefAny >>= aApiRef;
225 lclConvertSingleRefFlags( aApiRef, rBaseAddress, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) );
226 return Any( aApiRef );
228 if( rRefAny.has< ComplexReference >() )
230 ComplexReference aApiRef;
231 rRefAny >>= aApiRef;
232 lclConvertSingleRefFlags( aApiRef.Reference1, rBaseAddress, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) );
233 lclConvertSingleRefFlags( aApiRef.Reference2, rBaseAddress, getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) );
234 return Any( aApiRef );
236 return Any();
239 } // namespace
241 // ----------------------------------------------------------------------------
243 DefinedNameBase::DefinedNameBase( const WorkbookHelper& rHelper ) :
244 WorkbookHelper( rHelper )
248 const OUString& DefinedNameBase::getUpcaseModelName() const
250 if( maUpModelName.getLength() == 0 )
251 maUpModelName = maModel.maName.toAsciiUpperCase();
252 return maUpModelName;
255 Any DefinedNameBase::getReference( const CellAddress& rBaseAddress ) const
257 if( maRefAny.hasValue() && (maModel.maName.getLength() >= 2) && (maModel.maName[ 0 ] == '\x01') )
259 sal_Unicode cFlagsChar = getUpcaseModelName()[ 1 ];
260 if( ('A' <= cFlagsChar) && (cFlagsChar <= 'P') )
262 sal_uInt16 nRelFlags = static_cast< sal_uInt16 >( cFlagsChar - 'A' );
263 if( maRefAny.has< ExternalReference >() )
265 ExternalReference aApiExtRef;
266 maRefAny >>= aApiExtRef;
267 Any aRefAny = lclConvertReference( aApiExtRef.Reference, rBaseAddress, nRelFlags );
268 if( aRefAny.hasValue() )
270 aApiExtRef.Reference <<= aRefAny;
271 return Any( aApiExtRef );
274 else
276 return lclConvertReference( maRefAny, rBaseAddress, nRelFlags );
280 return Any();
283 void DefinedNameBase::importOoxFormula( FormulaContext& rContext, sal_Int16 nBaseSheet )
285 if( maModel.maFormula.getLength() > 0 )
287 rContext.setBaseAddress( CellAddress( nBaseSheet, 0, 0 ) );
288 getFormulaParser().importFormula( rContext, maModel.maFormula );
290 else
291 getFormulaParser().convertErrorToFormula( rContext, BIFF_ERR_NAME );
294 void DefinedNameBase::importOobFormula( FormulaContext& rContext, sal_Int16 nBaseSheet, RecordInputStream& rStrm )
296 rContext.setBaseAddress( CellAddress( nBaseSheet, 0, 0 ) );
297 getFormulaParser().importFormula( rContext, rStrm );
300 void DefinedNameBase::importBiffFormula( FormulaContext& rContext, sal_Int16 nBaseSheet, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize )
302 rContext.setBaseAddress( CellAddress( nBaseSheet, 0, 0 ) );
303 if( !pnFmlaSize || (*pnFmlaSize > 0) )
304 getFormulaParser().importFormula( rContext, rStrm, pnFmlaSize );
305 else
306 getFormulaParser().convertErrorToFormula( rContext, BIFF_ERR_NAME );
309 void DefinedNameBase::extractReference( const ApiTokenSequence& rTokens )
311 OSL_ENSURE( (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4), "DefinedNameBase::extractReference - unexpected call" );
312 maRefAny = getFormulaParser().extractReference( rTokens );
315 // ============================================================================
317 DefinedName::DefinedName( const WorkbookHelper& rHelper ) :
318 DefinedNameBase( rHelper ),
319 mnTokenIndex( -1 ),
320 mcBuiltinId( OOX_DEFNAME_UNKNOWN ),
321 mnFmlaSize( 0 )
325 void DefinedName::importDefinedName( const AttributeList& rAttribs )
327 maModel.maName = rAttribs.getXString( XML_name, OUString() );
328 maModel.mnSheet = rAttribs.getInteger( XML_localSheetId, -1 );
329 maModel.mnFuncGroupId = rAttribs.getInteger( XML_functionGroupId, -1 );
330 maModel.mbMacro = rAttribs.getBool( XML_xlm, false );
331 maModel.mbFunction = rAttribs.getBool( XML_function, false );
332 maModel.mbVBName = rAttribs.getBool( XML_vbProcedure, false );
333 maModel.mbHidden = rAttribs.getBool( XML_hidden, false );
334 mcBuiltinId = lclGetBuiltinIdFromOox( maModel.maName );
335 mnCalcSheet = (maModel.mnSheet >= 0) ? getWorksheets().getCalcSheetIndex( maModel.mnSheet ) : -1;
338 void DefinedName::setFormula( const OUString& rFormula )
340 maModel.maFormula = rFormula;
343 void DefinedName::importDefinedName( RecordInputStream& rStrm )
345 sal_uInt32 nFlags;
346 rStrm >> nFlags;
347 rStrm.skip( 1 ); // keyboard shortcut
348 rStrm >> maModel.mnSheet >> maModel.maName;
349 mnCalcSheet = (maModel.mnSheet >= 0) ? getWorksheets().getCalcSheetIndex( maModel.mnSheet ) : -1;
351 // macro function/command, hidden flag
352 maModel.mnFuncGroupId = extractValue< sal_Int32 >( nFlags, 6, 9 );
353 maModel.mbMacro = getFlag( nFlags, OOBIN_DEFNAME_MACRO );
354 maModel.mbFunction = getFlag( nFlags, OOBIN_DEFNAME_FUNC );
355 maModel.mbVBName = getFlag( nFlags, OOBIN_DEFNAME_VBNAME );
356 maModel.mbHidden = getFlag( nFlags, OOBIN_DEFNAME_HIDDEN );
358 // get builtin name index from name
359 if( getFlag( nFlags, OOBIN_DEFNAME_BUILTIN ) )
360 mcBuiltinId = lclGetBuiltinIdFromOob( maModel.maName );
361 // unhide built-in names (_xlnm._FilterDatabase is always hidden)
362 if( isBuiltinName() )
363 maModel.mbHidden = false;
365 // store token array data
366 sal_Int64 nRecPos = rStrm.tell();
367 sal_Int32 nFmlaSize = rStrm.readInt32();
368 rStrm.skip( nFmlaSize );
369 sal_Int32 nAddDataSize = rStrm.readInt32();
370 if( !rStrm.isEof() && (nFmlaSize > 0) && (nAddDataSize >= 0) && (rStrm.getRemaining() >= nAddDataSize) )
372 sal_Int32 nTotalSize = 8 + nFmlaSize + nAddDataSize;
373 mxFormula.reset( new StreamDataSequence );
374 rStrm.seek( nRecPos );
375 rStrm.readData( *mxFormula, nTotalSize );
379 void DefinedName::importDefinedName( BiffInputStream& rStrm, sal_Int16 nCalcSheet )
381 BiffType eBiff = getBiff();
382 sal_uInt16 nFlags = 0;
383 sal_Int16 nRefId = BIFF_DEFNAME_GLOBAL;
384 sal_Int16 nTabId = BIFF_DEFNAME_GLOBAL;
385 sal_uInt8 nNameLen = 0, nShortCut = 0;
387 switch( eBiff )
389 case BIFF2:
391 sal_uInt8 nFlagsBiff2;
392 rStrm >> nFlagsBiff2;
393 rStrm.skip( 1 );
394 rStrm >> nShortCut >> nNameLen;
395 mnFmlaSize = rStrm.readuInt8();
396 setFlag( nFlags, BIFF_DEFNAME_FUNC, getFlag( nFlagsBiff2, BIFF2_DEFNAME_FUNC ) );
397 maModel.maName = rStrm.readCharArrayUC( nNameLen, getTextEncoding(), true );
399 break;
400 case BIFF3:
401 case BIFF4:
402 rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize;
403 maModel.maName = rStrm.readCharArrayUC( nNameLen, getTextEncoding(), true );
404 break;
405 case BIFF5:
406 rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize >> nRefId >> nTabId;
407 rStrm.skip( 4 );
408 maModel.maName = rStrm.readCharArrayUC( nNameLen, getTextEncoding(), true );
409 break;
410 case BIFF8:
411 rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize >> nRefId >> nTabId;
412 rStrm.skip( 4 );
413 maModel.maName = rStrm.readUniStringBody( nNameLen, true );
414 break;
415 case BIFF_UNKNOWN: break;
418 // macro function/command, hidden flag
419 maModel.mnFuncGroupId = extractValue< sal_Int32 >( nFlags, 6, 6 );
420 maModel.mbMacro = getFlag( nFlags, BIFF_DEFNAME_MACRO );
421 maModel.mbFunction = getFlag( nFlags, BIFF_DEFNAME_FUNC );
422 maModel.mbVBName = getFlag( nFlags, BIFF_DEFNAME_VBNAME );
423 maModel.mbHidden = getFlag( nFlags, BIFF_DEFNAME_HIDDEN );
425 // get builtin name index from name
426 if( getFlag( nFlags, BIFF_DEFNAME_BUILTIN ) )
428 OSL_ENSURE( maModel.maName.getLength() == 1, "DefinedName::importDefinedName - wrong builtin name" );
429 if( maModel.maName.getLength() > 0 )
430 mcBuiltinId = maModel.maName[ 0 ];
432 /* In BIFF5, _xlnm._FilterDatabase appears as hidden user name without
433 built-in flag, and even worse, localized. */
434 else if( (eBiff == BIFF5) && lclIsFilterDatabaseName( maModel.maName ) )
436 mcBuiltinId = OOX_DEFNAME_FILTERDATABASE;
439 // unhide built-in names (_xlnm._FilterDatabase is always hidden)
440 if( isBuiltinName() )
441 maModel.mbHidden = false;
443 // get sheet index for sheet-local names in BIFF5-BIFF8
444 switch( getBiff() )
446 case BIFF2:
447 case BIFF3:
448 case BIFF4:
449 // BIFF2-BIFF4: all defined names are sheet-local
450 mnCalcSheet = nCalcSheet;
451 break;
452 case BIFF5:
453 // #i44019# nTabId may be invalid, resolve nRefId to sheet index
454 if( nRefId != BIFF_DEFNAME_GLOBAL )
455 if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() )
456 if( pExtLink->getLinkType() == LINKTYPE_INTERNAL )
457 mnCalcSheet = pExtLink->getCalcSheetIndex();
458 break;
459 case BIFF8:
460 // convert one-based worksheet index to zero-based Calc sheet index
461 OSL_ENSURE( nTabId >= 0, "DefinedName::importDefinedName - invalid local sheet index" );
462 if( nTabId != BIFF_DEFNAME_GLOBAL )
463 mnCalcSheet = getWorksheets().getCalcSheetIndex( nTabId - 1 );
464 break;
465 case BIFF_UNKNOWN:
466 break;
469 if( (getBiff() <= BIFF4) && maModel.mbHidden && (maModel.maName.getLength() > 1) && (maModel.maName[ 0 ] == '\x01') )
471 /* Read the token array of special internal names containing addresses
472 for BIFF3-BIFF4 3D references immediately. It is expected that
473 these names contain a simple cell reference or range reference.
474 Other regular defined names and external names rely on existence of
475 this reference. */
476 TokensFormulaContext aContext( true, true );
477 importBiffFormula( aContext, mnCalcSheet, rStrm, &mnFmlaSize );
478 extractReference( aContext.getTokens() );
480 else
482 /* Store record position of other defined names to be able to import
483 token array later. This is needed to correctly resolve references
484 to names that are stored later in the defined names list following
485 this name. */
486 mxBiffStrm.reset( new BiffInputStreamPos( rStrm ) );
490 void DefinedName::createNameObject()
492 // do not create hidden names and names for (macro) functions
493 if( maModel.mbHidden || maModel.mbFunction )
494 return;
496 // convert original name to final Calc name
497 if( maModel.mbVBName )
498 maCalcName = maModel.maName;
499 else if( isBuiltinName() )
500 maCalcName = lclGetBuiltinName( mcBuiltinId );
501 else
502 maCalcName = maModel.maName; //! TODO convert to valid name
504 // append sheet index for local names in multi-sheet documents
505 if( isWorkbookFile() && !isGlobalName() )
506 maCalcName = OUStringBuffer( maCalcName ).append( sal_Unicode( '_' ) ).
507 append( static_cast< sal_Int32 >( mnCalcSheet + 1 ) ).makeStringAndClear();
509 // special flags for this name
510 sal_Int32 nNameFlags = 0;
511 using namespace ::com::sun::star::sheet::NamedRangeFlag;
512 if( !isGlobalName() ) switch( mcBuiltinId )
514 case OOX_DEFNAME_CRITERIA: nNameFlags = FILTER_CRITERIA; break;
515 case OOX_DEFNAME_PRINTAREA: nNameFlags = PRINT_AREA; break;
516 case OOX_DEFNAME_PRINTTITLES: nNameFlags = COLUMN_HEADER | ROW_HEADER; break;
519 // create the name and insert it into the document, maCalcName will be changed to the resulting name
520 mxNamedRange = createNamedRangeObject( maCalcName, nNameFlags );
521 // index of this defined name used in formula token arrays
522 PropertySet aPropSet( mxNamedRange );
523 aPropSet.getProperty( mnTokenIndex, PROP_TokenIndex );
526 void DefinedName::convertFormula()
528 Reference< XFormulaTokens > xTokens( mxNamedRange, UNO_QUERY );
529 if( xTokens.is() )
531 // convert and set formula of the defined name
532 switch( getFilterType() )
534 case FILTER_OOX:
536 SimpleFormulaContext aContext( xTokens, true, false );
537 implImportOoxFormula( aContext );
539 break;
540 case FILTER_BIFF:
542 SimpleFormulaContext aContext( xTokens, true, getBiff() <= BIFF4 );
543 implImportBiffFormula( aContext );
545 break;
546 case FILTER_UNKNOWN: break;
549 // set builtin names (print ranges, repeated titles, filter ranges)
550 if( !isGlobalName() ) switch( mcBuiltinId )
552 case OOX_DEFNAME_PRINTAREA:
554 Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY );
555 ApiCellRangeList aPrintRanges;
556 getFormulaParser().extractCellRangeList( aPrintRanges, xTokens->getTokens(), false, mnCalcSheet );
557 if( xPrintAreas.is() && !aPrintRanges.empty() )
558 xPrintAreas->setPrintAreas( ContainerHelper::vectorToSequence( aPrintRanges ) );
560 break;
561 case OOX_DEFNAME_PRINTTITLES:
563 Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY );
564 ApiCellRangeList aTitleRanges;
565 getFormulaParser().extractCellRangeList( aTitleRanges, xTokens->getTokens(), false, mnCalcSheet );
566 if( xPrintAreas.is() && !aTitleRanges.empty() )
568 bool bHasRowTitles = false;
569 bool bHasColTitles = false;
570 const CellAddress& rMaxPos = getAddressConverter().getMaxAddress();
571 for( ApiCellRangeList::const_iterator aIt = aTitleRanges.begin(), aEnd = aTitleRanges.end(); (aIt != aEnd) && (!bHasRowTitles || !bHasColTitles); ++aIt )
573 bool bFullRow = (aIt->StartColumn == 0) && (aIt->EndColumn >= rMaxPos.Column);
574 bool bFullCol = (aIt->StartRow == 0) && (aIt->EndRow >= rMaxPos.Row);
575 if( !bHasRowTitles && bFullRow && !bFullCol )
577 xPrintAreas->setTitleRows( *aIt );
578 xPrintAreas->setPrintTitleRows( sal_True );
579 bHasRowTitles = true;
581 else if( !bHasColTitles && bFullCol && !bFullRow )
583 xPrintAreas->setTitleColumns( *aIt );
584 xPrintAreas->setPrintTitleColumns( sal_True );
585 bHasColTitles = true;
590 break;
595 bool DefinedName::getAbsoluteRange( CellRangeAddress& orRange ) const
597 /* ScNamedRangeObj::XCellRangeReferrer::getReferredCells is buggy with
598 relative references, so we extract an absolute reference by hand. */
599 Reference< XFormulaTokens > xTokens( mxNamedRange, UNO_QUERY );
600 return xTokens.is() && getFormulaParser().extractCellRange( orRange, xTokens->getTokens(), false );
603 void DefinedName::implImportOoxFormula( FormulaContext& rContext )
605 if( mxFormula.get() )
607 RecordInputStream aStrm( *mxFormula );
608 importOobFormula( rContext, mnCalcSheet, aStrm );
610 else
611 importOoxFormula( rContext, mnCalcSheet );
614 void DefinedName::implImportBiffFormula( FormulaContext& rContext )
616 OSL_ENSURE( mxBiffStrm.get(), "DefinedName::implImportBiffFormula - missing BIFF stream" );
617 BiffInputStream& rStrm = mxBiffStrm->getStream();
618 BiffInputStreamPosGuard aStrmGuard( rStrm );
619 if( mxBiffStrm->restorePosition() )
620 importBiffFormula( rContext, mnCalcSheet, rStrm, &mnFmlaSize );
623 // ============================================================================
625 DefinedNamesBuffer::DefinedNamesBuffer( const WorkbookHelper& rHelper ) :
626 WorkbookHelper( rHelper ),
627 mnCalcSheet( -1 )
631 void DefinedNamesBuffer::setLocalCalcSheet( sal_Int16 nCalcSheet )
633 OSL_ENSURE( (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4),
634 "DefinedNamesBuffer::setLocalCalcSheet - invalid call" );
635 mnCalcSheet = nCalcSheet;
638 DefinedNameRef DefinedNamesBuffer::importDefinedName( const AttributeList& rAttribs )
640 DefinedNameRef xDefName = createDefinedName();
641 xDefName->importDefinedName( rAttribs );
642 return xDefName;
645 void DefinedNamesBuffer::importDefinedName( RecordInputStream& rStrm )
647 createDefinedName()->importDefinedName( rStrm );
650 void DefinedNamesBuffer::importDefinedName( BiffInputStream& rStrm )
652 createDefinedName()->importDefinedName( rStrm, mnCalcSheet );
655 void DefinedNamesBuffer::finalizeImport()
657 // first insert all names without formula definition into the document
658 for( DefNameVector::iterator aIt = maDefNames.begin(), aEnd = maDefNames.end(); aIt != aEnd; ++aIt )
660 DefinedNameRef xDefName = *aIt;
661 xDefName->createNameObject();
662 sal_Int32 nTokenIndex = xDefName->getTokenIndex();
663 if( nTokenIndex >= 0 )
664 maDefNameMap[ nTokenIndex ] = xDefName;
667 /* Now convert all name formulas, so that the formula parser can find all
668 names in case of circular dependencies. */
669 maDefNames.forEachMem( &DefinedName::convertFormula );
672 DefinedNameRef DefinedNamesBuffer::getByIndex( sal_Int32 nIndex ) const
674 return maDefNames.get( nIndex );
677 DefinedNameRef DefinedNamesBuffer::getByTokenIndex( sal_Int32 nIndex ) const
679 return maDefNameMap.get( nIndex );
682 DefinedNameRef DefinedNamesBuffer::getByModelName( const OUString& rModelName, sal_Int16 nCalcSheet ) const
684 DefinedNameRef xGlobalName; // a found global name
685 DefinedNameRef xLocalName; // a found local name
686 for( DefNameVector::const_iterator aIt = maDefNames.begin(), aEnd = maDefNames.end(); (aIt != aEnd) && !xLocalName; ++aIt )
688 DefinedNameRef xCurrName = *aIt;
689 if( xCurrName->getModelName() == rModelName )
691 if( xCurrName->getLocalCalcSheet() == nCalcSheet )
692 xLocalName = xCurrName;
693 else if( xCurrName->isGlobalName() )
694 xGlobalName = xCurrName;
697 return xLocalName.get() ? xLocalName : xGlobalName;
700 DefinedNameRef DefinedNamesBuffer::createDefinedName()
702 DefinedNameRef xDefName( new DefinedName( *this ) );
703 maDefNames.push_back( xDefName );
704 return xDefName;
707 // ============================================================================
709 } // namespace xls
710 } // namespace oox