update ooo310-m15
[ooovba.git] / sc / source / filter / excel / xeescher.cxx
blob98eb5b740f3ee9eec204d804083952a0e9bba201
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: xeescher.cxx,v $
10 * $Revision: 1.24.128.6 $
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 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include <set>
35 #include <iterator>
37 #include "xeescher.hxx"
39 #include <com/sun/star/lang/XServiceInfo.hpp>
40 #include <com/sun/star/frame/XModel.hpp>
41 #include <com/sun/star/form/FormComponentType.hpp>
42 #include <com/sun/star/awt/VisualEffect.hpp>
43 #include <com/sun/star/awt/ScrollBarOrientation.hpp>
44 #include <com/sun/star/drawing/XShape.hpp>
45 #include <com/sun/star/form/binding/XBindableValue.hpp>
46 #include <com/sun/star/form/binding/XValueBinding.hpp>
47 #include <com/sun/star/form/binding/XListEntrySink.hpp>
48 #include <com/sun/star/form/binding/XListEntrySource.hpp>
49 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
51 #include <rtl/ustrbuf.h>
52 #include <vcl/bmpacc.hxx>
53 #include <svx/svdoole2.hxx>
54 #include <svx/svdocapt.hxx>
55 #include <svx/outlobj.hxx>
56 #include <svx/editobj.hxx>
58 #include "editutil.hxx"
59 #include "unonames.hxx"
60 #include "convuno.hxx"
61 #include "postit.hxx"
63 #include "fapihelper.hxx"
64 #include "xechart.hxx"
65 #include "xeformula.hxx"
66 #include "xelink.hxx"
67 #include "xename.hxx"
68 #include "xestyle.hxx"
69 #include "userdat.hxx"
70 #include "drwlayer.hxx"
71 #include "svx/unoapi.hxx"
73 #include <oox/core/tokens.hxx>
75 using ::rtl::OString;
76 using ::rtl::OUString;
77 using ::rtl::OUStringBuffer;
78 using ::com::sun::star::uno::UNO_QUERY;
79 using ::com::sun::star::uno::Reference;
80 using ::com::sun::star::uno::Sequence;
81 using ::com::sun::star::lang::XServiceInfo;
82 using ::com::sun::star::beans::XPropertySet;
83 using ::com::sun::star::drawing::XShape;
84 using ::com::sun::star::frame::XModel;
85 using ::com::sun::star::embed::XEmbeddedObject;
86 using ::com::sun::star::awt::XControlModel;
87 using ::com::sun::star::form::binding::XBindableValue;
88 using ::com::sun::star::form::binding::XValueBinding;
89 using ::com::sun::star::form::binding::XListEntrySink;
90 using ::com::sun::star::form::binding::XListEntrySource;
91 using ::com::sun::star::script::ScriptEventDescriptor;
92 using ::com::sun::star::table::CellAddress;
93 using ::com::sun::star::table::CellRangeAddress;
95 // ============================================================================
97 XclExpImgData::XclExpImgData( const Graphic& rGraphic, sal_uInt16 nRecId ) :
98 maGraphic( rGraphic ),
99 mnRecId( nRecId )
103 void XclExpImgData::Save( XclExpStream& rStrm )
105 Bitmap aBmp = maGraphic.GetBitmap();
106 if( aBmp.GetBitCount() != 24 )
107 aBmp.Convert( BMP_CONVERSION_24BIT );
109 if( BitmapReadAccess* pAccess = aBmp.AcquireReadAccess() )
111 sal_Int32 nWidth = ::std::min< sal_Int32 >( pAccess->Width(), 0xFFFF );
112 sal_Int32 nHeight = ::std::min< sal_Int32 >( pAccess->Height(), 0xFFFF );
113 if( (nWidth > 0) && (nHeight > 0) )
115 sal_uInt8 nPadding = static_cast< sal_uInt8 >( nWidth & 0x03 );
116 sal_uInt32 nTmpSize = static_cast< sal_uInt32 >( (nWidth * 3 + nPadding) * nHeight + 12 );
118 rStrm.StartRecord( mnRecId, nTmpSize + 4 );
120 rStrm << EXC_IMGDATA_BMP // BMP format
121 << EXC_IMGDATA_WIN // Windows
122 << nTmpSize // size after _this_ field
123 << sal_uInt32( 12 ) // BITMAPCOREHEADER size
124 << static_cast< sal_uInt16 >( nWidth ) // width
125 << static_cast< sal_uInt16 >( nHeight ) // height
126 << sal_uInt16( 1 ) // planes
127 << sal_uInt16( 24 ); // bits per pixel
129 for( sal_Int32 nY = nHeight - 1; nY >= 0; --nY )
131 for( sal_Int32 nX = 0; nX < nWidth; ++nX )
133 const BitmapColor& rBmpColor = pAccess->GetPixel( nY, nX );
134 rStrm << rBmpColor.GetBlue() << rBmpColor.GetGreen() << rBmpColor.GetRed();
136 rStrm.WriteZeroBytes( nPadding );
139 rStrm.EndRecord();
141 aBmp.ReleaseAccess( pAccess );
145 // ============================================================================
147 XclExpControlHelper::XclExpControlHelper( const XclExpRoot& rRoot ) :
148 XclExpRoot( rRoot ),
149 mnEntryCount( 0 )
153 XclExpControlHelper::~XclExpControlHelper()
157 void XclExpControlHelper::ConvertSheetLinks( Reference< XShape > xShape )
159 mxCellLink.reset();
160 mxSrcRange.reset();
161 mnEntryCount = 0;
163 // get control model
164 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( xShape );
165 if( !xCtrlModel.is() )
166 return;
168 // *** cell link *** ------------------------------------------------------
170 Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY );
171 if( xBindable.is() )
173 Reference< XServiceInfo > xServInfo( xBindable->getValueBinding(), UNO_QUERY );
174 if( xServInfo.is() && xServInfo->supportsService( CREATE_OUSTRING( SC_SERVICENAME_VALBIND ) ) )
176 ScfPropertySet aBindProp( xServInfo );
177 CellAddress aApiAddress;
178 if( aBindProp.GetProperty( aApiAddress, CREATE_OUSTRING( SC_UNONAME_BOUNDCELL ) ) )
180 ScAddress aCellLink;
181 ScUnoConversion::FillScAddress( aCellLink, aApiAddress );
182 if( GetTabInfo().IsExportTab( aCellLink.Tab() ) )
183 mxCellLink = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, aCellLink );
188 // *** source range *** ---------------------------------------------------
190 Reference< XListEntrySink > xEntrySink( xCtrlModel, UNO_QUERY );
191 if( xEntrySink.is() )
193 Reference< XServiceInfo > xServInfo( xEntrySink->getListEntrySource(), UNO_QUERY );
194 if( xServInfo.is() && xServInfo->supportsService( CREATE_OUSTRING( SC_SERVICENAME_LISTSOURCE ) ) )
196 ScfPropertySet aSinkProp( xServInfo );
197 CellRangeAddress aApiRange;
198 if( aSinkProp.GetProperty( aApiRange, CREATE_OUSTRING( SC_UNONAME_CELLRANGE ) ) )
200 ScRange aSrcRange;
201 ScUnoConversion::FillScRange( aSrcRange, aApiRange );
202 if( (aSrcRange.aStart.Tab() == aSrcRange.aEnd.Tab()) && GetTabInfo().IsExportTab( aSrcRange.aStart.Tab() ) )
203 mxSrcRange = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, aSrcRange );
204 mnEntryCount = static_cast< sal_uInt16 >( aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1 );
210 void XclExpControlHelper::WriteFormula( XclExpStream& rStrm, const XclTokenArray& rTokArr ) const
212 sal_uInt16 nFmlaSize = rTokArr.GetSize();
213 rStrm << nFmlaSize << sal_uInt32( 0 );
214 rTokArr.WriteArray( rStrm );
215 if( nFmlaSize & 1 ) // pad to 16-bit
216 rStrm << sal_uInt8( 0 );
219 void XclExpControlHelper::WriteFormulaSubRec( XclExpStream& rStrm, sal_uInt16 nSubRecId, const XclTokenArray& rTokArr ) const
221 rStrm.StartRecord( nSubRecId, (rTokArr.GetSize() + 5) & ~1 );
222 WriteFormula( rStrm, rTokArr );
223 rStrm.EndRecord();
226 // ----------------------------------------------------------------------------
228 #if EXC_EXP_OCX_CTRL
230 XclExpOcxControlObj::XclExpOcxControlObj( const XclExpRoot& rRoot, Reference< XShape > xShape,
231 const String& rClassName, sal_uInt32 nStrmStart, sal_uInt32 nStrmSize ) :
232 XclObj( rRoot, EXC_OBJTYPE_PICTURE, true ),
233 XclExpControlHelper( rRoot ),
234 maClassName( rClassName ),
235 mnStrmStart( nStrmStart ),
236 mnStrmSize( nStrmSize )
238 ScfPropertySet aCtrlProp( XclControlHelper::GetControlModel( xShape ) );
240 // OBJ record flags
241 SetLocked( TRUE );
242 SetPrintable( aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "Printable" ) ) );
243 SetAutoFill( FALSE );
244 SetAutoLine( FALSE );
246 // fill DFF property set
247 XclEscherEx& rEscherEx = *pMsodrawing->GetEscherEx();
248 rEscherEx.OpenContainer( ESCHER_SpContainer );
249 rEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVESPT | SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_OLESHAPE );
250 Rectangle aDummyRect;
251 EscherPropertyContainer aPropOpt( rEscherEx, rEscherEx.QueryPicStream(), aDummyRect );
252 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 ); // bool field
253 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x08000040 );
254 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field
256 // #i51348# name of the control, may overwrite shape name
257 OUString aCtrlName;
258 if( aCtrlProp.GetProperty( aCtrlName, CREATE_OUSTRING( "Name" ) ) && (aCtrlName.getLength() > 0) )
259 aPropOpt.AddOpt( ESCHER_Prop_wzName, aCtrlName );
261 // meta file
262 //! TODO - needs check
263 Reference< XPropertySet > xShapePS( xShape, UNO_QUERY );
264 if( xShapePS.is() && aPropOpt.CreateGraphicProperties( xShapePS, CREATE_STRING( "MetaFile" ), sal_False ) )
266 sal_uInt32 nBlipId;
267 if( aPropOpt.GetOpt( ESCHER_Prop_pib, nBlipId ) )
268 aPropOpt.AddOpt( ESCHER_Prop_pictureId, nBlipId );
271 // write DFF property set to stream
272 aPropOpt.Commit( rEscherEx.GetStream() );
274 // anchor
275 if( SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape ) )
276 XclExpDffAnchor( rRoot, *pSdrObj ).WriteData( rEscherEx );
277 rEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record
278 rEscherEx.CloseContainer(); // ESCHER_SpContainer
280 pMsodrawing->UpdateStopPos();
282 // spreadsheet links
283 ConvertSheetLinks( xShape );
286 void XclExpOcxControlObj::WriteSubRecs( XclExpStream& rStrm )
288 // OBJCF - clipboard format
289 rStrm.StartRecord( EXC_ID_OBJCF, 2 );
290 rStrm << sal_uInt16( 2 );
291 rStrm.EndRecord();
293 // OBJFLAGS
294 rStrm.StartRecord( EXC_ID_OBJFLAGS, 2 );
295 rStrm << sal_uInt16( 0x0031 );
296 rStrm.EndRecord();
298 // OBJPICTFMLA
299 XclExpString aClass( maClassName );
300 sal_uInt16 nClassNameSize = static_cast< sal_uInt16 >( aClass.GetSize() );
301 sal_uInt16 nClassNamePad = nClassNameSize & 1;
302 sal_uInt16 nFirstPartSize = 12 + nClassNameSize + nClassNamePad;
304 const XclTokenArray* pCellLink = GetCellLinkTokArr();
305 sal_uInt16 nCellLinkSize = pCellLink ? ((pCellLink->GetSize() + 7) & 0xFFFE) : 0;
307 const XclTokenArray* pSrcRange = GetSourceRangeTokArr();
308 sal_uInt16 nSrcRangeSize = pSrcRange ? ((pSrcRange->GetSize() + 7) & 0xFFFE) : 0;
310 sal_uInt16 nPictFmlaSize = nFirstPartSize + nCellLinkSize + nSrcRangeSize + 18;
311 rStrm.StartRecord( EXC_ID_OBJPICTFMLA, nPictFmlaSize );
313 rStrm << sal_uInt16( nFirstPartSize ) // size of first part
314 << sal_uInt16( 5 ) // formula size
315 << sal_uInt32( 0 ) // unknown ID
316 << sal_uInt8( 0x02 ) << sal_uInt32( 0 ) // tTbl token with unknown ID
317 << sal_uInt8( 3 ) // pad to word
318 << aClass; // "Forms.***.1"
319 rStrm.WriteZeroBytes( nClassNamePad ); // pad to word
320 rStrm << mnStrmStart // start in 'Ctls' stream
321 << mnStrmSize // size in 'Ctls' stream
322 << sal_uInt32( 0 ); // class ID size
323 // cell link
324 rStrm << nCellLinkSize;
325 if( pCellLink )
326 WriteFormula( rStrm, *pCellLink );
327 // list source range
328 rStrm << nSrcRangeSize;
329 if( pSrcRange )
330 WriteFormula( rStrm, *pSrcRange );
332 rStrm.EndRecord();
335 #else
337 XclExpTbxControlObj::XclExpTbxControlObj( const XclExpRoot& rRoot, Reference< XShape > xShape ) :
338 XclObj( rRoot, EXC_OBJTYPE_UNKNOWN, true ),
339 XclMacroHelper( rRoot ),
340 mnHeight( 0 ),
341 mnState( 0 ),
342 mnLineCount( 0 ),
343 mnSelEntry( 0 ),
344 mnScrollValue( 0 ),
345 mnScrollMin( 0 ),
346 mnScrollMax( 100 ),
347 mnScrollStep( 1 ),
348 mnScrollPage( 10 ),
349 mbFlatButton( false ),
350 mbFlatBorder( false ),
351 mbMultiSel( false ),
352 mbScrollHor( false )
354 namespace FormCompType = ::com::sun::star::form::FormComponentType;
355 namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect;
356 namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation;
358 ScfPropertySet aCtrlProp( XclControlHelper::GetControlModel( xShape ) );
359 if( !xShape.is() || !aCtrlProp.Is() )
360 return;
362 mnHeight = xShape->getSize().Height;
363 if( mnHeight <= 0 )
364 return;
366 // control type
367 sal_Int16 nClassId = 0;
368 if( aCtrlProp.GetProperty( nClassId, CREATE_OUSTRING( "ClassId" ) ) )
370 switch( nClassId )
372 case FormCompType::COMMANDBUTTON: mnObjType = EXC_OBJTYPE_BUTTON; meEventType = EXC_TBX_EVENT_ACTION; break;
373 case FormCompType::RADIOBUTTON: mnObjType = EXC_OBJTYPE_OPTIONBUTTON; meEventType = EXC_TBX_EVENT_ACTION; break;
374 case FormCompType::CHECKBOX: mnObjType = EXC_OBJTYPE_CHECKBOX; meEventType = EXC_TBX_EVENT_ACTION; break;
375 case FormCompType::LISTBOX: mnObjType = EXC_OBJTYPE_LISTBOX; meEventType = EXC_TBX_EVENT_CHANGE; break;
376 case FormCompType::COMBOBOX: mnObjType = EXC_OBJTYPE_DROPDOWN; meEventType = EXC_TBX_EVENT_CHANGE; break;
377 case FormCompType::GROUPBOX: mnObjType = EXC_OBJTYPE_GROUPBOX; meEventType = EXC_TBX_EVENT_MOUSE; break;
378 case FormCompType::FIXEDTEXT: mnObjType = EXC_OBJTYPE_LABEL; meEventType = EXC_TBX_EVENT_MOUSE; break;
379 case FormCompType::SCROLLBAR: mnObjType = EXC_OBJTYPE_SCROLLBAR; meEventType = EXC_TBX_EVENT_VALUE; break;
380 case FormCompType::SPINBUTTON: mnObjType = EXC_OBJTYPE_SPIN; meEventType = EXC_TBX_EVENT_VALUE; break;
383 if( mnObjType == EXC_OBJTYPE_UNKNOWN )
384 return;
386 // OBJ record flags
387 SetLocked( TRUE );
388 SetPrintable( aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "Printable" ) ) );
389 SetAutoFill( FALSE );
390 SetAutoLine( FALSE );
392 // fill DFF property set
393 XclEscherEx& rEscherEx = *pMsodrawing->GetEscherEx();
394 rEscherEx.OpenContainer( ESCHER_SpContainer );
395 rEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT );
396 EscherPropertyContainer aPropOpt;
397 bool bVisible = aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "EnableVisible" ) );
398 aPropOpt.AddOpt( ESCHER_Prop_fPrint, bVisible ? 0x00080000 : 0x00080002 ); // visible flag
400 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01000100 ); // bool field
401 aPropOpt.AddOpt( ESCHER_Prop_lTxid, 0 ); // Text ID
402 aPropOpt.AddOpt( ESCHER_Prop_WrapText, 0x00000001 );
403 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x001A0008 ); // bool field
404 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00100000 ); // bool field
405 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field
407 // #i51348# name of the control, may overwrite shape name
408 OUString aCtrlName;
409 if( aCtrlProp.GetProperty( aCtrlName, CREATE_OUSTRING( "Name" ) ) && (aCtrlName.getLength() > 0) )
410 aPropOpt.AddOpt( ESCHER_Prop_wzName, aCtrlName );
412 // write DFF property set to stream
413 aPropOpt.Commit( rEscherEx.GetStream() );
415 // anchor
416 if( SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape ) )
417 XclExpDffAnchor( rRoot, *pSdrObj ).WriteData( rEscherEx );
418 rEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record
419 pMsodrawing->UpdateStopPos();
421 // control label
422 OUString aString;
423 if( aCtrlProp.GetProperty( aString, CREATE_OUSTRING( "Label" ) ) )
425 /* Be sure to construct the MSODRAWING record containing the
426 ClientTextbox atom after the base OBJ's MSODRAWING record data is
427 completed. */
428 pClientTextbox = new XclMsodrawing( GetRoot() );
429 pClientTextbox->GetEscherEx()->AddAtom( 0, ESCHER_ClientTextbox ); // TXO record
430 pClientTextbox->UpdateStopPos();
432 sal_uInt16 nXclFont = EXC_FONT_APP;
433 if( aString.getLength() > 0 )
435 XclFontData aFontData;
436 GetFontPropSetHelper().ReadFontProperties( aFontData, aCtrlProp, EXC_FONTPROPSET_CONTROL );
437 if( (aFontData.maName.Len() > 0) && (aFontData.mnHeight > 0) )
438 nXclFont = GetFontBuffer().Insert( aFontData, EXC_COLOR_CTRLTEXT );
441 pTxo = new XclTxo( aString, nXclFont );
442 pTxo->SetHorAlign( (mnObjType == EXC_OBJTYPE_BUTTON) ? EXC_OBJ_HOR_CENTER : EXC_OBJ_HOR_LEFT );
443 pTxo->SetVerAlign( EXC_OBJ_VER_CENTER );
446 rEscherEx.CloseContainer(); // ESCHER_SpContainer
448 // other properties
449 aCtrlProp.GetProperty( mnLineCount, CREATE_OUSTRING( "LineCount" ) );
451 // border style
452 sal_Int16 nApiButton = AwtVisualEffect::LOOK3D;
453 sal_Int16 nApiBorder = AwtVisualEffect::LOOK3D;
454 switch( nClassId )
456 case FormCompType::LISTBOX:
457 case FormCompType::COMBOBOX:
458 aCtrlProp.GetProperty( nApiBorder, CREATE_OUSTRING( "Border" ) );
459 break;
460 case FormCompType::CHECKBOX:
461 case FormCompType::RADIOBUTTON:
462 aCtrlProp.GetProperty( nApiButton, CREATE_OUSTRING( "VisualEffect" ) );
463 nApiBorder = AwtVisualEffect::NONE;
464 break;
465 // Push button cannot be set to flat in Excel
466 case FormCompType::COMMANDBUTTON:
467 nApiBorder = AwtVisualEffect::LOOK3D;
468 break;
469 // Label does not support a border in Excel
470 case FormCompType::FIXEDTEXT:
471 nApiBorder = AwtVisualEffect::NONE;
472 break;
473 /* Scroll bar and spin button have a "Border" property, but it is
474 really used for a border, and not for own 3D/flat look (#i34712#). */
475 case FormCompType::SCROLLBAR:
476 case FormCompType::SPINBUTTON:
477 nApiButton = AwtVisualEffect::LOOK3D;
478 nApiBorder = AwtVisualEffect::NONE;
479 break;
480 // Group box does not support flat style (#i34712#)
481 case FormCompType::GROUPBOX:
482 nApiBorder = AwtVisualEffect::LOOK3D;
483 break;
485 mbFlatButton = nApiButton != AwtVisualEffect::LOOK3D;
486 mbFlatBorder = nApiBorder != AwtVisualEffect::LOOK3D;
488 // control state
489 sal_Int16 nApiState = 0;
490 if( aCtrlProp.GetProperty( nApiState, CREATE_OUSTRING( "State" ) ) )
492 switch( nApiState )
494 case 0: mnState = EXC_OBJ_CHECKBOX_UNCHECKED; break;
495 case 1: mnState = EXC_OBJ_CHECKBOX_CHECKED; break;
496 case 2: mnState = EXC_OBJ_CHECKBOX_TRISTATE; break;
500 // special control contents
501 switch( nClassId )
503 case FormCompType::LISTBOX:
505 mbMultiSel = aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "MultiSelection" ) );
506 Sequence< sal_Int16 > aSelection;
507 if( aCtrlProp.GetProperty( aSelection, CREATE_OUSTRING( "SelectedItems" ) ) )
509 sal_Int32 nLen = aSelection.getLength();
510 if( nLen > 0 )
512 mnSelEntry = aSelection[ 0 ] + 1;
513 maMultiSel.resize( nLen );
514 const sal_Int16* pnBegin = aSelection.getConstArray();
515 ::std::copy( pnBegin, pnBegin + nLen, maMultiSel.begin() );
519 // convert listbox with dropdown button to Excel dropdown
520 if( aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "Dropdown" ) ) )
521 mnObjType = EXC_OBJTYPE_DROPDOWN;
523 break;
525 case FormCompType::COMBOBOX:
527 Sequence< OUString > aStringList;
528 OUString aDefText;
529 if( aCtrlProp.GetProperty( aStringList, CREATE_OUSTRING( "StringItemList" ) ) &&
530 aCtrlProp.GetProperty( aDefText, CREATE_OUSTRING( "Text" ) ) &&
531 aStringList.getLength() && aDefText.getLength() )
533 const OUString* pBegin = aStringList.getConstArray();
534 const OUString* pEnd = pBegin + aStringList.getLength();
535 const OUString* pString = ::std::find( pBegin, pEnd, aDefText );
536 if( pString != pEnd )
537 mnSelEntry = static_cast< sal_Int16 >( pString - pBegin + 1 ); // 1-based
538 if( mnSelEntry > 0 )
539 maMultiSel.resize( 1, mnSelEntry - 1 );
542 // convert combobox without dropdown button to Excel listbox
543 if( !aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "Dropdown" ) ) )
544 mnObjType = EXC_OBJTYPE_LISTBOX;
546 break;
548 case FormCompType::SCROLLBAR:
550 sal_Int32 nApiValue = 0;
551 if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "ScrollValueMin" ) ) )
552 mnScrollMin = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
553 if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "ScrollValueMax" ) ) )
554 mnScrollMax = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, EXC_OBJ_SCROLLBAR_MIN );
555 if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "ScrollValue" ) ) )
556 mnScrollValue = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, mnScrollMax );
557 if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "LineIncrement" ) ) )
558 mnScrollStep = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
559 if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "BlockIncrement" ) ) )
560 mnScrollPage = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
561 if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "Orientation" ) ) )
562 mbScrollHor = nApiValue == AwtScrollOrient::HORIZONTAL;
564 break;
566 case FormCompType::SPINBUTTON:
568 sal_Int32 nApiValue = 0;
569 if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "SpinValueMin" ) ) )
570 mnScrollMin = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
571 if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "SpinValueMax" ) ) )
572 mnScrollMax = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, EXC_OBJ_SCROLLBAR_MAX );
573 if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "SpinValue" ) ) )
574 mnScrollValue = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, mnScrollMax );
575 if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "SpinIncrement" ) ) )
576 mnScrollStep = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
577 if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "Orientation" ) ) )
578 mbScrollHor = nApiValue == AwtScrollOrient::HORIZONTAL;
580 break;
583 // spreadsheet links
584 ConvertSheetLinks( xShape );
587 bool XclExpTbxControlObj::SetMacroLink( const ScriptEventDescriptor& rEvent )
589 return XclMacroHelper::SetMacroLink( rEvent, meEventType );
591 String aMacroName = XclControlHelper::ExtractFromMacroDescriptor( rEvent, meEventType );
592 if( aMacroName.Len() )
594 sal_uInt16 nExtSheet = GetLocalLinkManager().FindExtSheet( EXC_EXTSH_OWNDOC );
595 sal_uInt16 nNameIdx = GetNameManager().InsertMacroCall( aMacroName, true, false );
596 mxMacroLink = GetFormulaCompiler().CreateNameXFormula( nExtSheet, nNameIdx );
597 return true;
599 return false;
603 void XclExpTbxControlObj::WriteSubRecs( XclExpStream& rStrm )
605 switch( mnObjType )
607 // *** Push buttons, labels ***
609 case EXC_OBJTYPE_BUTTON:
610 case EXC_OBJTYPE_LABEL:
611 // ftMacro - macro link
612 WriteMacroSubRec( rStrm );
613 break;
615 // *** Check boxes, option buttons ***
617 case EXC_OBJTYPE_CHECKBOX:
618 case EXC_OBJTYPE_OPTIONBUTTON:
620 // ftCbls - box properties
621 sal_uInt16 nStyle = 0;
622 ::set_flag( nStyle, EXC_OBJ_CHECKBOX_FLAT, mbFlatButton );
624 rStrm.StartRecord( EXC_ID_OBJCBLS, 12 );
625 rStrm << mnState;
626 rStrm.WriteZeroBytes( 8 );
627 rStrm << nStyle;
628 rStrm.EndRecord();
630 // ftMacro - macro link
631 WriteMacroSubRec( rStrm );
632 // ftCblsFmla subrecord - cell link
633 WriteCellLinkSubRec( rStrm, EXC_ID_OBJCBLSFMLA );
635 // ftCblsData subrecord - box properties, again
636 rStrm.StartRecord( EXC_ID_OBJCBLS, 8 );
637 rStrm << mnState;
638 rStrm.WriteZeroBytes( 4 );
639 rStrm << nStyle;
640 rStrm.EndRecord();
642 break;
644 // *** List boxes, combo boxes ***
646 case EXC_OBJTYPE_LISTBOX:
647 case EXC_OBJTYPE_DROPDOWN:
649 sal_uInt16 nEntryCount = GetSourceEntryCount();
651 // ftSbs subrecord - Scroll bars
652 sal_Int32 nLineHeight = XclTools::GetHmmFromTwips( 200 ); // always 10pt
653 if( mnObjType == EXC_OBJTYPE_LISTBOX )
654 mnLineCount = static_cast< sal_uInt16 >( mnHeight / nLineHeight );
655 mnScrollValue = 0;
656 mnScrollMin = 0;
657 sal_uInt16 nInvisLines = (nEntryCount >= mnLineCount) ? (nEntryCount - mnLineCount) : 0;
658 mnScrollMax = limit_cast< sal_uInt16 >( nInvisLines, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
659 mnScrollStep = 1;
660 mnScrollPage = limit_cast< sal_uInt16 >( mnLineCount, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
661 mbScrollHor = false;
662 WriteSbs( rStrm );
664 // ftMacro - macro link
665 WriteMacroSubRec( rStrm );
666 // ftSbsFmla subrecord - cell link
667 WriteCellLinkSubRec( rStrm, EXC_ID_OBJSBSFMLA );
669 // ftLbsData - source data range and box properties
670 sal_uInt16 nStyle = 0;
671 ::insert_value( nStyle, mbMultiSel ? EXC_OBJ_LISTBOX_MULTI : EXC_OBJ_LISTBOX_SINGLE, 4, 2 );
672 ::set_flag( nStyle, EXC_OBJ_LISTBOX_FLAT, mbFlatBorder );
674 rStrm.StartRecord( EXC_ID_OBJLBSDATA, 0 );
676 if( const XclTokenArray* pSrcRange = GetSourceRangeTokArr() )
678 rStrm << static_cast< sal_uInt16 >( (pSrcRange->GetSize() + 7) & 0xFFFE );
679 WriteFormula( rStrm, *pSrcRange );
681 else
682 rStrm << sal_uInt16( 0 );
684 rStrm << nEntryCount << mnSelEntry << nStyle << sal_uInt16( 0 );
685 if( mnObjType == EXC_OBJTYPE_LISTBOX )
687 if( nEntryCount )
689 ScfUInt8Vec aSelEx( nEntryCount, 0 );
690 for( ScfInt16Vec::const_iterator aIt = maMultiSel.begin(), aEnd = maMultiSel.end(); aIt != aEnd; ++aIt )
691 if( *aIt < nEntryCount )
692 aSelEx[ *aIt ] = 1;
693 rStrm.Write( &aSelEx[ 0 ], aSelEx.size() );
696 else if( mnObjType == EXC_OBJTYPE_DROPDOWN )
698 rStrm << sal_uInt16( 0 ) << mnLineCount;
701 rStrm.EndRecord();
703 break;
705 // *** Spin buttons, scrollbars ***
707 case EXC_OBJTYPE_SPIN:
708 case EXC_OBJTYPE_SCROLLBAR:
710 // ftSbs subrecord - scroll bars
711 WriteSbs( rStrm );
712 // ftMacro - macro link
713 WriteMacroSubRec( rStrm );
714 // ftSbsFmla subrecord - cell link
715 WriteCellLinkSubRec( rStrm, EXC_ID_OBJSBSFMLA );
717 break;
719 // *** Group boxes ***
721 case EXC_OBJTYPE_GROUPBOX:
723 // ftMacro - macro link
724 WriteMacroSubRec( rStrm );
726 // ftGboData subrecord - group box properties
727 sal_uInt16 nStyle = 0;
728 ::set_flag( nStyle, EXC_OBJ_GROUPBOX_FLAT, mbFlatBorder );
730 rStrm.StartRecord( EXC_ID_OBJGBODATA, 6 );
731 rStrm << sal_uInt32( 0 )
732 << nStyle;
733 rStrm.EndRecord();
735 break;
739 void XclExpTbxControlObj::WriteCellLinkSubRec( XclExpStream& rStrm, sal_uInt16 nSubRecId )
741 if( const XclTokenArray* pCellLink = GetCellLinkTokArr() )
742 WriteFormulaSubRec( rStrm, nSubRecId, *pCellLink );
745 void XclExpTbxControlObj::WriteSbs( XclExpStream& rStrm )
747 sal_uInt16 nOrient = 0;
748 ::set_flag( nOrient, EXC_OBJ_SCROLLBAR_HOR, mbScrollHor );
749 sal_uInt16 nStyle = EXC_OBJ_SCROLLBAR_DEFFLAGS;
750 ::set_flag( nStyle, EXC_OBJ_SCROLLBAR_FLAT, mbFlatButton );
752 rStrm.StartRecord( EXC_ID_OBJSBS, 20 );
753 rStrm << sal_uInt32( 0 ) // reserved
754 << mnScrollValue // thumb position
755 << mnScrollMin // thumb min pos
756 << mnScrollMax // thumb max pos
757 << mnScrollStep // line increment
758 << mnScrollPage // page increment
759 << nOrient // 0 = vertical, 1 = horizontal
760 << sal_uInt16( 15 ) // thumb width
761 << nStyle; // flags/style
762 rStrm.EndRecord();
765 #endif
768 // ----------------------------------------------------------------------------
770 XclExpChartObj::XclExpChartObj( const XclExpRoot& rRoot, Reference< XShape > xShape ) :
771 XclObj( rRoot, EXC_OBJTYPE_CHART ),
772 XclExpRoot( rRoot )
774 // create the MSODRAWING record contents for the chart object
775 XclEscherEx& rEscherEx = *pMsodrawing->GetEscherEx();
776 rEscherEx.OpenContainer( ESCHER_SpContainer );
777 rEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT );
778 EscherPropertyContainer aPropOpt;
779 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01040104 );
780 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 );
781 aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x0800004E );
782 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x0800004D );
783 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00110010 );
784 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x0800004D );
785 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080008 );
786 aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x00020000 );
787 aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080000 );
788 aPropOpt.Commit( rEscherEx.GetStream() );
790 // client anchor
791 SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape );
792 if( pSdrObj )
793 XclExpDffAnchor( rRoot, *pSdrObj ).WriteData( rEscherEx );
795 // client data (the following OBJ record)
796 rEscherEx.AddAtom( 0, ESCHER_ClientData );
797 rEscherEx.CloseContainer(); // ESCHER_SpContainer
798 pMsodrawing->UpdateStopPos();
800 // load the chart OLE object
801 if( SdrOle2Obj* pSdrOleObj = dynamic_cast< SdrOle2Obj* >( pSdrObj ) )
802 svt::EmbeddedObjectRef::TryRunningState( pSdrOleObj->GetObjRef() );
804 // create the chart substream object
805 ScfPropertySet aShapeProp( xShape );
806 Reference< XModel > xModel;
807 aShapeProp.GetProperty( xModel, CREATE_OUSTRING( "Model" ) );
808 ::com::sun::star::awt::Rectangle aBoundRect;
809 aShapeProp.GetProperty( aBoundRect, CREATE_OUSTRING( "BoundRect" ) );
810 Size aSize( aBoundRect.Width, aBoundRect.Height );
811 mxChart.reset( new XclExpChart( rRoot, xModel, aSize ) );
814 XclExpChartObj::~XclExpChartObj()
818 void XclExpChartObj::Save( XclExpStream& rStrm )
820 // content of OBJ record
821 XclObj::Save( rStrm );
822 // chart substream
823 mxChart->Save( rStrm );
826 // ============================================================================
828 XclExpNote::XclExpNote( const XclExpRoot& rRoot, const ScAddress& rScPos,
829 const ScPostIt* pScNote, const String& rAddText ) :
830 XclExpRecord( EXC_ID_NOTE ),
831 maScPos( rScPos ),
832 mnObjId( EXC_OBJ_INVALID_ID ),
833 mbVisible( pScNote && pScNote->IsCaptionShown() )
835 // get the main note text
836 String aNoteText;
837 if( pScNote )
838 aNoteText = pScNote->GetText();
839 // append additional text
840 ScGlobal::AddToken( aNoteText, rAddText, '\n', 2 );
841 maOrigNoteText = aNoteText;
843 // initialize record dependent on BIFF type
844 switch( rRoot.GetBiff() )
846 case EXC_BIFF5:
847 maNoteText = ByteString( aNoteText, rRoot.GetTextEncoding() );
848 break;
850 case EXC_BIFF8:
852 // TODO: additional text
853 if( pScNote )
854 if( SdrCaptionObj* pCaption = pScNote->GetCaption() )
855 if( const OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() )
856 mnObjId = rRoot.GetOldRoot().pObjRecs->Add( new XclObjComment( rRoot, pCaption->GetLogicRect(), pOPO->GetTextObject(), pCaption, mbVisible ) );
858 SetRecSize( 9 + maAuthor.GetSize() );
860 break;
862 default: DBG_ERROR_BIFF();
866 void XclExpNote::Save( XclExpStream& rStrm )
868 switch( rStrm.GetRoot().GetBiff() )
870 case EXC_BIFF5:
872 // write the NOTE record directly, there may be the need to create more than one
873 const sal_Char* pcBuffer = maNoteText.GetBuffer();
874 sal_uInt16 nCharsLeft = static_cast< sal_uInt16 >( maNoteText.Len() );
876 while( nCharsLeft )
878 sal_uInt16 nWriteChars = ::std::min( nCharsLeft, EXC_NOTE5_MAXLEN );
880 rStrm.StartRecord( EXC_ID_NOTE, 6 + nWriteChars );
881 if( pcBuffer == maNoteText.GetBuffer() )
883 // first record: row, col, length of complete text
884 rStrm << static_cast< sal_uInt16 >( maScPos.Row() )
885 << static_cast< sal_uInt16 >( maScPos.Col() )
886 << nCharsLeft; // still contains full length
888 else
890 // next records: -1, 0, length of current text segment
891 rStrm << sal_uInt16( 0xFFFF )
892 << sal_uInt16( 0 )
893 << nWriteChars;
895 rStrm.Write( pcBuffer, nWriteChars );
896 rStrm.EndRecord();
898 pcBuffer += nWriteChars;
899 nCharsLeft = nCharsLeft - nWriteChars;
902 break;
904 case EXC_BIFF8:
905 if( mnObjId != EXC_OBJ_INVALID_ID )
906 XclExpRecord::Save( rStrm );
907 break;
909 default: DBG_ERROR_BIFF();
914 void XclExpNote::WriteBody( XclExpStream& rStrm )
916 // BIFF5/BIFF7 is written separately
917 DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 );
919 sal_uInt16 nFlags = 0;
920 ::set_flag( nFlags, EXC_NOTE_VISIBLE, mbVisible );
922 rStrm << static_cast< sal_uInt16 >( maScPos.Row() )
923 << static_cast< sal_uInt16 >( maScPos.Col() )
924 << nFlags
925 << mnObjId
926 << maAuthor
927 << sal_uInt8( 0 );
930 void XclExpNote::WriteXml( sal_Int32 nAuthorId, XclExpXmlStream& rStrm )
932 sax_fastparser::FSHelperPtr rComments = rStrm.GetCurrentStream();
934 rComments->startElement( XML_comment,
935 XML_ref, XclXmlUtils::ToOString( maScPos ).getStr(),
936 XML_authorId, OString::valueOf( nAuthorId ).getStr(),
937 // OOXTODO: XML_guid,
938 FSEND );
939 rComments->startElement( XML_text, FSEND );
940 // OOXTODO: phoneticPr, rPh, r
941 rComments->startElement( XML_t, FSEND );
942 rComments->writeEscaped( XclXmlUtils::ToOUString( maOrigNoteText ) );
943 rComments->endElement ( XML_t );
944 rComments->endElement( XML_text );
945 rComments->endElement( XML_comment );
948 // ============================================================================
950 XclMacroHelper::XclMacroHelper( const XclExpRoot& rRoot ) :
951 XclExpControlHelper( rRoot )
955 XclMacroHelper::~XclMacroHelper()
959 void XclMacroHelper::WriteMacroSubRec( XclExpStream& rStrm )
961 if( mxMacroLink.is() )
962 WriteFormulaSubRec( rStrm, EXC_ID_OBJMACRO, *mxMacroLink );
965 bool
966 XclMacroHelper::SetMacroLink( const ScriptEventDescriptor& rEvent, const XclTbxEventType& nEventType )
968 String aMacroName = XclControlHelper::ExtractFromMacroDescriptor( rEvent, nEventType );
969 if( aMacroName.Len() )
971 return SetMacroLink( aMacroName );
973 return false;
976 bool
977 XclMacroHelper::SetMacroLink( const String& rMacroName )
979 OSL_TRACE("SetMacroLink( macroname:=%s )", rtl::OUStringToOString( rMacroName, RTL_TEXTENCODING_UTF8 ).getStr() );
980 if( rMacroName.Len() )
982 sal_uInt16 nExtSheet = GetLocalLinkManager().FindExtSheet( EXC_EXTSH_OWNDOC );
983 sal_uInt16 nNameIdx = GetNameManager().InsertMacroCall( rMacroName, true, false );
984 mxMacroLink = GetFormulaCompiler().CreateNameXFormula( nExtSheet, nNameIdx );
985 return true;
987 return false;
990 XclExpShapeObj::XclExpShapeObj( const XclExpRoot& rRoot, ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape ) :
991 XclObjAny( rRoot ),
992 XclMacroHelper( rRoot )
994 if( SdrObject* pSdrObj = ::GetSdrObjectFromXShape( xShape ) )
996 ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pSdrObj );
997 if ( pInfo && pInfo->GetMacro().getLength() )
998 SetMacroLink( XclControlHelper::GetXclMacroName( pInfo->GetMacro() ) );
1002 XclExpShapeObj::~XclExpShapeObj()
1006 void XclExpShapeObj::WriteSubRecs( XclExpStream& rStrm )
1008 XclObjAny::WriteSubRecs( rStrm );
1009 WriteMacroSubRec( rStrm );
1012 // ============================================================================
1014 XclExpComments::XclExpComments( SCTAB nTab, XclExpRecordList< XclExpNote >& rNotes )
1015 : mnTab( nTab ), mrNotes( rNotes )
1019 struct OUStringLess : public std::binary_function<OUString, OUString, bool>
1021 bool operator()(const OUString& x, const OUString& y) const
1023 return x.compareTo( y ) <= 0;
1027 void XclExpComments::SaveXml( XclExpXmlStream& rStrm )
1029 if( mrNotes.IsEmpty() )
1030 return;
1032 sax_fastparser::FSHelperPtr rComments = rStrm.CreateOutputStream(
1033 XclXmlUtils::GetStreamName( "xl/", "comments", mnTab + 1 ),
1034 XclXmlUtils::GetStreamName( "../", "comments", mnTab + 1 ),
1035 rStrm.GetCurrentStream()->getOutputStream(),
1036 "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
1037 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments" );
1038 rStrm.PushStream( rComments );
1040 rComments->startElement( XML_comments,
1041 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
1042 FSEND );
1043 rComments->startElement( XML_authors, FSEND );
1045 typedef std::set< OUString, OUStringLess > Authors;
1046 Authors aAuthors;
1048 size_t nNotes = mrNotes.GetSize();
1049 for( size_t i = 0; i < nNotes; ++i )
1051 aAuthors.insert( XclXmlUtils::ToOUString( mrNotes.GetRecord( i )->GetAuthor() ) );
1054 for( Authors::const_iterator b = aAuthors.begin(), e = aAuthors.end(); b != e; ++b )
1056 rComments->startElement( XML_author, FSEND );
1057 rComments->writeEscaped( *b );
1058 rComments->endElement( XML_author );
1061 rComments->endElement( XML_authors );
1062 rComments->startElement( XML_commentList, FSEND );
1064 for( size_t i = 0; i < nNotes; ++i )
1066 XclExpNoteList::RecordRefType xNote = mrNotes.GetRecord( i );
1067 Authors::const_iterator aAuthor = aAuthors.find(
1068 XclXmlUtils::ToOUString( xNote->GetAuthor() ) );
1069 sal_Int32 nAuthorId = distance( aAuthors.begin(), aAuthor );
1070 xNote->WriteXml( nAuthorId, rStrm );
1073 rComments->endElement( XML_commentList );
1074 rComments->endElement( XML_comments );
1076 rStrm.PopStream();
1079 // ============================================================================