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
;
65 // ============================================================================
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 */
101 "Database", /* OOX */
102 "Criteria", /* OOX */
103 "Print_Area", /* OOX */
104 "Print_Titles", /* OOX */
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
] );
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
) )
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
] ) )
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
) )
171 // ============================================================================
173 DefinedNameModel::DefinedNameModel() :
183 // ============================================================================
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
;
212 orApiRef
.Flags
, orApiRef
.Column
, orApiRef
.RelativeColumn
,
213 rBaseAddress
.Column
, COLUMN_RELATIVE
, bColRel
);
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
;
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
;
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
);
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
);
276 return lclConvertReference( maRefAny
, rBaseAddress
, nRelFlags
);
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
);
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
);
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
),
320 mcBuiltinId( OOX_DEFNAME_UNKNOWN
),
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
)
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;
391 sal_uInt8 nFlagsBiff2
;
392 rStrm
>> nFlagsBiff2
;
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 );
402 rStrm
>> nFlags
>> nShortCut
>> nNameLen
>> mnFmlaSize
;
403 maModel
.maName
= rStrm
.readCharArrayUC( nNameLen
, getTextEncoding(), true );
406 rStrm
>> nFlags
>> nShortCut
>> nNameLen
>> mnFmlaSize
>> nRefId
>> nTabId
;
408 maModel
.maName
= rStrm
.readCharArrayUC( nNameLen
, getTextEncoding(), true );
411 rStrm
>> nFlags
>> nShortCut
>> nNameLen
>> mnFmlaSize
>> nRefId
>> nTabId
;
413 maModel
.maName
= rStrm
.readUniStringBody( nNameLen
, true );
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
449 // BIFF2-BIFF4: all defined names are sheet-local
450 mnCalcSheet
= nCalcSheet
;
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();
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 );
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
476 TokensFormulaContext
aContext( true, true );
477 importBiffFormula( aContext
, mnCalcSheet
, rStrm
, &mnFmlaSize
);
478 extractReference( aContext
.getTokens() );
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
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
)
496 // convert original name to final Calc name
497 if( maModel
.mbVBName
)
498 maCalcName
= maModel
.maName
;
499 else if( isBuiltinName() )
500 maCalcName
= lclGetBuiltinName( mcBuiltinId
);
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
);
531 // convert and set formula of the defined name
532 switch( getFilterType() )
536 SimpleFormulaContext
aContext( xTokens
, true, false );
537 implImportOoxFormula( aContext
);
542 SimpleFormulaContext
aContext( xTokens
, true, getBiff() <= BIFF4
);
543 implImportBiffFormula( aContext
);
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
) );
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;
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
);
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
),
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
);
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
);
707 // ============================================================================