Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "defnamesbuffer.hxx"
30 : :
31 : : #include <com/sun/star/sheet/ComplexReference.hpp>
32 : : #include <com/sun/star/sheet/ExternalReference.hpp>
33 : : #include <com/sun/star/sheet/NamedRangeFlag.hpp>
34 : : #include <com/sun/star/sheet/ReferenceFlags.hpp>
35 : : #include <com/sun/star/sheet/SingleReference.hpp>
36 : : #include <com/sun/star/sheet/XFormulaTokens.hpp>
37 : : #include <com/sun/star/sheet/XPrintAreas.hpp>
38 : : #include <rtl/ustrbuf.hxx>
39 : : #include "oox/helper/attributelist.hxx"
40 : : #include "oox/helper/containerhelper.hxx"
41 : : #include "oox/helper/propertyset.hxx"
42 : : #include "addressconverter.hxx"
43 : : #include "biffinputstream.hxx"
44 : : #include "externallinkbuffer.hxx"
45 : : #include "formulaparser.hxx"
46 : : #include "worksheetbuffer.hxx"
47 : : #include "tokenarray.hxx"
48 : : #include "tokenuno.hxx"
49 : :
50 : : namespace oox {
51 : : namespace xls {
52 : :
53 : : // ============================================================================
54 : :
55 : : using namespace ::com::sun::star::sheet;
56 : : using namespace ::com::sun::star::table;
57 : : using namespace ::com::sun::star::uno;
58 : :
59 : : using ::rtl::OUString;
60 : : using ::rtl::OUStringBuffer;
61 : :
62 : : // ============================================================================
63 : :
64 : : namespace {
65 : :
66 : : const sal_uInt32 BIFF12_DEFNAME_HIDDEN = 0x00000001;
67 : : const sal_uInt32 BIFF12_DEFNAME_FUNC = 0x00000002;
68 : : const sal_uInt32 BIFF12_DEFNAME_VBNAME = 0x00000004;
69 : : const sal_uInt32 BIFF12_DEFNAME_MACRO = 0x00000008;
70 : : const sal_uInt32 BIFF12_DEFNAME_CALCEXP = 0x00000010;
71 : : const sal_uInt32 BIFF12_DEFNAME_BUILTIN = 0x00000020;
72 : : const sal_uInt32 BIFF12_DEFNAME_PUBLISHED = 0x00008000;
73 : : const sal_uInt32 BIFF12_DEFNAME_WBPARAM = 0x00010000;
74 : :
75 : : const sal_uInt16 BIFF_DEFNAME_HIDDEN = 0x0001;
76 : : const sal_uInt16 BIFF_DEFNAME_FUNC = 0x0002;
77 : : const sal_uInt16 BIFF_DEFNAME_VBNAME = 0x0004;
78 : : const sal_uInt16 BIFF_DEFNAME_MACRO = 0x0008;
79 : : const sal_uInt16 BIFF_DEFNAME_CALCEXP = 0x0010;
80 : : const sal_uInt16 BIFF_DEFNAME_BUILTIN = 0x0020;
81 : : const sal_uInt16 BIFF_DEFNAME_BIG = 0x1000;
82 : :
83 : : const sal_uInt8 BIFF2_DEFNAME_FUNC = 0x02; /// BIFF2 function/command flag.
84 : :
85 : : const sal_uInt16 BIFF_DEFNAME_GLOBAL = 0; /// 0 = Globally defined name.
86 : :
87 : : const sal_uInt16 BIFF_REFFLAG_COL1REL = 0x0001;
88 : : const sal_uInt16 BIFF_REFFLAG_ROW1REL = 0x0002;
89 : : const sal_uInt16 BIFF_REFFLAG_COL2REL = 0x0004;
90 : : const sal_uInt16 BIFF_REFFLAG_ROW2REL = 0x0008;
91 : :
92 : : // ----------------------------------------------------------------------------
93 : :
94 : : const sal_Char* const spcLegacyPrefix = "Excel_BuiltIn_";
95 : : const sal_Char* const spcOoxPrefix = "_xlnm.";
96 : :
97 : : const sal_Char* const sppcBaseNames[] =
98 : : {
99 : : "Consolidate_Area",
100 : : "Auto_Open",
101 : : "Auto_Close",
102 : : "Extract",
103 : : "Database",
104 : : "Criteria",
105 : : "Print_Area",
106 : : "Print_Titles",
107 : : "Recorder",
108 : : "Data_Form",
109 : : "Auto_Activate",
110 : : "Auto_Deactivate",
111 : : "Sheet_Title",
112 : : "_FilterDatabase"
113 : : };
114 : :
115 : : /** Localized names for _xlnm._FilterDatabase as used in BIFF5. */
116 : : const sal_Char* const sppcFilterDbNames[] =
117 : : {
118 : : "_FilterDatabase", // English
119 : : "_FilterDatenbank" // German
120 : : };
121 : :
122 : 45 : OUString lclGetBaseName( sal_Unicode cBuiltinId )
123 : : {
124 : : OSL_ENSURE( cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ), "lclGetBaseName - unsupported built-in identifier" );
125 : 45 : OUStringBuffer aBuffer;
126 [ + - ]: 45 : if( cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ) )
127 [ + - ]: 45 : aBuffer.appendAscii( sppcBaseNames[ cBuiltinId ] );
128 : : else
129 [ # # ]: 0 : aBuffer.append( static_cast< sal_Int32 >( cBuiltinId ) );
130 [ + - ]: 45 : return aBuffer.makeStringAndClear();
131 : : }
132 : :
133 : 3 : OUString lclGetPrefixedName( sal_Unicode cBuiltinId )
134 : : {
135 [ + - ][ + - ]: 3 : return OUStringBuffer().appendAscii( spcOoxPrefix ).append( lclGetBaseName( cBuiltinId ) ).makeStringAndClear();
[ + - ]
136 : : }
137 : :
138 : : /** returns the built-in name identifier from a perfixed built-in name, e.g. '_xlnm.Print_Area'. */
139 : 33 : sal_Unicode lclGetBuiltinIdFromPrefixedName( const OUString& rModelName )
140 : : {
141 : 33 : OUString aPrefix = OUString::createFromAscii( spcOoxPrefix );
142 : 33 : sal_Int32 nPrefixLen = aPrefix.getLength();
143 [ + + ]: 33 : if( rModelName.matchIgnoreAsciiCase( aPrefix ) )
144 : : {
145 [ + - ]: 45 : for( sal_Unicode cBuiltinId = 0; cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ); ++cBuiltinId )
146 : : {
147 [ + - ]: 42 : OUString aBaseName = lclGetBaseName( cBuiltinId );
148 : 42 : sal_Int32 nBaseNameLen = aBaseName.getLength();
149 [ + + ][ + + ]: 42 : if( (rModelName.getLength() == nPrefixLen + nBaseNameLen) && rModelName.matchIgnoreAsciiCase( aBaseName, nPrefixLen ) )
[ + + ]
150 : 42 : return cBuiltinId;
151 [ + + ]: 42 : }
152 : : }
153 : 33 : return BIFF_DEFNAME_UNKNOWN;
154 : : }
155 : :
156 : : /** returns the built-in name identifier from a built-in base name, e.g. 'Print_Area'. */
157 : 0 : sal_Unicode lclGetBuiltinIdFromBaseName( const OUString& rModelName )
158 : : {
159 [ # # ]: 0 : for( sal_Unicode cBuiltinId = 0; cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ); ++cBuiltinId )
160 [ # # ]: 0 : if( rModelName.equalsIgnoreAsciiCaseAscii( sppcBaseNames[ cBuiltinId ] ) )
161 : 0 : return cBuiltinId;
162 : 0 : return BIFF_DEFNAME_UNKNOWN;
163 : : }
164 : :
165 : 33 : OUString lclGetUpcaseModelName( const OUString& rModelName )
166 : : {
167 : : // TODO: i18n?
168 : 33 : return rModelName.toAsciiUpperCase();
169 : : }
170 : :
171 : 0 : void lclConvertRefFlags( sal_Int32& ornFlags, sal_Int32& ornAbsPos, sal_Int32& ornRelPos, sal_Int32 nBasePos, sal_Int32 nApiRelFlag, bool bRel )
172 : : {
173 [ # # ][ # # ]: 0 : if( getFlag( ornFlags, nApiRelFlag ) && !bRel )
[ # # ]
174 : : {
175 : : // convert relative to absolute
176 : 0 : setFlag( ornFlags, nApiRelFlag, false );
177 : 0 : ornAbsPos = nBasePos + ornRelPos;
178 : : }
179 [ # # ][ # # ]: 0 : else if( !getFlag( ornFlags, nApiRelFlag ) && bRel )
[ # # ]
180 : : {
181 : : // convert absolute to relative
182 : 0 : setFlag( ornFlags, nApiRelFlag, true );
183 : 0 : ornRelPos = ornAbsPos - nBasePos;
184 : : }
185 : 0 : }
186 : :
187 : 0 : void lclConvertSingleRefFlags( SingleReference& orApiRef, const CellAddress& rBaseAddr, bool bColRel, bool bRowRel )
188 : : {
189 : : using namespace ::com::sun::star::sheet::ReferenceFlags;
190 : : lclConvertRefFlags(
191 : : orApiRef.Flags, orApiRef.Column, orApiRef.RelativeColumn,
192 : 0 : rBaseAddr.Column, COLUMN_RELATIVE, bColRel );
193 : : lclConvertRefFlags(
194 : : orApiRef.Flags, orApiRef.Row, orApiRef.RelativeRow,
195 : 0 : rBaseAddr.Row, ROW_RELATIVE, bRowRel );
196 : 0 : }
197 : :
198 : 0 : Any lclConvertReference( const Any& rRefAny, const CellAddress& rBaseAddr, sal_uInt16 nRelFlags )
199 : : {
200 [ # # ][ # # ]: 0 : if( rRefAny.has< SingleReference >() && !getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ) && !getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) )
[ # # ][ # # ]
201 : : {
202 : 0 : SingleReference aApiRef;
203 [ # # ]: 0 : rRefAny >>= aApiRef;
204 [ # # ]: 0 : lclConvertSingleRefFlags( aApiRef, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) );
205 [ # # ]: 0 : return Any( aApiRef );
206 : : }
207 [ # # ]: 0 : if( rRefAny.has< ComplexReference >() )
208 : : {
209 : 0 : ComplexReference aApiRef;
210 [ # # ]: 0 : rRefAny >>= aApiRef;
211 [ # # ]: 0 : lclConvertSingleRefFlags( aApiRef.Reference1, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) );
212 [ # # ]: 0 : lclConvertSingleRefFlags( aApiRef.Reference2, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) );
213 [ # # ]: 0 : return Any( aApiRef );
214 : : }
215 : 0 : return Any();
216 : : }
217 : :
218 : : } // namespace
219 : :
220 : : // ============================================================================
221 : :
222 : 33 : DefinedNameModel::DefinedNameModel() :
223 : : mnSheet( -1 ),
224 : : mnFuncGroupId( -1 ),
225 : : mbMacro( false ),
226 : : mbFunction( false ),
227 : : mbVBName( false ),
228 : 33 : mbHidden( false )
229 : : {
230 : 33 : }
231 : :
232 : : // ============================================================================
233 : :
234 : 33 : DefinedNameBase::DefinedNameBase( const WorkbookHelper& rHelper ) :
235 : 33 : WorkbookHelper( rHelper )
236 : : {
237 : 33 : }
238 : :
239 : 33 : const OUString& DefinedNameBase::getUpcaseModelName() const
240 : : {
241 [ + - ]: 33 : if( maUpModelName.isEmpty() )
242 : 33 : maUpModelName = lclGetUpcaseModelName( maModel.maName );
243 : 33 : return maUpModelName;
244 : : }
245 : :
246 : 0 : Any DefinedNameBase::getReference( const CellAddress& rBaseAddr ) const
247 : : {
248 [ # # ][ # # ]: 0 : if( maRefAny.hasValue() && (maModel.maName.getLength() >= 2) && (maModel.maName[ 0 ] == '\x01') )
[ # # ][ # # ]
249 : : {
250 : 0 : sal_Unicode cFlagsChar = getUpcaseModelName()[ 1 ];
251 [ # # ][ # # ]: 0 : if( ('A' <= cFlagsChar) && (cFlagsChar <= 'P') )
252 : : {
253 : 0 : sal_uInt16 nRelFlags = static_cast< sal_uInt16 >( cFlagsChar - 'A' );
254 [ # # ]: 0 : if( maRefAny.has< ExternalReference >() )
255 : : {
256 : 0 : ExternalReference aApiExtRef;
257 [ # # ]: 0 : maRefAny >>= aApiExtRef;
258 [ # # ]: 0 : Any aRefAny = lclConvertReference( aApiExtRef.Reference, rBaseAddr, nRelFlags );
259 [ # # ]: 0 : if( aRefAny.hasValue() )
260 : : {
261 [ # # ]: 0 : aApiExtRef.Reference <<= aRefAny;
262 [ # # ]: 0 : return Any( aApiExtRef );
263 [ # # ][ # # ]: 0 : }
264 : : }
265 : : else
266 : : {
267 : 0 : return lclConvertReference( maRefAny, rBaseAddr, nRelFlags );
268 : : }
269 : : }
270 : : }
271 : 0 : return Any();
272 : : }
273 : :
274 : 33 : ApiTokenSequence DefinedNameBase::importOoxFormula( sal_Int16 nBaseSheet )
275 : : {
276 : 33 : return (!maModel.maFormula.isEmpty()) ?
277 [ + - ]: 33 : getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), maModel.maFormula ) :
278 [ + - ][ # # ]: 66 : getFormulaParser().convertErrorToFormula( BIFF_ERR_NAME );
[ # # ][ + - ]
[ + - ][ + - ]
[ # # # #
# # ][ + - ]
279 : : }
280 : :
281 : 0 : ApiTokenSequence DefinedNameBase::importBiff12Formula( sal_Int16 nBaseSheet, SequenceInputStream& rStrm )
282 : : {
283 [ # # ][ # # ]: 0 : return getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), FORMULATYPE_DEFINEDNAME, rStrm );
284 : : }
285 : :
286 : 0 : ApiTokenSequence DefinedNameBase::importBiffFormula( sal_Int16 nBaseSheet, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize )
287 : : {
288 : : return (!pnFmlaSize || (*pnFmlaSize > 0)) ?
289 [ # # ]: 0 : getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), FORMULATYPE_DEFINEDNAME, rStrm, pnFmlaSize ) :
290 [ # # ][ # # ]: 0 : getFormulaParser().convertErrorToFormula( BIFF_ERR_NAME );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # #
# # ]
291 : : }
292 : :
293 : : // ============================================================================
294 : :
295 : 33 : DefinedName::DefinedName( const WorkbookHelper& rHelper ) :
296 : : DefinedNameBase( rHelper ),
297 : : mnTokenIndex( -1 ),
298 : : mcBuiltinId( BIFF_DEFNAME_UNKNOWN ),
299 : 33 : mnFmlaSize( 0 )
300 : : {
301 : 33 : }
302 : :
303 : 33 : void DefinedName::importDefinedName( const AttributeList& rAttribs )
304 : : {
305 [ + - ]: 33 : maModel.maName = rAttribs.getXString( XML_name, OUString() );
306 : 33 : maModel.mnSheet = rAttribs.getInteger( XML_localSheetId, -1 );
307 : 33 : maModel.mnFuncGroupId = rAttribs.getInteger( XML_functionGroupId, -1 );
308 : 33 : maModel.mbMacro = rAttribs.getBool( XML_xlm, false );
309 : 33 : maModel.mbFunction = rAttribs.getBool( XML_function, false );
310 : 33 : maModel.mbVBName = rAttribs.getBool( XML_vbProcedure, false );
311 : 33 : maModel.mbHidden = rAttribs.getBool( XML_hidden, false );
312 [ + + ]: 33 : mnCalcSheet = (maModel.mnSheet >= 0) ? getWorksheets().getCalcSheetIndex( maModel.mnSheet ) : -1;
313 : :
314 : : /* Detect built-in state from name itself, there is no built-in flag.
315 : : Built-in names are prexixed with '_xlnm.' instead. */
316 : 33 : mcBuiltinId = lclGetBuiltinIdFromPrefixedName( maModel.maName );
317 : 33 : }
318 : :
319 : 33 : void DefinedName::setFormula( const OUString& rFormula )
320 : : {
321 : 33 : maModel.maFormula = rFormula;
322 : 33 : }
323 : :
324 : 0 : void DefinedName::importDefinedName( SequenceInputStream& rStrm )
325 : : {
326 : : sal_uInt32 nFlags;
327 [ # # ]: 0 : rStrm >> nFlags;
328 [ # # ]: 0 : rStrm.skip( 1 ); // keyboard shortcut
329 [ # # ][ # # ]: 0 : rStrm >> maModel.mnSheet >> maModel.maName;
330 [ # # ][ # # ]: 0 : mnCalcSheet = (maModel.mnSheet >= 0) ? getWorksheets().getCalcSheetIndex( maModel.mnSheet ) : -1;
[ # # ]
331 : :
332 : : // macro function/command, hidden flag
333 : 0 : maModel.mnFuncGroupId = extractValue< sal_Int32 >( nFlags, 6, 9 );
334 : 0 : maModel.mbMacro = getFlag( nFlags, BIFF12_DEFNAME_MACRO );
335 : 0 : maModel.mbFunction = getFlag( nFlags, BIFF12_DEFNAME_FUNC );
336 : 0 : maModel.mbVBName = getFlag( nFlags, BIFF12_DEFNAME_VBNAME );
337 : 0 : maModel.mbHidden = getFlag( nFlags, BIFF12_DEFNAME_HIDDEN );
338 : :
339 : : // get built-in name index from name
340 [ # # ]: 0 : if( getFlag( nFlags, BIFF12_DEFNAME_BUILTIN ) )
341 : 0 : mcBuiltinId = lclGetBuiltinIdFromBaseName( maModel.maName );
342 : :
343 : : // store token array data
344 [ # # ]: 0 : sal_Int64 nRecPos = rStrm.tell();
345 [ # # ]: 0 : sal_Int32 nFmlaSize = rStrm.readInt32();
346 [ # # ]: 0 : rStrm.skip( nFmlaSize );
347 [ # # ]: 0 : sal_Int32 nAddDataSize = rStrm.readInt32();
348 [ # # ][ # # ]: 0 : if( !rStrm.isEof() && (nFmlaSize > 0) && (nAddDataSize >= 0) && (rStrm.getRemaining() >= nAddDataSize) )
[ # # ][ # # ]
[ # # ][ # # ]
349 : : {
350 : 0 : sal_Int32 nTotalSize = 8 + nFmlaSize + nAddDataSize;
351 [ # # ]: 0 : mxFormula.reset( new StreamDataSequence );
352 [ # # ]: 0 : rStrm.seek( nRecPos );
353 [ # # ]: 0 : rStrm.readData( *mxFormula, nTotalSize );
354 : : }
355 : 0 : }
356 : :
357 : 33 : void DefinedName::createNameObject( sal_Int32 nIndex )
358 : : {
359 : : // do not create names for (macro) functions or VBA procedures
360 : : // #163146# do not ignore hidden names (may be regular names created by VBA scripts)
361 [ + - ][ - + ]: 33 : if( /*maModel.mbHidden ||*/ maModel.mbFunction || maModel.mbVBName )
362 : 0 : return;
363 : :
364 : : // skip BIFF names without stream position (e.g. BIFF3-BIFF4 internal 3D references)
365 [ - + ][ # # ]: 33 : if( (getFilterType() == FILTER_BIFF) && !mxBiffStrm.get() )
[ - + ]
366 : 0 : return;
367 : :
368 : : // convert original name to final Calc name (TODO: filter invalid characters from model name)
369 [ + + ]: 33 : maCalcName = isBuiltinName() ? lclGetPrefixedName( mcBuiltinId ) : maModel.maName;
370 : :
371 : : // #163146# do not rename sheet-local names by default, this breaks VBA scripts
372 : :
373 : : // special flags for this name
374 : 33 : sal_Int32 nNameFlags = 0;
375 : : using namespace ::com::sun::star::sheet::NamedRangeFlag;
376 [ - - - + ]: 33 : if( !isGlobalName() ) switch( mcBuiltinId )
[ + + ]
377 : : {
378 : 0 : case BIFF_DEFNAME_CRITERIA: nNameFlags = FILTER_CRITERIA; break;
379 : 0 : case BIFF_DEFNAME_PRINTAREA: nNameFlags = PRINT_AREA; break;
380 : 15 : case BIFF_DEFNAME_PRINTTITLES: nNameFlags = COLUMN_HEADER | ROW_HEADER; break;
381 : : }
382 : :
383 : : // create the name and insert it into the document, maCalcName will be changed to the resulting name
384 [ + + ]: 33 : if (maModel.mnSheet >= 0)
385 [ + - ]: 15 : mpScRangeData = createLocalNamedRangeObject( maCalcName, getTokens(), nIndex, nNameFlags, maModel.mnSheet );
386 : : else
387 [ + - ]: 18 : mpScRangeData = createNamedRangeObject( maCalcName, getTokens(), nIndex, nNameFlags );
388 : 33 : mnTokenIndex = nIndex;
389 : : }
390 : :
391 : : ApiTokenSequence
392 : 33 : DefinedName::getTokens()
393 : : {
394 : : // convert and set formula of the defined name
395 : 33 : ApiTokenSequence aTokens;
396 [ + - - - ]: 33 : switch( getFilterType() )
[ + - ]
397 : : {
398 : : case FILTER_OOXML:
399 : : {
400 [ - + ]: 33 : if( mxFormula.get() )
401 : : {
402 [ # # ]: 0 : SequenceInputStream aStrm( *mxFormula );
403 [ # # ][ # # ]: 0 : aTokens = importBiff12Formula( mnCalcSheet, aStrm );
[ # # ][ # # ]
404 : : }
405 : : else
406 [ + - ][ + - ]: 33 : aTokens = importOoxFormula( mnCalcSheet );
[ + - ]
407 : : }
408 : 33 : break;
409 : : case FILTER_BIFF:
410 : : {
411 : : OSL_ENSURE( mxBiffStrm.get(), "DefinedName::convertFormula - missing BIFF stream" );
412 [ # # ]: 0 : if( mxBiffStrm.get() )
413 : : {
414 : 0 : BiffInputStream& rStrm = mxBiffStrm->getStream();
415 [ # # ]: 0 : BiffInputStreamPosGuard aStrmGuard( rStrm );
416 [ # # ][ # # ]: 0 : if( mxBiffStrm->restorePosition() )
417 [ # # ][ # # ]: 0 : aTokens = importBiffFormula( mnCalcSheet, rStrm, &mnFmlaSize );
[ # # ][ # # ]
418 : : }
419 : : }
420 : 0 : break;
421 : : case FILTER_UNKNOWN:
422 : 0 : break;
423 : : }
424 : 33 : return aTokens;
425 : : }
426 : :
427 : 33 : void DefinedName::convertFormula()
428 : : {
429 : 33 : ScTokenArray* pTokenArray = mpScRangeData->GetCode();
430 [ + - ]: 33 : Sequence< FormulaToken > aFTokenSeq;
431 [ + - ][ + - ]: 33 : (void)ScTokenConversion::ConvertToTokenSequence( this->getScDocument(), aFTokenSeq, *pTokenArray );
432 : : // set built-in names (print ranges, repeated titles, filter ranges)
433 [ + + ]: 33 : if( !isGlobalName() ) switch( mcBuiltinId )
[ - - + ]
434 : : {
435 : : case BIFF_DEFNAME_PRINTAREA:
436 : : {
437 [ # # ][ # # ]: 0 : Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY );
438 [ # # ]: 0 : ApiCellRangeList aPrintRanges;
439 [ # # ][ # # ]: 0 : getFormulaParser().extractCellRangeList( aPrintRanges, aFTokenSeq, false, mnCalcSheet );
440 [ # # ][ # # ]: 0 : if( xPrintAreas.is() && !aPrintRanges.empty() )
[ # # ]
441 [ # # ][ # # ]: 0 : xPrintAreas->setPrintAreas( ContainerHelper::vectorToSequence( aPrintRanges ) );
[ # # ][ # # ]
442 : : }
443 : 0 : break;
444 : : case BIFF_DEFNAME_PRINTTITLES:
445 : : {
446 [ # # ][ # # ]: 0 : Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY );
447 [ # # ]: 0 : ApiCellRangeList aTitleRanges;
448 [ # # ][ # # ]: 0 : getFormulaParser().extractCellRangeList( aTitleRanges, aFTokenSeq, false, mnCalcSheet );
449 [ # # ][ # # ]: 0 : if( xPrintAreas.is() && !aTitleRanges.empty() )
[ # # ]
450 : : {
451 : 0 : bool bHasRowTitles = false;
452 : 0 : bool bHasColTitles = false;
453 [ # # ]: 0 : const CellAddress& rMaxPos = getAddressConverter().getMaxAddress();
454 [ # # ][ # # ]: 0 : for( ApiCellRangeList::const_iterator aIt = aTitleRanges.begin(), aEnd = aTitleRanges.end(); (aIt != aEnd) && (!bHasRowTitles || !bHasColTitles); ++aIt )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
455 : : {
456 [ # # ][ # # ]: 0 : bool bFullRow = (aIt->StartColumn == 0) && (aIt->EndColumn >= rMaxPos.Column);
457 [ # # ][ # # ]: 0 : bool bFullCol = (aIt->StartRow == 0) && (aIt->EndRow >= rMaxPos.Row);
458 [ # # ][ # # ]: 0 : if( !bHasRowTitles && bFullRow && !bFullCol )
[ # # ]
459 : : {
460 [ # # ][ # # ]: 0 : xPrintAreas->setTitleRows( *aIt );
461 [ # # ][ # # ]: 0 : xPrintAreas->setPrintTitleRows( sal_True );
462 : 0 : bHasRowTitles = true;
463 : : }
464 [ # # ][ # # ]: 0 : else if( !bHasColTitles && bFullCol && !bFullRow )
[ # # ]
465 : : {
466 [ # # ][ # # ]: 0 : xPrintAreas->setTitleColumns( *aIt );
467 [ # # ][ # # ]: 0 : xPrintAreas->setPrintTitleColumns( sal_True );
468 : 0 : bHasColTitles = true;
469 : : }
470 : : }
471 : 0 : }
472 : : }
473 : 15 : break;
474 [ + - ]: 33 : }
475 : 33 : }
476 : :
477 : 3 : bool DefinedName::getAbsoluteRange( CellRangeAddress& orRange ) const
478 : : {
479 : 3 : ScTokenArray* pTokenArray = mpScRangeData->GetCode();
480 [ + - ]: 3 : Sequence< FormulaToken > aFTokenSeq;
481 [ + - ][ + - ]: 3 : ScTokenConversion::ConvertToTokenSequence( this->getScDocument(), aFTokenSeq, *pTokenArray );
482 [ + - ][ + - ]: 3 : return getFormulaParser().extractCellRange( orRange, aFTokenSeq, false );
[ + - ]
483 : : }
484 : :
485 : : // ============================================================================
486 : :
487 : 24 : DefinedNamesBuffer::DefinedNamesBuffer( const WorkbookHelper& rHelper ) :
488 : : WorkbookHelper( rHelper ),
489 [ + - ][ + - ]: 24 : mnCalcSheet( -1 )
[ + - ][ + - ]
490 : : {
491 : 24 : }
492 : :
493 : 33 : DefinedNameRef DefinedNamesBuffer::importDefinedName( const AttributeList& rAttribs )
494 : : {
495 : 33 : DefinedNameRef xDefName = createDefinedName();
496 [ + - ]: 33 : xDefName->importDefinedName( rAttribs );
497 : 33 : return xDefName;
498 : : }
499 : :
500 : 0 : void DefinedNamesBuffer::importDefinedName( SequenceInputStream& rStrm )
501 : : {
502 [ # # ]: 0 : createDefinedName()->importDefinedName( rStrm );
503 : 0 : }
504 : :
505 : 24 : void DefinedNamesBuffer::finalizeImport()
506 : : {
507 : : // first insert all names without formula definition into the document, and insert them into the maps
508 : 24 : int index = 0;
509 [ + - ][ + + ]: 57 : for( DefNameVector::iterator aIt = maDefNames.begin(), aEnd = maDefNames.end(); aIt != aEnd; ++aIt )
510 : : {
511 [ + - ]: 33 : DefinedNameRef xDefName = *aIt;
512 [ + - ]: 33 : xDefName->createNameObject( ++index );
513 : : // map by sheet index and original model name
514 [ + - ][ + - ]: 33 : maModelNameMap[ SheetNameKey( xDefName->getLocalCalcSheet(), xDefName->getUpcaseModelName() ) ] = xDefName;
[ + - ]
515 : : // map by sheet index and built-in identifier
516 [ + + ][ + + ]: 33 : if( !xDefName->isGlobalName() && xDefName->isBuiltinName() )
[ + + ]
517 [ + - ][ + - ]: 3 : maBuiltinMap[ BuiltinKey( xDefName->getLocalCalcSheet(), xDefName->getBuiltinId() ) ] = xDefName;
[ + - ]
518 : : // map by API formula token identifier
519 : 33 : sal_Int32 nTokenIndex = xDefName->getTokenIndex();
520 [ + - ]: 33 : if( nTokenIndex >= 0 )
521 [ + - ][ + - ]: 33 : maTokenIdMap[ nTokenIndex ] = xDefName;
522 [ + - ]: 33 : }
523 : :
524 : : /* Now convert all name formulas, so that the formula parser can find all
525 : : names in case of circular dependencies. */
526 : 24 : maDefNames.forEachMem( &DefinedName::convertFormula );
527 : 24 : }
528 : :
529 : 0 : DefinedNameRef DefinedNamesBuffer::getByIndex( sal_Int32 nIndex ) const
530 : : {
531 : 0 : return maDefNames.get( nIndex );
532 : : }
533 : :
534 : 0 : DefinedNameRef DefinedNamesBuffer::getByTokenIndex( sal_Int32 nIndex ) const
535 : : {
536 : 0 : return maTokenIdMap.get( nIndex );
537 : : }
538 : :
539 : 0 : DefinedNameRef DefinedNamesBuffer::getByModelName( const OUString& rModelName, sal_Int16 nCalcSheet ) const
540 : : {
541 : 0 : OUString aUpcaseName = lclGetUpcaseModelName( rModelName );
542 [ # # ]: 0 : DefinedNameRef xDefName = maModelNameMap.get( SheetNameKey( nCalcSheet, aUpcaseName ) );
543 : : // lookup global name, if no local name exists
544 [ # # ][ # # ]: 0 : if( !xDefName && (nCalcSheet >= 0) )
[ # # ]
545 [ # # ][ # # ]: 0 : xDefName = maModelNameMap.get( SheetNameKey( -1, aUpcaseName ) );
[ # # ]
546 : 0 : return xDefName;
547 : : }
548 : :
549 : 60 : DefinedNameRef DefinedNamesBuffer::getByBuiltinId( sal_Unicode cBuiltinId, sal_Int16 nCalcSheet ) const
550 : : {
551 [ + - ]: 60 : return maBuiltinMap.get( BuiltinKey( nCalcSheet, cBuiltinId ) );
552 : : }
553 : :
554 : 33 : DefinedNameRef DefinedNamesBuffer::createDefinedName()
555 : : {
556 [ + - ][ + - ]: 33 : DefinedNameRef xDefName( new DefinedName( *this ) );
557 [ + - ]: 33 : maDefNames.push_back( xDefName );
558 : 33 : return xDefName;
559 : : }
560 : :
561 : : // ============================================================================
562 : :
563 : : } // namespace xls
564 [ + - ][ + - ]: 24 : } // namespace oox
565 : :
566 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|