1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <xeescher.hxx>
23 #include <com/sun/star/lang/XServiceInfo.hpp>
24 #include <com/sun/star/form/FormComponentType.hpp>
25 #include <com/sun/star/awt/VisualEffect.hpp>
26 #include <com/sun/star/awt/ScrollBarOrientation.hpp>
27 #include <com/sun/star/awt/XControlModel.hpp>
28 #include <com/sun/star/drawing/XShape.hpp>
29 #include <com/sun/star/form/binding/XBindableValue.hpp>
30 #include <com/sun/star/form/binding/XListEntrySink.hpp>
31 #include <com/sun/star/awt/Size.hpp>
32 #include <com/sun/star/chart/XChartDocument.hpp>
35 #include <vcl/BitmapReadAccess.hxx>
36 #include <svx/svdoole2.hxx>
37 #include <svx/svdocapt.hxx>
38 #include <editeng/outlobj.hxx>
39 #include <unotools/tempfile.hxx>
40 #include <unotools/ucbstreamhelper.hxx>
41 #include <unotools/securityoptions.hxx>
42 #include <svtools/embedhlp.hxx>
44 #include <unonames.hxx>
45 #include <convuno.hxx>
48 #include <fapihelper.hxx>
49 #include <xcl97esc.hxx>
50 #include <xechart.hxx>
51 #include <xeformula.hxx>
52 #include <xehelper.hxx>
55 #include <xestyle.hxx>
57 #include <xltools.hxx>
58 #include <userdat.hxx>
59 #include <drwlayer.hxx>
60 #include <svl/itemset.hxx>
61 #include <svx/sdtaitm.hxx>
62 #include <document.hxx>
63 #include <svx/xfillit0.hxx>
64 #include <svx/xflclit.hxx>
66 #include <comphelper/sequence.hxx>
67 #include <oox/token/tokens.hxx>
68 #include <oox/token/relationship.hxx>
69 #include <oox/export/drawingml.hxx>
70 #include <oox/export/chartexport.hxx>
71 #include <oox/export/utils.hxx>
72 #include <oox/token/namespaces.hxx>
73 #include <oox/export/vmlexport.hxx>
76 using namespace com::sun::star
;
77 using ::com::sun::star::uno::UNO_QUERY
;
78 using ::com::sun::star::uno::Reference
;
79 using ::com::sun::star::uno::Sequence
;
80 using ::com::sun::star::lang::XServiceInfo
;
81 using ::com::sun::star::beans::XPropertySet
;
82 using ::com::sun::star::drawing::XShape
;
83 using ::com::sun::star::drawing::XShapes
;
84 using ::com::sun::star::awt::XControlModel
;
85 using ::com::sun::star::form::binding::XBindableValue
;
86 using ::com::sun::star::form::binding::XListEntrySink
;
87 using ::com::sun::star::script::ScriptEventDescriptor
;
88 using ::com::sun::star::table::CellAddress
;
89 using ::com::sun::star::table::CellRangeAddress
;
90 using ::oox::drawingml::DrawingML
;
91 using ::oox::drawingml::ChartExport
;
97 const char *ToHorizAlign( SdrTextHorzAdjust eAdjust
)
101 case SDRTEXTHORZADJUST_CENTER
:
103 case SDRTEXTHORZADJUST_RIGHT
:
105 case SDRTEXTHORZADJUST_BLOCK
:
107 case SDRTEXTHORZADJUST_LEFT
:
113 const char *ToVertAlign( SdrTextVertAdjust eAdjust
)
117 case SDRTEXTVERTADJUST_CENTER
:
119 case SDRTEXTVERTADJUST_BOTTOM
:
121 case SDRTEXTVERTADJUST_BLOCK
:
123 case SDRTEXTVERTADJUST_TOP
:
129 void lcl_WriteAnchorVertex( sax_fastparser::FSHelperPtr
const & rComments
, const tools::Rectangle
&aRect
)
131 rComments
->startElement(FSNS(XML_xdr
, XML_col
));
132 rComments
->writeEscaped( OUString::number( aRect
.Left() ) );
133 rComments
->endElement( FSNS( XML_xdr
, XML_col
) );
134 rComments
->startElement(FSNS(XML_xdr
, XML_colOff
));
135 rComments
->writeEscaped( OUString::number( aRect
.Top() ) );
136 rComments
->endElement( FSNS( XML_xdr
, XML_colOff
) );
137 rComments
->startElement(FSNS(XML_xdr
, XML_row
));
138 rComments
->writeEscaped( OUString::number( aRect
.Right() ) );
139 rComments
->endElement( FSNS( XML_xdr
, XML_row
) );
140 rComments
->startElement(FSNS(XML_xdr
, XML_rowOff
));
141 rComments
->writeEscaped( OUString::number( aRect
.Bottom() ) );
142 rComments
->endElement( FSNS( XML_xdr
, XML_rowOff
) );
145 tools::Long
lcl_hmm2output(tools::Long value
, bool bInEMU
)
147 return o3tl::convert(value
, o3tl::Length::mm100
, bInEMU
? o3tl::Length::emu
: o3tl::Length::px
);
150 void lcl_GetFromTo( const XclExpRoot
& rRoot
, const tools::Rectangle
&aRect
, sal_Int32 nTab
, tools::Rectangle
&aFrom
, tools::Rectangle
&aTo
, bool bInEMU
= false )
152 sal_Int32 nCol
= 0, nRow
= 0;
153 sal_Int32 nColOff
= 0, nRowOff
= 0;
155 const bool bRTL
= rRoot
.GetDoc().IsNegativePage( nTab
);
160 tools::Rectangle r
= rRoot
.GetDoc().GetMMRect( nCol
,nRow
,nCol
,nRow
,nTab
);
161 if( r
.Left() <= aRect
.Left() )
164 nColOff
= aRect
.Left() - r
.Left();
166 if( r
.Top() <= aRect
.Top() )
169 nRowOff
= aRect
.Top() - r
.Top();
171 if( r
.Left() > aRect
.Left() && r
.Top() > aRect
.Top() )
173 aFrom
= tools::Rectangle( nCol
-1, lcl_hmm2output( nColOff
, bInEMU
),
174 nRow
-1, lcl_hmm2output( nRowOff
, bInEMU
) );
183 tools::Rectangle r
= rRoot
.GetDoc().GetMMRect( nCol
,nRow
,nCol
,nRow
,nTab
);
184 if( r
.Left() >= aRect
.Left() )
187 nColOff
= r
.Left() - aRect
.Left();
189 if( r
.Top() <= aRect
.Top() )
192 nRowOff
= aRect
.Top() - r
.Top();
194 if( r
.Left() < aRect
.Left() && r
.Top() > aRect
.Top() )
196 aFrom
= tools::Rectangle( nCol
-1, lcl_hmm2output( nColOff
, bInEMU
),
197 nRow
-1, lcl_hmm2output( nRowOff
, bInEMU
) );
206 tools::Rectangle r
= rRoot
.GetDoc().GetMMRect( nCol
,nRow
,nCol
,nRow
,nTab
);
207 if( r
.Right() < aRect
.Right() )
209 if( r
.Bottom() < aRect
.Bottom() )
211 if( r
.Right() >= aRect
.Right() && r
.Bottom() >= aRect
.Bottom() )
213 aTo
= tools::Rectangle( nCol
, lcl_hmm2output( aRect
.Right() - r
.Left(), bInEMU
),
214 nRow
, lcl_hmm2output( aRect
.Bottom() - r
.Top(), bInEMU
));
223 tools::Rectangle r
= rRoot
.GetDoc().GetMMRect( nCol
,nRow
,nCol
,nRow
,nTab
);
224 if( r
.Right() >= aRect
.Right() )
226 if( r
.Bottom() < aRect
.Bottom() )
228 if( r
.Right() < aRect
.Right() && r
.Bottom() >= aRect
.Bottom() )
230 aTo
= tools::Rectangle( nCol
, lcl_hmm2output( r
.Left() - aRect
.Right(), bInEMU
),
231 nRow
, lcl_hmm2output( aRect
.Bottom() - r
.Top(), bInEMU
));
240 // Escher client anchor =======================================================
242 XclExpDffAnchorBase::XclExpDffAnchorBase( const XclExpRoot
& rRoot
, sal_uInt16 nFlags
) :
248 void XclExpDffAnchorBase::SetFlags( const SdrObject
& rSdrObj
)
250 ImplSetFlags( rSdrObj
);
253 void XclExpDffAnchorBase::SetSdrObject( const SdrObject
& rSdrObj
)
255 ImplSetFlags( rSdrObj
);
256 ImplCalcAnchorRect( rSdrObj
.GetCurrentBoundRect(), MapUnit::Map100thMM
);
259 void XclExpDffAnchorBase::WriteDffData( EscherEx
& rEscherEx
) const
261 rEscherEx
.AddAtom( 18, ESCHER_ClientAnchor
);
262 rEscherEx
.GetStream().WriteUInt16( mnFlags
);
263 WriteXclObjAnchor( rEscherEx
.GetStream(), maAnchor
);
266 void XclExpDffAnchorBase::WriteData( EscherEx
& rEscherEx
, const tools::Rectangle
& rRect
)
268 // the passed rectangle is in twips
269 ImplCalcAnchorRect( rRect
, MapUnit::MapTwip
);
270 WriteDffData( rEscherEx
);
273 void XclExpDffAnchorBase::ImplSetFlags( const SdrObject
& )
275 OSL_FAIL( "XclExpDffAnchorBase::ImplSetFlags - not implemented" );
278 void XclExpDffAnchorBase::ImplCalcAnchorRect( const tools::Rectangle
&, MapUnit
)
280 OSL_FAIL( "XclExpDffAnchorBase::ImplCalcAnchorRect - not implemented" );
283 XclExpDffSheetAnchor::XclExpDffSheetAnchor( const XclExpRoot
& rRoot
) :
284 XclExpDffAnchorBase( rRoot
),
285 mnScTab( rRoot
.GetCurrScTab() )
289 void XclExpDffSheetAnchor::ImplSetFlags( const SdrObject
& rSdrObj
)
291 // set flags for cell/page anchoring
292 if ( ScDrawLayer::GetAnchorType( rSdrObj
) == SCA_CELL
)
295 mnFlags
= EXC_ESC_ANCHOR_LOCKED
;
298 void XclExpDffSheetAnchor::ImplCalcAnchorRect( const tools::Rectangle
& rRect
, MapUnit eMapUnit
)
300 maAnchor
.SetRect( GetRoot(), mnScTab
, rRect
, eMapUnit
);
303 XclExpDffEmbeddedAnchor::XclExpDffEmbeddedAnchor( const XclExpRoot
& rRoot
,
304 const Size
& rPageSize
, sal_Int32 nScaleX
, sal_Int32 nScaleY
) :
305 XclExpDffAnchorBase( rRoot
),
306 maPageSize( rPageSize
),
312 void XclExpDffEmbeddedAnchor::ImplSetFlags( const SdrObject
& /*rSdrObj*/ )
314 // TODO (unsupported feature): fixed size
317 void XclExpDffEmbeddedAnchor::ImplCalcAnchorRect( const tools::Rectangle
& rRect
, MapUnit eMapUnit
)
319 maAnchor
.SetRect( maPageSize
, mnScaleX
, mnScaleY
, rRect
, eMapUnit
);
322 XclExpDffNoteAnchor::XclExpDffNoteAnchor( const XclExpRoot
& rRoot
, const tools::Rectangle
& rRect
) :
323 XclExpDffAnchorBase( rRoot
, EXC_ESC_ANCHOR_SIZELOCKED
)
325 maAnchor
.SetRect( rRoot
, rRoot
.GetCurrScTab(), rRect
, MapUnit::Map100thMM
);
328 XclExpDffDropDownAnchor::XclExpDffDropDownAnchor( const XclExpRoot
& rRoot
, const ScAddress
& rScPos
) :
329 XclExpDffAnchorBase( rRoot
, EXC_ESC_ANCHOR_POSLOCKED
)
331 GetAddressConverter().ConvertAddress( maAnchor
.maFirst
, rScPos
, true );
332 maAnchor
.maLast
.mnCol
= maAnchor
.maFirst
.mnCol
+ 1;
333 maAnchor
.maLast
.mnRow
= maAnchor
.maFirst
.mnRow
+ 1;
334 maAnchor
.mnLX
= maAnchor
.mnTY
= maAnchor
.mnRX
= maAnchor
.mnBY
= 0;
337 // MSODRAWING* records ========================================================
339 XclExpMsoDrawingBase::XclExpMsoDrawingBase( XclEscherEx
& rEscherEx
, sal_uInt16 nRecId
) :
340 XclExpRecord( nRecId
),
341 mrEscherEx( rEscherEx
),
342 mnFragmentKey( rEscherEx
.InitNextDffFragment() )
346 void XclExpMsoDrawingBase::WriteBody( XclExpStream
& rStrm
)
348 OSL_ENSURE( mrEscherEx
.GetStreamPos() == mrEscherEx
.GetDffFragmentPos( mnFragmentKey
),
349 "XclExpMsoDrawingBase::WriteBody - DFF stream position mismatch" );
350 rStrm
.CopyFromStream( mrEscherEx
.GetStream(), mrEscherEx
.GetDffFragmentSize( mnFragmentKey
) );
353 XclExpMsoDrawingGroup::XclExpMsoDrawingGroup( XclEscherEx
& rEscherEx
) :
354 XclExpMsoDrawingBase( rEscherEx
, EXC_ID_MSODRAWINGGROUP
)
356 SvStream
& rDffStrm
= mrEscherEx
.GetStream();
358 // write the DGGCONTAINER with some default settings
359 mrEscherEx
.OpenContainer( ESCHER_DggContainer
);
361 // TODO: stuff the OPT atom with our own document defaults?
362 static const sal_uInt8 spnDffOpt
[] = {
363 0xBF, 0x00, 0x08, 0x00, 0x08, 0x00, 0x81, 0x01,
364 0x09, 0x00, 0x00, 0x08, 0xC0, 0x01, 0x40, 0x00,
367 mrEscherEx
.AddAtom( sizeof( spnDffOpt
), ESCHER_OPT
, 3, 3 );
368 rDffStrm
.WriteBytes(spnDffOpt
, sizeof(spnDffOpt
));
370 // SPLITMENUCOLORS contains colors in toolbar
371 static const sal_uInt8 spnDffSplitMenuColors
[] = {
372 0x0D, 0x00, 0x00, 0x08, 0x0C, 0x00, 0x00, 0x08,
373 0x17, 0x00, 0x00, 0x08, 0xF7, 0x00, 0x00, 0x10
375 mrEscherEx
.AddAtom( sizeof( spnDffSplitMenuColors
), ESCHER_SplitMenuColors
, 0, 4 );
376 rDffStrm
.WriteBytes(spnDffSplitMenuColors
, sizeof(spnDffSplitMenuColors
));
378 // close the DGGCONTAINER
379 mrEscherEx
.CloseContainer();
380 mrEscherEx
.UpdateDffFragmentEnd();
383 XclExpMsoDrawing::XclExpMsoDrawing( XclEscherEx
& rEscherEx
) :
384 XclExpMsoDrawingBase( rEscherEx
, EXC_ID_MSODRAWING
)
388 XclExpImgData::XclExpImgData( Graphic aGraphic
, sal_uInt16 nRecId
) :
389 maGraphic(std::move( aGraphic
)),
394 void XclExpImgData::Save( XclExpStream
& rStrm
)
396 Bitmap aBmp
= maGraphic
.GetBitmapEx().GetBitmap();
397 if (aBmp
.getPixelFormat() != vcl::PixelFormat::N24_BPP
)
398 aBmp
.Convert( BmpConversion::N24Bit
);
400 BitmapScopedReadAccess
pAccess(aBmp
);
404 sal_Int32 nWidth
= ::std::min
< sal_Int32
>( pAccess
->Width(), 0xFFFF );
405 sal_Int32 nHeight
= ::std::min
< sal_Int32
>( pAccess
->Height(), 0xFFFF );
406 if( (nWidth
<= 0) || (nHeight
<= 0) )
409 sal_uInt8 nPadding
= static_cast< sal_uInt8
>( nWidth
& 0x03 );
410 sal_uInt32 nTmpSize
= static_cast< sal_uInt32
>( (nWidth
* 3 + nPadding
) * nHeight
+ 12 );
412 rStrm
.StartRecord( mnRecId
, nTmpSize
+ 4 );
414 rStrm
<< EXC_IMGDATA_BMP
// BMP format
415 << EXC_IMGDATA_WIN
// Windows
416 << nTmpSize
// size after _this_ field
417 << sal_uInt32( 12 ) // BITMAPCOREHEADER size
418 << static_cast< sal_uInt16
>( nWidth
) // width
419 << static_cast< sal_uInt16
>( nHeight
) // height
420 << sal_uInt16( 1 ) // planes
421 << sal_uInt16( 24 ); // bits per pixel
423 for( sal_Int32 nY
= nHeight
- 1; nY
>= 0; --nY
)
425 Scanline pScanline
= pAccess
->GetScanline( nY
);
426 for( sal_Int32 nX
= 0; nX
< nWidth
; ++nX
)
428 const BitmapColor aBmpColor
= pAccess
->GetPixelFromData( pScanline
, nX
);
429 rStrm
<< aBmpColor
.GetBlue() << aBmpColor
.GetGreen() << aBmpColor
.GetRed();
431 rStrm
.WriteZeroBytes( nPadding
);
437 void XclExpImgData::SaveXml( XclExpXmlStream
& rStrm
)
439 sax_fastparser::FSHelperPtr pWorksheet
= rStrm
.GetCurrentStream();
441 DrawingML
aDML(pWorksheet
, &rStrm
, drawingml::DOCUMENT_XLSX
);
442 OUString rId
= aDML
.writeGraphicToStorage(maGraphic
);
443 pWorksheet
->singleElement(XML_picture
, FSNS(XML_r
, XML_id
), rId
);
446 XclExpControlHelper::XclExpControlHelper( const XclExpRoot
& rRoot
) :
452 XclExpControlHelper::~XclExpControlHelper()
456 void XclExpControlHelper::ConvertSheetLinks( Reference
< XShape
> const & xShape
)
459 mxCellLinkAddress
.SetInvalid();
464 Reference
< XControlModel
> xCtrlModel
= XclControlHelper::GetControlModel( xShape
);
465 if( !xCtrlModel
.is() )
468 // *** cell link *** ------------------------------------------------------
470 Reference
< XBindableValue
> xBindable( xCtrlModel
, UNO_QUERY
);
473 Reference
< XServiceInfo
> xServInfo( xBindable
->getValueBinding(), UNO_QUERY
);
474 if( xServInfo
.is() && xServInfo
->supportsService( SC_SERVICENAME_VALBIND
) )
476 ScfPropertySet
aBindProp( xServInfo
);
477 CellAddress aApiAddress
;
478 if( aBindProp
.GetProperty( aApiAddress
, SC_UNONAME_BOUNDCELL
) )
480 ScUnoConversion::FillScAddress( mxCellLinkAddress
, aApiAddress
);
481 if( GetTabInfo().IsExportTab( mxCellLinkAddress
.Tab() ) )
482 mxCellLink
= GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL
, mxCellLinkAddress
);
487 // *** source range *** ---------------------------------------------------
489 Reference
< XListEntrySink
> xEntrySink( xCtrlModel
, UNO_QUERY
);
490 if( !xEntrySink
.is() )
493 Reference
< XServiceInfo
> xServInfo( xEntrySink
->getListEntrySource(), UNO_QUERY
);
494 if( !(xServInfo
.is() && xServInfo
->supportsService( SC_SERVICENAME_LISTSOURCE
)) )
497 ScfPropertySet
aSinkProp( xServInfo
);
498 CellRangeAddress aApiRange
;
499 if( aSinkProp
.GetProperty( aApiRange
, SC_UNONAME_CELLRANGE
) )
502 ScUnoConversion::FillScRange( aSrcRange
, aApiRange
);
503 if( (aSrcRange
.aStart
.Tab() == aSrcRange
.aEnd
.Tab()) && GetTabInfo().IsExportTab( aSrcRange
.aStart
.Tab() ) )
504 mxSrcRange
= GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL
, aSrcRange
);
505 mnEntryCount
= static_cast< sal_uInt16
>( aSrcRange
.aEnd
.Col() - aSrcRange
.aStart
.Col() + 1 );
509 void XclExpControlHelper::WriteFormula( XclExpStream
& rStrm
, const XclTokenArray
& rTokArr
)
511 sal_uInt16 nFmlaSize
= rTokArr
.GetSize();
512 rStrm
<< nFmlaSize
<< sal_uInt32( 0 );
513 rTokArr
.WriteArray( rStrm
);
514 if( nFmlaSize
& 1 ) // pad to 16-bit
515 rStrm
<< sal_uInt8( 0 );
518 void XclExpControlHelper::WriteFormulaSubRec( XclExpStream
& rStrm
, sal_uInt16 nSubRecId
, const XclTokenArray
& rTokArr
)
520 rStrm
.StartRecord( nSubRecId
, (rTokArr
.GetSize() + 5) & ~1 );
521 WriteFormula( rStrm
, rTokArr
);
525 //delete for exporting OCX
526 //#if EXC_EXP_OCX_CTRL
528 XclExpOcxControlObj::XclExpOcxControlObj( XclExpObjectManager
& rObjMgr
, Reference
< XShape
> const & xShape
,
529 const tools::Rectangle
* pChildAnchor
, OUString aClassName
, sal_uInt32 nStrmStart
, sal_uInt32 nStrmSize
) :
530 XclObj( rObjMgr
, EXC_OBJTYPE_PICTURE
, true ),
531 XclExpControlHelper( rObjMgr
.GetRoot() ),
532 maClassName(std::move( aClassName
)),
533 mnStrmStart( nStrmStart
),
534 mnStrmSize( nStrmSize
)
536 ScfPropertySet
aCtrlProp( XclControlHelper::GetControlModel( xShape
) );
540 SetPrintable( aCtrlProp
.GetBoolProperty( u
"Printable"_ustr
) );
541 SetAutoFill( false );
542 SetAutoLine( false );
544 // fill DFF property set
545 mrEscherEx
.OpenContainer( ESCHER_SpContainer
);
546 mrEscherEx
.AddShape( ESCHER_ShpInst_HostControl
,
547 ShapeFlag::HaveShapeProperty
| ShapeFlag::HaveAnchor
| ShapeFlag::OLEShape
);
548 tools::Rectangle aDummyRect
;
549 EscherPropertyContainer
aPropOpt( mrEscherEx
.GetGraphicProvider(), mrEscherEx
.QueryPictureStream(), aDummyRect
);
550 aPropOpt
.AddOpt( ESCHER_Prop_FitTextToShape
, 0x00080008 ); // bool field
551 aPropOpt
.AddOpt( ESCHER_Prop_lineColor
, 0x08000040 );
552 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0x00080000 ); // bool field
554 // #i51348# name of the control, may overwrite shape name
556 if( aCtrlProp
.GetProperty( aCtrlName
, u
"Name"_ustr
) && !aCtrlName
.isEmpty() )
557 aPropOpt
.AddOpt( ESCHER_Prop_wzName
, aCtrlName
);
561 Reference
< XPropertySet
> xShapePS( xShape
, UNO_QUERY
);
562 if( xShapePS
.is() && aPropOpt
.CreateGraphicProperties( xShapePS
, u
"MetaFile"_ustr
, false ) )
565 if( aPropOpt
.GetOpt( ESCHER_Prop_pib
, nBlipId
) )
566 aPropOpt
.AddOpt( ESCHER_Prop_pictureId
, nBlipId
);
569 // write DFF property set to stream
570 aPropOpt
.Commit( mrEscherEx
.GetStream() );
573 ImplWriteAnchor( SdrObject::getSdrObjectFromXShape( xShape
), pChildAnchor
);
575 mrEscherEx
.AddAtom( 0, ESCHER_ClientData
); // OBJ record
576 mrEscherEx
.CloseContainer(); // ESCHER_SpContainer
577 mrEscherEx
.UpdateDffFragmentEnd();
580 ConvertSheetLinks( xShape
);
583 void XclExpOcxControlObj::WriteSubRecs( XclExpStream
& rStrm
)
585 // OBJCF - clipboard format
586 rStrm
.StartRecord( EXC_ID_OBJCF
, 2 );
587 rStrm
<< sal_uInt16( 2 );
591 rStrm
.StartRecord( EXC_ID_OBJFLAGS
, 2 );
592 rStrm
<< sal_uInt16( 0x0031 );
596 XclExpString
aClass( maClassName
);
597 sal_uInt16 nClassNameSize
= static_cast< sal_uInt16
>( aClass
.GetSize() );
598 sal_uInt16 nClassNamePad
= nClassNameSize
& 1;
599 sal_uInt16 nFirstPartSize
= 12 + nClassNameSize
+ nClassNamePad
;
601 const XclTokenArray
* pCellLink
= GetCellLinkTokArr();
602 sal_uInt16 nCellLinkSize
= pCellLink
? ((pCellLink
->GetSize() + 7) & 0xFFFE) : 0;
604 const XclTokenArray
* pSrcRange
= GetSourceRangeTokArr();
605 sal_uInt16 nSrcRangeSize
= pSrcRange
? ((pSrcRange
->GetSize() + 7) & 0xFFFE) : 0;
607 sal_uInt16 nPictFmlaSize
= nFirstPartSize
+ nCellLinkSize
+ nSrcRangeSize
+ 18;
608 rStrm
.StartRecord( EXC_ID_OBJPICTFMLA
, nPictFmlaSize
);
610 rStrm
<< nFirstPartSize
// size of first part
611 << sal_uInt16( 5 ) // formula size
612 << sal_uInt32( 0 ) // unknown ID
613 << sal_uInt8( 0x02 ) << sal_uInt32( 0 ) // tTbl token with unknown ID
614 << sal_uInt8( 3 ) // pad to word
615 << aClass
; // "Forms.***.1"
616 rStrm
.WriteZeroBytes( nClassNamePad
); // pad to word
617 rStrm
<< mnStrmStart
// start in 'Ctls' stream
618 << mnStrmSize
// size in 'Ctls' stream
619 << sal_uInt32( 0 ); // class ID size
621 rStrm
<< nCellLinkSize
;
623 WriteFormula( rStrm
, *pCellLink
);
625 rStrm
<< nSrcRangeSize
;
627 WriteFormula( rStrm
, *pSrcRange
);
634 XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager
& rRoot
, Reference
< XShape
> const & xShape
, const tools::Rectangle
* pChildAnchor
) :
635 XclObj( rRoot
, EXC_OBJTYPE_UNKNOWN
, true ),
636 XclMacroHelper( rRoot
),
638 meEventType( EXC_TBX_EVENT_ACTION
),
648 mbFlatButton( false ),
649 mbFlatBorder( false ),
651 mbScrollHor( false ),
657 namespace FormCompType
= css::form::FormComponentType
;
658 namespace AwtVisualEffect
= css::awt::VisualEffect
;
659 namespace AwtScrollOrient
= css::awt::ScrollBarOrientation
;
661 ScfPropertySet
aCtrlProp( XclControlHelper::GetControlModel( xShape
) );
662 if( !xShape
.is() || !aCtrlProp
.Is() )
665 mnHeight
= xShape
->getSize().Height
;
670 sal_Int16 nClassId
= 0;
671 if( aCtrlProp
.GetProperty( nClassId
, u
"ClassId"_ustr
) )
675 case FormCompType::COMMANDBUTTON
: mnObjType
= EXC_OBJTYPE_BUTTON
; meEventType
= EXC_TBX_EVENT_ACTION
; break;
676 case FormCompType::RADIOBUTTON
: mnObjType
= EXC_OBJTYPE_OPTIONBUTTON
; meEventType
= EXC_TBX_EVENT_ACTION
; break;
677 case FormCompType::CHECKBOX
: mnObjType
= EXC_OBJTYPE_CHECKBOX
; meEventType
= EXC_TBX_EVENT_ACTION
; break;
678 case FormCompType::LISTBOX
: mnObjType
= EXC_OBJTYPE_LISTBOX
; meEventType
= EXC_TBX_EVENT_CHANGE
; break;
679 case FormCompType::COMBOBOX
: mnObjType
= EXC_OBJTYPE_DROPDOWN
; meEventType
= EXC_TBX_EVENT_CHANGE
; break;
680 case FormCompType::GROUPBOX
: mnObjType
= EXC_OBJTYPE_GROUPBOX
; meEventType
= EXC_TBX_EVENT_MOUSE
; break;
681 case FormCompType::FIXEDTEXT
: mnObjType
= EXC_OBJTYPE_LABEL
; meEventType
= EXC_TBX_EVENT_MOUSE
; break;
682 case FormCompType::SCROLLBAR
: mnObjType
= EXC_OBJTYPE_SCROLLBAR
; meEventType
= EXC_TBX_EVENT_VALUE
; break;
683 case FormCompType::SPINBUTTON
: mnObjType
= EXC_OBJTYPE_SPIN
; meEventType
= EXC_TBX_EVENT_VALUE
; break;
686 if( mnObjType
== EXC_OBJTYPE_UNKNOWN
)
691 mbPrint
= aCtrlProp
.GetBoolProperty( u
"Printable"_ustr
);
692 SetPrintable( mbPrint
);
693 SetAutoFill( false );
694 SetAutoLine( false );
696 // fill DFF property set
697 mrEscherEx
.OpenContainer( ESCHER_SpContainer
);
698 mrEscherEx
.AddShape( ESCHER_ShpInst_HostControl
, ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
);
699 EscherPropertyContainer aPropOpt
;
700 mbVisible
= aCtrlProp
.GetBoolProperty( u
"EnableVisible"_ustr
);
701 aPropOpt
.AddOpt( ESCHER_Prop_fPrint
, mbVisible
? 0x00080000 : 0x00080002 ); // visible flag
703 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x01000100 ); // bool field
704 aPropOpt
.AddOpt( ESCHER_Prop_lTxid
, 0 ); // Text ID
705 aPropOpt
.AddOpt( ESCHER_Prop_WrapText
, 0x00000001 );
706 aPropOpt
.AddOpt( ESCHER_Prop_FitTextToShape
, 0x001A0008 ); // bool field
707 aPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x00100000 ); // bool field
708 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0x00080000 ); // bool field
710 // #i51348# name of the control, may overwrite shape name
711 if( aCtrlProp
.GetProperty( msCtrlName
, u
"Name"_ustr
) && !msCtrlName
.isEmpty() )
712 aPropOpt
.AddOpt( ESCHER_Prop_wzName
, msCtrlName
);
714 //Export description as alt text
715 if( SdrObject
* pSdrObj
= SdrObject::getSdrObjectFromXShape( xShape
) )
718 OUString aDescrText
= pSdrObj
->GetDescription();
719 if(!aDescrText
.isEmpty())
720 aAltTxt
= aDescrText
.copy( 0, std::min
<sal_Int32
>(MSPROP_DESCRIPTION_MAX_LEN
, aDescrText
.getLength()) );
721 aPropOpt
.AddOpt( ESCHER_Prop_wzDescription
, aAltTxt
);
724 // write DFF property set to stream
725 aPropOpt
.Commit( mrEscherEx
.GetStream() );
728 ImplWriteAnchor( SdrObject::getSdrObjectFromXShape( xShape
), pChildAnchor
);
730 mrEscherEx
.AddAtom( 0, ESCHER_ClientData
); // OBJ record
731 mrEscherEx
.UpdateDffFragmentEnd();
734 if( aCtrlProp
.GetProperty( msLabel
, u
"Label"_ustr
) )
736 /* Be sure to construct the MSODRAWING record containing the
737 ClientTextbox atom after the base OBJ's MSODRAWING record data is
739 pClientTextbox
.reset( new XclExpMsoDrawing( mrEscherEx
) );
740 mrEscherEx
.AddAtom( 0, ESCHER_ClientTextbox
); // TXO record
741 mrEscherEx
.UpdateDffFragmentEnd();
743 sal_uInt16 nXclFont
= EXC_FONT_APP
;
744 if( !msLabel
.isEmpty() )
746 XclFontData aFontData
;
747 GetFontPropSetHelper().ReadFontProperties( aFontData
, aCtrlProp
, EXC_FONTPROPSET_CONTROL
);
748 if( (!aFontData
.maName
.isEmpty() ) && (aFontData
.mnHeight
> 0) )
749 nXclFont
= GetFontBuffer().Insert( aFontData
, EXC_COLOR_CTRLTEXT
);
752 pTxo
.reset( new XclTxo( msLabel
, nXclFont
) );
753 pTxo
->SetHorAlign( (mnObjType
== EXC_OBJTYPE_BUTTON
) ? EXC_OBJ_HOR_CENTER
: EXC_OBJ_HOR_LEFT
);
754 pTxo
->SetVerAlign( EXC_OBJ_VER_CENTER
);
757 mrEscherEx
.CloseContainer(); // ESCHER_SpContainer
760 aCtrlProp
.GetProperty( mnLineCount
, u
"LineCount"_ustr
);
763 sal_Int16 nApiButton
= AwtVisualEffect::LOOK3D
;
764 sal_Int16 nApiBorder
= AwtVisualEffect::LOOK3D
;
767 case FormCompType::LISTBOX
:
768 case FormCompType::COMBOBOX
:
769 aCtrlProp
.GetProperty( nApiBorder
, u
"Border"_ustr
);
771 case FormCompType::CHECKBOX
:
772 case FormCompType::RADIOBUTTON
:
773 aCtrlProp
.GetProperty( nApiButton
, u
"VisualEffect"_ustr
);
774 nApiBorder
= AwtVisualEffect::NONE
;
776 // Push button cannot be set to flat in Excel
777 case FormCompType::COMMANDBUTTON
:
778 // Group box does not support flat style (#i34712#)
779 case FormCompType::GROUPBOX
:
780 nApiBorder
= AwtVisualEffect::LOOK3D
;
782 // Label does not support a border in Excel
783 case FormCompType::FIXEDTEXT
:
784 nApiBorder
= AwtVisualEffect::NONE
;
786 /* Scroll bar and spin button have a "Border" property, but it is
787 really used for a border, and not for own 3D/flat look (#i34712#). */
788 case FormCompType::SCROLLBAR
:
789 case FormCompType::SPINBUTTON
:
790 nApiButton
= AwtVisualEffect::LOOK3D
;
791 nApiBorder
= AwtVisualEffect::NONE
;
794 mbFlatButton
= nApiButton
!= AwtVisualEffect::LOOK3D
;
795 mbFlatBorder
= nApiBorder
!= AwtVisualEffect::LOOK3D
;
798 sal_Int16 nApiState
= 0;
799 if( aCtrlProp
.GetProperty( nApiState
, u
"State"_ustr
) )
803 case 0: mnState
= EXC_OBJ_CHECKBOX_UNCHECKED
; break;
804 case 1: mnState
= EXC_OBJ_CHECKBOX_CHECKED
; break;
805 case 2: mnState
= EXC_OBJ_CHECKBOX_TRISTATE
; break;
809 // special control contents
812 case FormCompType::LISTBOX
:
814 mbMultiSel
= aCtrlProp
.GetBoolProperty( u
"MultiSelection"_ustr
);
815 Sequence
< sal_Int16
> aSelection
;
816 if( aCtrlProp
.GetProperty( aSelection
, u
"SelectedItems"_ustr
) )
818 if( aSelection
.hasElements() )
820 mnSelEntry
= aSelection
[ 0 ] + 1;
821 comphelper::sequenceToContainer(maMultiSel
, aSelection
);
825 // convert listbox with dropdown button to Excel dropdown
826 if( aCtrlProp
.GetBoolProperty( u
"Dropdown"_ustr
) )
827 mnObjType
= EXC_OBJTYPE_DROPDOWN
;
831 case FormCompType::COMBOBOX
:
833 Sequence
< OUString
> aStringList
;
835 if( aCtrlProp
.GetProperty( aStringList
, u
"StringItemList"_ustr
) &&
836 aCtrlProp
.GetProperty( aDefText
, u
"Text"_ustr
) &&
837 aStringList
.hasElements() && !aDefText
.isEmpty() )
839 auto nIndex
= comphelper::findValue(aStringList
, aDefText
);
841 mnSelEntry
= static_cast< sal_Int16
>( nIndex
+ 1 ); // 1-based
843 maMultiSel
.resize( 1, mnSelEntry
- 1 );
846 // convert combobox without dropdown button to Excel listbox
847 if( !aCtrlProp
.GetBoolProperty( u
"Dropdown"_ustr
) )
848 mnObjType
= EXC_OBJTYPE_LISTBOX
;
852 case FormCompType::SCROLLBAR
:
854 sal_Int32 nApiValue
= 0;
855 if( aCtrlProp
.GetProperty( nApiValue
, u
"ScrollValueMin"_ustr
) )
856 mnScrollMin
= limit_cast
< sal_uInt16
>( nApiValue
, EXC_OBJ_SCROLLBAR_MIN
, EXC_OBJ_SCROLLBAR_MAX
);
857 if( aCtrlProp
.GetProperty( nApiValue
, u
"ScrollValueMax"_ustr
) )
858 mnScrollMax
= limit_cast
< sal_uInt16
>( nApiValue
, mnScrollMin
, EXC_OBJ_SCROLLBAR_MAX
);
859 if( aCtrlProp
.GetProperty( nApiValue
, u
"ScrollValue"_ustr
) )
860 mnScrollValue
= limit_cast
< sal_uInt16
>( nApiValue
, mnScrollMin
, mnScrollMax
);
861 if( aCtrlProp
.GetProperty( nApiValue
, u
"LineIncrement"_ustr
) )
862 mnScrollStep
= limit_cast
< sal_uInt16
>( nApiValue
, EXC_OBJ_SCROLLBAR_MIN
, EXC_OBJ_SCROLLBAR_MAX
);
863 if( aCtrlProp
.GetProperty( nApiValue
, u
"BlockIncrement"_ustr
) )
864 mnScrollPage
= limit_cast
< sal_uInt16
>( nApiValue
, EXC_OBJ_SCROLLBAR_MIN
, EXC_OBJ_SCROLLBAR_MAX
);
865 if( aCtrlProp
.GetProperty( nApiValue
, u
"Orientation"_ustr
) )
866 mbScrollHor
= nApiValue
== AwtScrollOrient::HORIZONTAL
;
870 case FormCompType::SPINBUTTON
:
872 sal_Int32 nApiValue
= 0;
873 if( aCtrlProp
.GetProperty( nApiValue
, u
"SpinValueMin"_ustr
) )
874 mnScrollMin
= limit_cast
< sal_uInt16
>( nApiValue
, EXC_OBJ_SCROLLBAR_MIN
, EXC_OBJ_SCROLLBAR_MAX
);
875 if( aCtrlProp
.GetProperty( nApiValue
, u
"SpinValueMax"_ustr
) )
876 mnScrollMax
= limit_cast
< sal_uInt16
>( nApiValue
, mnScrollMin
, EXC_OBJ_SCROLLBAR_MAX
);
877 if( aCtrlProp
.GetProperty( nApiValue
, u
"SpinValue"_ustr
) )
878 mnScrollValue
= limit_cast
< sal_uInt16
>( nApiValue
, mnScrollMin
, mnScrollMax
);
879 if( aCtrlProp
.GetProperty( nApiValue
, u
"SpinIncrement"_ustr
) )
880 mnScrollStep
= limit_cast
< sal_uInt16
>( nApiValue
, EXC_OBJ_SCROLLBAR_MIN
, EXC_OBJ_SCROLLBAR_MAX
);
881 if( aCtrlProp
.GetProperty( nApiValue
, u
"Orientation"_ustr
) )
882 mbScrollHor
= nApiValue
== AwtScrollOrient::HORIZONTAL
;
888 Reference
< XControlModel
> xCtrlModel
= XclControlHelper::GetControlModel( xShape
);
889 if( xCtrlModel
.is() )
891 Reference
< XBindableValue
> xBindable( xCtrlModel
, UNO_QUERY
);
894 Reference
< XServiceInfo
> xServInfo( xBindable
->getValueBinding(), UNO_QUERY
);
895 if( xServInfo
.is() && xServInfo
->supportsService( SC_SERVICENAME_VALBIND
) )
897 ScfPropertySet
aBindProp( xServInfo
);
898 CellAddress aApiAddress
;
899 if( aBindProp
.GetProperty( aApiAddress
, SC_UNONAME_BOUNDCELL
) )
901 ScUnoConversion::FillScAddress( mxCellLinkAddress
, aApiAddress
);
902 if( SdrObject
* pSdrObj
= SdrObject::getSdrObjectFromXShape( xShape
) )
903 lcl_GetFromTo( rRoot
, pSdrObj
->GetLogicRect(), mxCellLinkAddress
.Tab(), maAreaFrom
, maAreaTo
, true );
911 ConvertSheetLinks( xShape
);
914 bool XclExpTbxControlObj::SetMacroLink( const ScriptEventDescriptor
& rEvent
)
916 return XclMacroHelper::SetMacroLink( rEvent
, meEventType
);
919 void XclExpTbxControlObj::WriteSubRecs( XclExpStream
& rStrm
)
923 // *** Push buttons, labels ***
925 case EXC_OBJTYPE_BUTTON
:
926 case EXC_OBJTYPE_LABEL
:
927 // ftMacro - macro link
928 WriteMacroSubRec( rStrm
);
931 // *** Check boxes, option buttons ***
933 case EXC_OBJTYPE_CHECKBOX
:
934 case EXC_OBJTYPE_OPTIONBUTTON
:
936 // ftCbls - box properties
937 sal_uInt16 nStyle
= 0;
938 ::set_flag( nStyle
, EXC_OBJ_CHECKBOX_FLAT
, mbFlatButton
);
940 rStrm
.StartRecord( EXC_ID_OBJCBLS
, 12 );
942 rStrm
.WriteZeroBytes( 8 );
946 // ftMacro - macro link
947 WriteMacroSubRec( rStrm
);
948 // ftCblsFmla subrecord - cell link
949 WriteCellLinkSubRec( rStrm
, EXC_ID_OBJCBLSFMLA
);
951 // ftCblsData subrecord - box properties, again
952 rStrm
.StartRecord( EXC_ID_OBJCBLS
, 8 );
954 rStrm
.WriteZeroBytes( 4 );
960 // *** List boxes, combo boxes ***
962 case EXC_OBJTYPE_LISTBOX
:
963 case EXC_OBJTYPE_DROPDOWN
:
965 sal_uInt16 nEntryCount
= GetSourceEntryCount();
967 // ftSbs subrecord - Scroll bars
968 sal_Int32 nLineHeight
= XclTools::GetHmmFromTwips( 200 ); // always 10pt
969 if( mnObjType
== EXC_OBJTYPE_LISTBOX
)
970 mnLineCount
= static_cast< sal_uInt16
>( mnHeight
/ nLineHeight
);
973 sal_uInt16 nInvisLines
= (nEntryCount
>= mnLineCount
) ? (nEntryCount
- mnLineCount
) : 0;
974 mnScrollMax
= limit_cast
< sal_uInt16
>( nInvisLines
, EXC_OBJ_SCROLLBAR_MIN
, EXC_OBJ_SCROLLBAR_MAX
);
976 mnScrollPage
= limit_cast
< sal_uInt16
>( mnLineCount
, EXC_OBJ_SCROLLBAR_MIN
, EXC_OBJ_SCROLLBAR_MAX
);
980 // ftMacro - macro link
981 WriteMacroSubRec( rStrm
);
982 // ftSbsFmla subrecord - cell link
983 WriteCellLinkSubRec( rStrm
, EXC_ID_OBJSBSFMLA
);
985 // ftLbsData - source data range and box properties
986 sal_uInt16 nStyle
= 0;
987 ::insert_value( nStyle
, mbMultiSel
? EXC_OBJ_LISTBOX_MULTI
: EXC_OBJ_LISTBOX_SINGLE
, 4, 2 );
988 ::set_flag( nStyle
, EXC_OBJ_LISTBOX_FLAT
, mbFlatBorder
);
990 rStrm
.StartRecord( EXC_ID_OBJLBSDATA
, 0 );
992 if( const XclTokenArray
* pSrcRange
= GetSourceRangeTokArr() )
994 rStrm
<< static_cast< sal_uInt16
>( (pSrcRange
->GetSize() + 7) & 0xFFFE );
995 WriteFormula( rStrm
, *pSrcRange
);
998 rStrm
<< sal_uInt16( 0 );
1000 rStrm
<< nEntryCount
<< mnSelEntry
<< nStyle
<< sal_uInt16( 0 );
1001 if( mnObjType
== EXC_OBJTYPE_LISTBOX
)
1005 ScfUInt8Vec
aSelEx( nEntryCount
, 0 );
1006 for( const auto& rItem
: maMultiSel
)
1007 if( rItem
< nEntryCount
)
1008 aSelEx
[ rItem
] = 1;
1009 rStrm
.Write( aSelEx
.data(), aSelEx
.size() );
1012 else if( mnObjType
== EXC_OBJTYPE_DROPDOWN
)
1014 rStrm
<< sal_uInt16( 0 ) << mnLineCount
<< sal_uInt16( 0 ) << sal_uInt16( 0 );
1021 // *** Spin buttons, scrollbars ***
1023 case EXC_OBJTYPE_SPIN
:
1024 case EXC_OBJTYPE_SCROLLBAR
:
1026 // ftSbs subrecord - scroll bars
1028 // ftMacro - macro link
1029 WriteMacroSubRec( rStrm
);
1030 // ftSbsFmla subrecord - cell link
1031 WriteCellLinkSubRec( rStrm
, EXC_ID_OBJSBSFMLA
);
1035 // *** Group boxes ***
1037 case EXC_OBJTYPE_GROUPBOX
:
1039 // ftMacro - macro link
1040 WriteMacroSubRec( rStrm
);
1042 // ftGboData subrecord - group box properties
1043 sal_uInt16 nStyle
= 0;
1044 ::set_flag( nStyle
, EXC_OBJ_GROUPBOX_FLAT
, mbFlatBorder
);
1046 rStrm
.StartRecord( EXC_ID_OBJGBODATA
, 6 );
1047 rStrm
<< sal_uInt32( 0 )
1055 void XclExpTbxControlObj::WriteCellLinkSubRec( XclExpStream
& rStrm
, sal_uInt16 nSubRecId
)
1057 if( const XclTokenArray
* pCellLink
= GetCellLinkTokArr() )
1058 WriteFormulaSubRec( rStrm
, nSubRecId
, *pCellLink
);
1061 void XclExpTbxControlObj::WriteSbs( XclExpStream
& rStrm
)
1063 sal_uInt16 nOrient
= 0;
1064 ::set_flag( nOrient
, EXC_OBJ_SCROLLBAR_HOR
, mbScrollHor
);
1065 sal_uInt16 nStyle
= EXC_OBJ_SCROLLBAR_DEFFLAGS
;
1066 ::set_flag( nStyle
, EXC_OBJ_SCROLLBAR_FLAT
, mbFlatButton
);
1068 rStrm
.StartRecord( EXC_ID_OBJSBS
, 20 );
1069 rStrm
<< sal_uInt32( 0 ) // reserved
1070 << mnScrollValue
// thumb position
1071 << mnScrollMin
// thumb min pos
1072 << mnScrollMax
// thumb max pos
1073 << mnScrollStep
// line increment
1074 << mnScrollPage
// page increment
1075 << nOrient
// 0 = vertical, 1 = horizontal
1076 << sal_uInt16( 15 ) // thumb width
1077 << nStyle
; // flags/style
1081 void XclExpTbxControlObj::setShapeId(sal_Int32 aShapeId
)
1083 mnShapeId
= aShapeId
;
1088 /// Handles the VML export of form controls (e.g. checkboxes).
1089 class VmlFormControlExporter
: public oox::vml::VMLExport
1091 sal_uInt16 m_nObjType
;
1092 tools::Rectangle m_aAreaFrom
;
1093 tools::Rectangle m_aAreaTo
;
1094 OUString m_sControlName
;
1095 OUString m_sFmlaLink
;
1097 OUString m_aMacroName
;
1100 VmlFormControlExporter(const sax_fastparser::FSHelperPtr
& p
, sal_uInt16 nObjType
,
1101 const tools::Rectangle
& rAreaFrom
, const tools::Rectangle
& rAreaTo
,
1102 const OUString
& sControlName
, const OUString
& sFmlaLink
,
1103 OUString aLabel
, OUString aMacroName
);
1106 using VMLExport::StartShape
;
1107 sal_Int32
StartShape() override
;
1108 using VMLExport::EndShape
;
1109 void EndShape(sal_Int32 nShapeElement
) override
;
1112 VmlFormControlExporter::VmlFormControlExporter(const sax_fastparser::FSHelperPtr
& p
,
1113 sal_uInt16 nObjType
,
1114 const tools::Rectangle
& rAreaFrom
,
1115 const tools::Rectangle
& rAreaTo
,
1116 const OUString
& sControlName
,
1117 const OUString
& sFmlaLink
,
1118 OUString aLabel
, OUString aMacroName
)
1120 , m_nObjType(nObjType
)
1121 , m_aAreaFrom(rAreaFrom
)
1122 , m_aAreaTo(rAreaTo
)
1123 , m_sControlName(sControlName
)
1124 , m_sFmlaLink(sFmlaLink
)
1125 , m_aLabel(std::move(aLabel
))
1126 , m_aMacroName(std::move(aMacroName
))
1130 sal_Int32
VmlFormControlExporter::StartShape()
1133 AddShapeAttribute(XML_type
, "#_x0000_t201");
1134 if (!m_sControlName
.isEmpty())
1135 AddShapeAttribute(XML_id
, m_sControlName
.toUtf8());
1137 return VMLExport::StartShape();
1140 void VmlFormControlExporter::EndShape(sal_Int32 nShapeElement
)
1142 sax_fastparser::FSHelperPtr pVmlDrawing
= GetFS();
1144 pVmlDrawing
->startElement(FSNS(XML_v
, XML_textbox
));
1145 pVmlDrawing
->startElement(XML_div
);
1146 pVmlDrawing
->startElement(XML_font
);
1147 pVmlDrawing
->write(m_aLabel
);
1148 pVmlDrawing
->endElement(XML_font
);
1149 pVmlDrawing
->endElement(XML_div
);
1150 pVmlDrawing
->endElement(FSNS(XML_v
, XML_textbox
));
1152 OString aObjectType
;
1155 case EXC_OBJTYPE_CHECKBOX
:
1156 aObjectType
= "Checkbox"_ostr
;
1158 case EXC_OBJTYPE_BUTTON
:
1159 aObjectType
= "Button"_ostr
;
1162 pVmlDrawing
->startElement(FSNS(XML_x
, XML_ClientData
), XML_ObjectType
, aObjectType
);
1164 = OString::number(m_aAreaFrom
.Left()) + ", " + OString::number(m_aAreaFrom
.Top()) + ", "
1165 + OString::number(m_aAreaFrom
.Right()) + ", " + OString::number(m_aAreaFrom
.Bottom()) + ", "
1166 + OString::number(m_aAreaTo
.Left()) + ", " + OString::number(m_aAreaTo
.Top()) + ", "
1167 + OString::number(m_aAreaTo
.Right()) + ", " + OString::number(m_aAreaTo
.Bottom());
1168 XclXmlUtils::WriteElement(pVmlDrawing
, FSNS(XML_x
, XML_Anchor
), aAnchor
);
1170 if (!m_aMacroName
.isEmpty())
1172 XclXmlUtils::WriteElement(pVmlDrawing
, FSNS(XML_x
, XML_FmlaMacro
), m_aMacroName
);
1175 // XclExpOcxControlObj::WriteSubRecs() has the same fixed values.
1176 if (m_nObjType
== EXC_OBJTYPE_BUTTON
)
1178 XclXmlUtils::WriteElement(pVmlDrawing
, FSNS(XML_x
, XML_TextHAlign
), "Center");
1180 XclXmlUtils::WriteElement(pVmlDrawing
, FSNS(XML_x
, XML_TextVAlign
), "Center");
1182 if (!m_sFmlaLink
.isEmpty())
1183 XclXmlUtils::WriteElement(pVmlDrawing
, FSNS(XML_x
, XML_FmlaLink
), m_sFmlaLink
);
1185 pVmlDrawing
->endElement(FSNS(XML_x
, XML_ClientData
));
1186 VMLExport::EndShape(nShapeElement
);
1191 /// Save into xl/drawings/vmlDrawing1.vml.
1192 void XclExpTbxControlObj::SaveVml(XclExpXmlStream
& rStrm
)
1194 SdrObject
* pObj
= SdrObject::getSdrObjectFromXShape(mxShape
);
1195 tools::Rectangle aAreaFrom
;
1196 tools::Rectangle aAreaTo
;
1197 // Unlike XclExpTbxControlObj::SaveXml(), this is not calculated in EMUs.
1198 lcl_GetFromTo(mrRoot
, pObj
->GetLogicRect(), GetTab(), aAreaFrom
, aAreaTo
);
1200 const OUString sCellLink
1201 = mxCellLinkAddress
.IsValid()
1202 ? mxCellLinkAddress
.Format(ScRefFlags::ADDR_ABS
, &GetDoc(),
1203 ScAddress::Details(formula::FormulaGrammar::CONV_XL_A1
))
1206 VmlFormControlExporter
aFormControlExporter(rStrm
.GetCurrentStream(), GetObjType(), aAreaFrom
,
1207 aAreaTo
, msCtrlName
, sCellLink
, msLabel
, GetMacroName());
1208 aFormControlExporter
.SetSkipwzName(true); // use XML_id for legacyid, not XML_ID
1209 aFormControlExporter
.OverrideShapeIDGen(true, "_x0000_s"_ostr
);
1210 aFormControlExporter
.AddSdrObject(*pObj
, /*bIsFollowingTextFlow=*/false, /*eHOri=*/-1,
1211 /*eVOri=*/-1, /*eHRel=*/-1, /*eVRel=*/-1,
1212 /*pWrapAttrList=*/nullptr, /*bOOxmlExport=*/true, mnShapeId
);
1215 // save into xl\drawings\drawing1.xml
1216 void XclExpTbxControlObj::SaveXml( XclExpXmlStream
& rStrm
)
1218 sax_fastparser::FSHelperPtr
& pDrawing
= rStrm
.GetCurrentStream();
1220 pDrawing
->startElement(FSNS(XML_mc
, XML_AlternateContent
),
1221 FSNS(XML_xmlns
, XML_mc
), rStrm
.getNamespaceURL(OOX_NS(mce
)));
1222 pDrawing
->startElement(FSNS(XML_mc
, XML_Choice
),
1223 FSNS(XML_xmlns
, XML_a14
), rStrm
.getNamespaceURL(OOX_NS(a14
)),
1224 XML_Requires
, "a14");
1226 pDrawing
->startElement(FSNS(XML_xdr
, XML_twoCellAnchor
), XML_editAs
, "oneCell");
1228 pDrawing
->startElement(FSNS(XML_xdr
, XML_from
));
1229 lcl_WriteAnchorVertex(pDrawing
, maAreaFrom
);
1230 pDrawing
->endElement(FSNS(XML_xdr
, XML_from
));
1231 pDrawing
->startElement(FSNS(XML_xdr
, XML_to
));
1232 lcl_WriteAnchorVertex(pDrawing
, maAreaTo
);
1233 pDrawing
->endElement(FSNS(XML_xdr
, XML_to
));
1235 pDrawing
->startElement(FSNS(XML_xdr
, XML_sp
));
1238 pDrawing
->startElement(FSNS(XML_xdr
, XML_nvSpPr
));
1240 pDrawing
->singleElement(FSNS(XML_xdr
, XML_cNvPr
),
1241 XML_id
, OString::number(mnShapeId
),
1242 XML_name
, msCtrlName
, // control name
1243 XML_descr
, msLabel
, // description as alt text
1244 XML_hidden
, mbVisible
? "0" : "1");
1245 pDrawing
->singleElement(FSNS(XML_xdr
, XML_cNvSpPr
));
1247 pDrawing
->endElement(FSNS(XML_xdr
, XML_nvSpPr
));
1250 pDrawing
->startElement(FSNS(XML_xdr
, XML_spPr
));
1253 pDrawing
->startElement(FSNS(XML_a
, XML_xfrm
));
1255 pDrawing
->singleElement(FSNS(XML_a
, XML_off
),
1258 pDrawing
->singleElement(FSNS(XML_a
, XML_ext
),
1262 pDrawing
->endElement(FSNS(XML_a
, XML_xfrm
));
1265 pDrawing
->startElement(FSNS(XML_a
, XML_prstGeom
), XML_prst
, "rect");
1267 pDrawing
->singleElement(FSNS(XML_a
, XML_avLst
));
1269 pDrawing
->endElement(FSNS(XML_a
, XML_prstGeom
));
1271 pDrawing
->endElement(FSNS(XML_xdr
, XML_spPr
));
1275 pDrawing
->startElement(FSNS(XML_xdr
, XML_txBody
));
1277 #define DEFLRINS 254
1278 #define DEFTBINS 127
1279 sal_Int32 nLeft
, nRight
, nTop
, nBottom
;
1280 nLeft
= nRight
= DEFLRINS
;
1281 nTop
= nBottom
= DEFTBINS
;
1283 // top inset looks a bit different compared to ppt export
1284 // check if something related doesn't work as expected
1285 Reference
< XPropertySet
> rXPropSet(mxShape
, UNO_QUERY
);
1291 mAny
= rXPropSet
->getPropertyValue(u
"TextLeftDistance"_ustr
);
1292 if (mAny
.hasValue())
1295 mAny
= rXPropSet
->getPropertyValue(u
"TextRightDistance"_ustr
);
1296 if (mAny
.hasValue())
1299 mAny
= rXPropSet
->getPropertyValue(u
"TextUpperDistance"_ustr
);
1300 if (mAny
.hasValue())
1303 mAny
= rXPropSet
->getPropertyValue(u
"TextLowerDistance"_ustr
);
1304 if (mAny
.hasValue())
1311 // Specifies the inset of the bounding rectangle.
1312 // Insets are used just as internal margins for text boxes within shapes.
1313 // If this attribute is omitted, then a value of 45720 or 0.05 inches is implied.
1314 pDrawing
->startElementNS(XML_a
, XML_bodyPr
,
1315 XML_lIns
, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nLeft
)), nLeft
!= DEFLRINS
),
1316 XML_rIns
, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nRight
)), nRight
!= DEFLRINS
),
1317 XML_tIns
, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nTop
)), nTop
!= DEFTBINS
),
1318 XML_bIns
, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nBottom
)), nBottom
!= DEFTBINS
),
1322 bool bTextAutoGrowHeight
= false;
1328 mAny
= rXPropSet
->getPropertyValue(u
"TextAutoGrowHeight"_ustr
);
1329 if (mAny
.hasValue())
1330 mAny
>>= bTextAutoGrowHeight
;
1336 pDrawing
->singleElementNS(XML_a
, (bTextAutoGrowHeight
? XML_spAutoFit
: XML_noAutofit
));
1339 pDrawing
->endElementNS(XML_a
, XML_bodyPr
);
1342 pDrawing
->startElementNS(XML_a
, XML_p
);
1343 pDrawing
->startElementNS(XML_a
, XML_r
);
1344 pDrawing
->startElementNS(XML_a
, XML_t
);
1345 pDrawing
->write(msLabel
);
1346 pDrawing
->endElementNS(XML_a
, XML_t
);
1347 pDrawing
->endElementNS(XML_a
, XML_r
);
1348 pDrawing
->endElementNS(XML_a
, XML_p
);
1351 pDrawing
->endElement(FSNS(XML_xdr
, XML_txBody
));
1354 pDrawing
->endElement(FSNS(XML_xdr
, XML_sp
));
1355 pDrawing
->singleElement(FSNS(XML_xdr
, XML_clientData
));
1357 pDrawing
->endElement(FSNS(XML_xdr
, XML_twoCellAnchor
));
1358 pDrawing
->endElement( FSNS( XML_mc
, XML_Choice
) );
1359 pDrawing
->endElement( FSNS( XML_mc
, XML_AlternateContent
) );
1362 // output into ctrlProp1.xml
1363 OUString
XclExpTbxControlObj::SaveControlPropertiesXml(XclExpXmlStream
& rStrm
) const
1365 OUString sIdFormControlPr
;
1369 case EXC_OBJTYPE_CHECKBOX
:
1371 const sal_Int32 nDrawing
= DrawingML::getNewDrawingUniqueId();
1372 sax_fastparser::FSHelperPtr pFormControl
= rStrm
.CreateOutputStream(
1373 XclXmlUtils::GetStreamName( "xl/", "ctrlProps/ctrlProps", nDrawing
),
1374 XclXmlUtils::GetStreamName( "../", "ctrlProps/ctrlProps", nDrawing
),
1375 rStrm
.GetCurrentStream()->getOutputStream(),
1376 "application/vnd.ms-excel.controlproperties+xml",
1377 oox::getRelationship(Relationship::CTRLPROP
),
1378 &sIdFormControlPr
);
1380 rStrm
.PushStream( pFormControl
);
1383 // xmlns="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"
1384 // objectType="CheckBox" checked="Checked" lockText="1" noThreeD="1"/>
1386 pFormControl
->write("<formControlPr xmlns=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main\" objectType=\"CheckBox\"");
1387 if (mnState
== EXC_OBJ_CHECKBOX_CHECKED
)
1388 pFormControl
->write(" checked=\"Checked\"");
1390 pFormControl
->write(" autoLine=\"false\"");
1393 pFormControl
->write(" print=\"true\"");
1395 pFormControl
->write(" print=\"false\"");
1397 if (mxCellLinkAddress
.IsValid())
1399 OUString aCellLink
= mxCellLinkAddress
.Format(ScRefFlags::ADDR_ABS
,
1401 ScAddress::Details(::formula::FormulaGrammar::CONV_XL_A1
));
1404 pFormControl
->write(" fmlaLink=\"");
1405 if (aCellLink
.indexOf('!') < 0)
1407 pFormControl
->write(GetTabInfo().GetScTabName(mxCellLinkAddress
.Tab()));
1408 pFormControl
->write("!");
1410 pFormControl
->write(aCellLink
);
1411 pFormControl
->write("\"");
1414 pFormControl
->write(" lockText=\"1\" noThreeD=\"1\"/>");
1419 case EXC_OBJTYPE_BUTTON
:
1421 sal_Int32 nDrawing
= DrawingML::getNewDrawingUniqueId();
1422 sax_fastparser::FSHelperPtr pFormControl
= rStrm
.CreateOutputStream(
1423 XclXmlUtils::GetStreamName("xl/", "ctrlProps/ctrlProps", nDrawing
),
1424 XclXmlUtils::GetStreamName("../", "ctrlProps/ctrlProps", nDrawing
),
1425 rStrm
.GetCurrentStream()->getOutputStream(),
1426 "application/vnd.ms-excel.controlproperties+xml",
1427 oox::getRelationship(Relationship::CTRLPROP
), &sIdFormControlPr
);
1429 pFormControl
->singleElement(XML_formControlPr
, XML_xmlns
,
1430 rStrm
.getNamespaceURL(OOX_NS(xls14Lst
)), XML_objectType
,
1431 "Button", XML_lockText
, "1");
1436 return sIdFormControlPr
;
1439 // output into sheet1.xml
1440 void XclExpTbxControlObj::SaveSheetXml(XclExpXmlStream
& rStrm
, const OUString
& aIdFormControlPr
) const
1444 case EXC_OBJTYPE_CHECKBOX
:
1446 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
1448 rWorksheet
->startElement(FSNS(XML_mc
, XML_AlternateContent
),
1449 FSNS(XML_xmlns
, XML_mc
), rStrm
.getNamespaceURL(OOX_NS(mce
)));
1450 rWorksheet
->startElement(FSNS(XML_mc
, XML_Choice
), XML_Requires
, "x14");
1452 rWorksheet
->startElement(
1454 XML_shapeId
, OString::number(mnShapeId
),
1455 FSNS(XML_r
, XML_id
), aIdFormControlPr
,
1456 XML_name
, msLabel
); // text to display with checkbox button
1458 rWorksheet
->write("<controlPr defaultSize=\"0\" locked=\"1\" autoFill=\"0\" autoLine=\"0\" autoPict=\"0\"");
1461 rWorksheet
->write(" print=\"true\"");
1463 rWorksheet
->write(" print=\"false\"");
1465 if (!msCtrlName
.isEmpty())
1467 rWorksheet
->write(" altText=\"");
1468 rWorksheet
->write(msCtrlName
); // alt text
1469 rWorksheet
->write("\"");
1472 rWorksheet
->write(">");
1474 rWorksheet
->startElement(XML_anchor
, XML_moveWithCells
, "true", XML_sizeWithCells
, "false");
1475 rWorksheet
->startElement(XML_from
);
1476 lcl_WriteAnchorVertex(rWorksheet
, maAreaFrom
);
1477 rWorksheet
->endElement(XML_from
);
1478 rWorksheet
->startElement(XML_to
);
1479 lcl_WriteAnchorVertex(rWorksheet
, maAreaTo
);
1480 rWorksheet
->endElement(XML_to
);
1481 rWorksheet
->endElement( XML_anchor
);
1483 rWorksheet
->write("</controlPr>");
1485 rWorksheet
->endElement(XML_control
);
1486 rWorksheet
->endElement( FSNS( XML_mc
, XML_Choice
) );
1487 rWorksheet
->endElement( FSNS( XML_mc
, XML_AlternateContent
) );
1491 case EXC_OBJTYPE_BUTTON
:
1493 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
1495 rWorksheet
->startElement(FSNS(XML_mc
, XML_AlternateContent
), FSNS(XML_xmlns
, XML_mc
),
1496 rStrm
.getNamespaceURL(OOX_NS(mce
)));
1497 rWorksheet
->startElement(FSNS(XML_mc
, XML_Choice
), XML_Requires
, "x14");
1499 rWorksheet
->startElement(XML_control
, XML_shapeId
, OString::number(mnShapeId
),
1500 FSNS(XML_r
, XML_id
), aIdFormControlPr
, XML_name
, msCtrlName
);
1502 OUString aMacroName
= GetMacroName();
1503 // Omit the macro attribute if it would be empty.
1504 rWorksheet
->startElement(XML_controlPr
, XML_defaultSize
, "0", XML_print
,
1505 mbPrint
? "true" : "false", XML_autoFill
, "0", XML_autoPict
,
1506 "0", XML_macro
, sax_fastparser::UseIf(aMacroName
, !aMacroName
.isEmpty()));
1508 rWorksheet
->startElement(XML_anchor
, XML_moveWithCells
, "true", XML_sizeWithCells
,
1511 SdrObject
* pObj
= SdrObject::getSdrObjectFromXShape(mxShape
);
1512 tools::Rectangle aAreaFrom
;
1513 tools::Rectangle aAreaTo
;
1514 lcl_GetFromTo(mrRoot
, pObj
->GetLogicRect(), GetTab(), aAreaFrom
, aAreaTo
,
1517 rWorksheet
->startElement(XML_from
);
1518 lcl_WriteAnchorVertex(rWorksheet
, aAreaFrom
);
1519 rWorksheet
->endElement(XML_from
);
1520 rWorksheet
->startElement(XML_to
);
1521 lcl_WriteAnchorVertex(rWorksheet
, aAreaTo
);
1522 rWorksheet
->endElement(XML_to
);
1523 rWorksheet
->endElement(XML_anchor
);
1525 rWorksheet
->endElement(XML_controlPr
);
1527 rWorksheet
->endElement(XML_control
);
1528 rWorksheet
->endElement(FSNS(XML_mc
, XML_Choice
));
1529 rWorksheet
->endElement(FSNS(XML_mc
, XML_AlternateContent
));
1537 XclExpChartObj::XclExpChartObj( XclExpObjectManager
& rObjMgr
, Reference
< XShape
> const & xShape
, const tools::Rectangle
* pChildAnchor
, ScDocument
* pDoc
) :
1538 XclObj( rObjMgr
, EXC_OBJTYPE_CHART
),
1539 XclExpRoot( rObjMgr
.GetRoot() ), mxShape( xShape
),
1542 // create the MSODRAWING record contents for the chart object
1543 mrEscherEx
.OpenContainer( ESCHER_SpContainer
);
1544 mrEscherEx
.AddShape( ESCHER_ShpInst_HostControl
, ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
);
1545 EscherPropertyContainer aPropOpt
;
1546 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x01040104 );
1547 aPropOpt
.AddOpt( ESCHER_Prop_FitTextToShape
, 0x00080008 );
1548 aPropOpt
.AddOpt( ESCHER_Prop_fillColor
, 0x0800004E );
1549 aPropOpt
.AddOpt( ESCHER_Prop_fillBackColor
, 0x0800004D );
1550 aPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x00110010 );
1551 aPropOpt
.AddOpt( ESCHER_Prop_lineColor
, 0x0800004D );
1552 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0x00080008 );
1553 aPropOpt
.AddOpt( ESCHER_Prop_fshadowObscured
, 0x00020000 );
1554 aPropOpt
.AddOpt( ESCHER_Prop_fPrint
, 0x00080000 );
1555 aPropOpt
.Commit( mrEscherEx
.GetStream() );
1558 SdrObject
* pSdrObj
= SdrObject::getSdrObjectFromXShape( xShape
);
1559 ImplWriteAnchor( pSdrObj
, pChildAnchor
);
1561 // client data (the following OBJ record)
1562 mrEscherEx
.AddAtom( 0, ESCHER_ClientData
);
1563 mrEscherEx
.CloseContainer(); // ESCHER_SpContainer
1564 mrEscherEx
.UpdateDffFragmentEnd();
1566 // load the chart OLE object
1567 if( SdrOle2Obj
* pSdrOleObj
= dynamic_cast< SdrOle2Obj
* >( pSdrObj
) )
1568 (void)svt::EmbeddedObjectRef::TryRunningState(pSdrOleObj
->GetObjRef());
1570 // create the chart substream object
1571 ScfPropertySet
aShapeProp( xShape
);
1572 css::awt::Rectangle aBoundRect
;
1573 aShapeProp
.GetProperty( aBoundRect
, u
"BoundRect"_ustr
);
1574 tools::Rectangle
aChartRect( Point( aBoundRect
.X
, aBoundRect
.Y
), Size( aBoundRect
.Width
, aBoundRect
.Height
) );
1575 mxChart
= std::make_shared
<XclExpChart
>(GetRoot(), GetChartDoc(), aChartRect
);
1578 XclExpChartObj::~XclExpChartObj()
1582 void XclExpChartObj::Save( XclExpStream
& rStrm
)
1584 // content of OBJ record
1585 XclObj::Save( rStrm
);
1587 mxChart
->Save( rStrm
);
1590 void XclExpChartObj::SaveXml( XclExpXmlStream
& rStrm
)
1592 sax_fastparser::FSHelperPtr pDrawing
= rStrm
.GetCurrentStream();
1594 // FIXME: two cell? it seems the two cell anchor is incorrect.
1595 pDrawing
->startElement( FSNS( XML_xdr
, XML_twoCellAnchor
), // OOXTODO: oneCellAnchor, absoluteAnchor
1596 XML_editAs
, "oneCell" );
1597 Reference
< XPropertySet
> xPropSet( mxShape
, UNO_QUERY
);
1600 XclObjAny::WriteFromTo( rStrm
, mxShape
, GetTab() );
1601 ChartExport
aChartExport(XML_xdr
, pDrawing
, GetChartDoc(), &rStrm
, drawingml::DOCUMENT_XLSX
);
1602 auto pURLTransformer
= std::make_shared
<ScURLTransformer
>(*mpDoc
);
1603 aChartExport
.SetURLTranslator(pURLTransformer
);
1604 sal_Int32 nChartCount
= oox::drawingml::DrawingML::getNewChartUniqueId();
1605 sal_Int32 nID
= rStrm
.GetUniqueId();
1606 aChartExport
.WriteChartObj( mxShape
, nID
, nChartCount
);
1607 // TODO: get the correcto chart number
1610 pDrawing
->singleElement( FSNS( XML_xdr
, XML_clientData
)
1611 // OOXTODO: XML_fLocksWithSheet
1612 // OOXTODO: XML_fPrintsWithSheet
1614 pDrawing
->endElement( FSNS( XML_xdr
, XML_twoCellAnchor
) );
1617 css::uno::Reference
<css::chart::XChartDocument
> XclExpChartObj::GetChartDoc() const
1619 SdrObject
* pObj
= SdrObject::getSdrObjectFromXShape(mxShape
);
1620 if (!pObj
|| pObj
->GetObjIdentifier() != SdrObjKind::OLE2
)
1622 // May load here - makes sure that we are working with actually loaded OLE object
1623 return css::uno::Reference
<css::chart::XChartDocument
>(
1624 static_cast<SdrOle2Obj
*>(pObj
)->getXModel(), css::uno::UNO_QUERY
);
1627 XclExpNote::XclExpNote(const XclExpRoot
& rRoot
, const ScAddress
& rScPos
,
1628 const ScPostIt
* pScNote
, std::u16string_view rAddText
)
1629 : XclExpRecord(EXC_ID_NOTE
)
1632 , mnObjId(EXC_OBJ_INVALID_ID
)
1633 , mbVisible(pScNote
&& pScNote
->IsCaptionShown())
1634 , meTHA(SDRTEXTHORZADJUST_LEFT
)
1635 , meTVA(SDRTEXTVERTADJUST_TOP
)
1636 , mbAutoScale(false)
1639 , mbColHidden(false)
1640 , mbRowHidden(false)
1641 , mpAuthorIDs(new SvtSecurityMapPersonalInfo
)
1643 // get the main note text
1646 aNoteText
= pScNote
->GetText();
1648 // append additional text
1649 aNoteText
= ScGlobal::addToken( aNoteText
, rAddText
, '\n', 2 );
1651 // initialize record dependent on BIFF type
1652 switch( rRoot
.GetBiff() )
1655 maNoteText
= OUStringToOString(aNoteText
, rRoot
.GetTextEncoding());
1660 // TODO: additional text
1663 if( SdrCaptionObj
* pCaption
= pScNote
->GetOrCreateCaption( maScPos
) )
1665 lcl_GetFromTo( rRoot
, pCaption
->GetLogicRect(), maScPos
.Tab(), maCommentFrom
, maCommentTo
);
1666 if( const OutlinerParaObject
* pOPO
= pCaption
->GetOutlinerParaObject() )
1667 mnObjId
= rRoot
.GetObjectManager().AddObj( std::make_unique
<XclObjComment
>( rRoot
.GetObjectManager(), pCaption
->GetLogicRect(), pOPO
->GetTextObject(), pCaption
, mbVisible
, maScPos
, maCommentFrom
, maCommentTo
) );
1669 SfxItemSet aItemSet
= pCaption
->GetMergedItemSet();
1670 meTVA
= pCaption
->GetTextVerticalAdjust();
1671 meTHA
= pCaption
->GetTextHorizontalAdjust();
1672 mbAutoScale
= pCaption
->GetFitToSize() != drawing::TextFitToSizeType_NONE
;
1673 mbLocked
= pCaption
->IsMoveProtect() || pCaption
->IsResizeProtect();
1675 // AutoFill style would change if Postit.cxx object creation values are changed
1676 OUString
aCol(aItemSet
.Get(XATTR_FILLCOLOR
).GetValue());
1677 mbAutoFill
= aCol
.isEmpty() && (aItemSet
.Get(XATTR_FILLSTYLE
).GetValue() == drawing::FillStyle_SOLID
);
1678 mbRowHidden
= (rRoot
.GetDoc().RowHidden(maScPos
.Row(),maScPos
.Tab()));
1679 mbColHidden
= (rRoot
.GetDoc().ColHidden(maScPos
.Col(),maScPos
.Tab()));
1681 // stAuthor (variable): An XLUnicodeString that specifies the name of the comment
1682 // author. String length MUST be greater than or equal to 1 and less than or equal
1684 bool bRemovePersonalInfo
1685 = SvtSecurityOptions::IsOptionSet(
1686 SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo
)
1687 && !SvtSecurityOptions::IsOptionSet(
1688 SvtSecurityOptions::EOption::DocWarnKeepNoteAuthorDateInfo
);
1689 if( pScNote
->GetAuthor().isEmpty() )
1690 maAuthor
= XclExpString( u
" "_ustr
);
1691 else if (bRemovePersonalInfo
)
1692 maAuthor
= XclExpString(
1694 + OUString::number(mpAuthorIDs
->GetInfoID(pScNote
->GetAuthor())),
1695 XclStrFlags::NONE
, 54);
1697 maAuthor
= XclExpString( pScNote
->GetAuthor(), XclStrFlags::NONE
, 54 );
1699 if (const EditTextObject
*pEditObj
= pScNote
->GetEditTextObject())
1700 mpNoteContents
= XclExpStringHelper::CreateString( rRoot
, *pEditObj
);
1703 SetRecSize( 9 + maAuthor
.GetSize() );
1707 default: DBG_ERROR_BIFF();
1711 void XclExpNote::Save( XclExpStream
& rStrm
)
1713 switch( rStrm
.GetRoot().GetBiff() )
1717 // write the NOTE record directly, there may be the need to create more than one
1718 const char* pcBuffer
= maNoteText
.getStr();
1719 sal_uInt16 nCharsLeft
= static_cast< sal_uInt16
>( maNoteText
.getLength() );
1723 sal_uInt16 nWriteChars
= ::std::min( nCharsLeft
, EXC_NOTE5_MAXLEN
);
1725 rStrm
.StartRecord( EXC_ID_NOTE
, 6 + nWriteChars
);
1726 if( pcBuffer
== maNoteText
.getStr() )
1728 // first record: row, col, length of complete text
1729 rStrm
<< static_cast< sal_uInt16
>( maScPos
.Row() )
1730 << static_cast< sal_uInt16
>( maScPos
.Col() )
1731 << nCharsLeft
; // still contains full length
1735 // next records: -1, 0, length of current text segment
1736 rStrm
<< sal_uInt16( 0xFFFF )
1740 rStrm
.Write( pcBuffer
, nWriteChars
);
1743 pcBuffer
+= nWriteChars
;
1744 nCharsLeft
= nCharsLeft
- nWriteChars
;
1750 if( mnObjId
!= EXC_OBJ_INVALID_ID
)
1751 XclExpRecord::Save( rStrm
);
1754 default: DBG_ERROR_BIFF();
1758 void XclExpNote::WriteBody( XclExpStream
& rStrm
)
1760 // BIFF5/BIFF7 is written separately
1761 OSL_ENSURE_BIFF( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
);
1763 sal_uInt16 nFlags
= 0;
1764 ::set_flag( nFlags
, EXC_NOTE_VISIBLE
, mbVisible
);
1766 rStrm
<< static_cast< sal_uInt16
>( maScPos
.Row() )
1767 << static_cast< sal_uInt16
>( maScPos
.Col() )
1774 void XclExpNote::WriteXml( sal_Int32 nAuthorId
, XclExpXmlStream
& rStrm
)
1776 sax_fastparser::FSHelperPtr rComments
= rStrm
.GetCurrentStream();
1778 rComments
->startElement( XML_comment
,
1779 XML_ref
, XclXmlUtils::ToOString(mrRoot
.GetDoc(), ScRange(maScPos
)),
1780 XML_authorId
, OString::number(nAuthorId
)
1781 // OOXTODO: XML_guid
1783 rComments
->startElement(XML_text
);
1784 // OOXTODO: phoneticPr, rPh, r
1785 if( mpNoteContents
)
1786 mpNoteContents
->WriteXml( rStrm
);
1787 rComments
->endElement( XML_text
);
1790 Export of commentPr is disabled, since the current (Oct 2010)
1791 version of MSO 2010 doesn't yet support commentPr
1793 #if 1//def XLSX_OOXML_FUTURE
1794 if( rStrm
.getVersion() == oox::core::ISOIEC_29500_2008
)
1796 rComments
->startElement(FSNS(XML_mc
, XML_AlternateContent
));
1797 rComments
->startElement(FSNS(XML_mc
, XML_Choice
), XML_Requires
, "v2");
1798 rComments
->startElement( XML_commentPr
,
1799 XML_autoFill
, ToPsz( mbAutoFill
),
1800 XML_autoScale
, ToPsz( mbAutoScale
),
1801 XML_colHidden
, ToPsz( mbColHidden
),
1802 XML_locked
, ToPsz( mbLocked
),
1803 XML_rowHidden
, ToPsz( mbRowHidden
),
1804 XML_textHAlign
, ToHorizAlign( meTHA
),
1805 XML_textVAlign
, ToVertAlign( meTVA
) );
1806 rComments
->startElement(XML_anchor
, XML_moveWithCells
, "false", XML_sizeWithCells
, "false");
1807 rComments
->startElement(FSNS(XML_xdr
, XML_from
));
1808 lcl_WriteAnchorVertex( rComments
, maCommentFrom
);
1809 rComments
->endElement( FSNS( XML_xdr
, XML_from
) );
1810 rComments
->startElement(FSNS(XML_xdr
, XML_to
));
1811 lcl_WriteAnchorVertex( rComments
, maCommentTo
);
1812 rComments
->endElement( FSNS( XML_xdr
, XML_to
) );
1813 rComments
->endElement( XML_anchor
);
1814 rComments
->endElement( XML_commentPr
);
1816 rComments
->endElement( FSNS( XML_mc
, XML_Choice
) );
1817 rComments
->startElement(FSNS(XML_mc
, XML_Fallback
));
1818 // Any fallback code ?
1819 rComments
->endElement( FSNS( XML_mc
, XML_Fallback
) );
1820 rComments
->endElement( FSNS( XML_mc
, XML_AlternateContent
) );
1823 rComments
->endElement( XML_comment
);
1826 XclMacroHelper::XclMacroHelper( const XclExpRoot
& rRoot
) :
1827 XclExpControlHelper( rRoot
)
1831 XclMacroHelper::~XclMacroHelper()
1835 void XclMacroHelper::WriteMacroSubRec( XclExpStream
& rStrm
)
1838 WriteFormulaSubRec( rStrm
, EXC_ID_OBJMACRO
, *mxMacroLink
);
1841 const OUString
& XclMacroHelper::GetMacroName() const { return maMacroName
; }
1844 XclMacroHelper::SetMacroLink( const ScriptEventDescriptor
& rEvent
, const XclTbxEventType
& nEventType
)
1846 maMacroName
= XclControlHelper::ExtractFromMacroDescriptor(rEvent
, nEventType
);
1847 if (!maMacroName
.isEmpty())
1849 return SetMacroLink(maMacroName
);
1855 XclMacroHelper::SetMacroLink( const OUString
& rMacroName
)
1857 // OOXML documents do not store any defined name for VBA macros (while BIFF documents do).
1858 bool bOOXML
= GetOutput() == EXC_OUTPUT_XML_2007
;
1859 if (!rMacroName
.isEmpty() && !bOOXML
)
1861 sal_uInt16 nExtSheet
= GetLocalLinkManager().FindExtSheet( EXC_EXTSH_OWNDOC
);
1863 = GetNameManager().InsertMacroCall(rMacroName
, /*bVBasic=*/true, /*bFunc=*/false);
1864 mxMacroLink
= GetFormulaCompiler().CreateNameXFormula( nExtSheet
, nNameIdx
);
1870 XclExpShapeObj::XclExpShapeObj( XclExpObjectManager
& rRoot
, css::uno::Reference
< css::drawing::XShape
> const & xShape
, ScDocument
* pDoc
) :
1871 XclObjAny( rRoot
, xShape
, pDoc
),
1872 XclMacroHelper( rRoot
)
1874 if (SdrObject
* pSdrObj
= SdrObject::getSdrObjectFromXShape(xShape
))
1876 ScMacroInfo
* pInfo
= ScDrawLayer::GetMacroInfo( pSdrObj
);
1877 if ( pInfo
&& !pInfo
->GetMacro().isEmpty() )
1878 // FIXME ooo330-m2: XclControlHelper::GetXclMacroName was removed in upstream sources; they started to call XclTools::GetXclMacroName instead; is this enough? it has only one parameter
1879 // SetMacroLink( XclControlHelper::GetXclMacroName( pInfo->GetMacro(), rRoot.GetDocShell() ) );
1880 SetMacroLink( XclTools::GetXclMacroName( pInfo
->GetMacro() ) );
1884 XclExpShapeObj::~XclExpShapeObj()
1888 void XclExpShapeObj::WriteSubRecs( XclExpStream
& rStrm
)
1890 XclObjAny::WriteSubRecs( rStrm
);
1891 WriteMacroSubRec( rStrm
);
1894 XclExpComments::XclExpComments( SCTAB nTab
, XclExpRecordList
< XclExpNote
>& rNotes
)
1895 : mnTab( nTab
), mrNotes( rNotes
)
1899 void XclExpComments::SaveXml( XclExpXmlStream
& rStrm
)
1901 if( mrNotes
.IsEmpty() )
1904 sax_fastparser::FSHelperPtr rComments
= rStrm
.CreateOutputStream(
1905 XclXmlUtils::GetStreamName( "xl/", "comments", mnTab
+ 1 ),
1906 XclXmlUtils::GetStreamName( "../", "comments", mnTab
+ 1 ),
1907 rStrm
.GetCurrentStream()->getOutputStream(),
1908 "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
1909 oox::getRelationship(Relationship::COMMENTS
));
1910 rStrm
.PushStream( rComments
);
1912 if( rStrm
.getVersion() == oox::core::ISOIEC_29500_2008
)
1913 rComments
->startElement( XML_comments
,
1914 XML_xmlns
, rStrm
.getNamespaceURL(OOX_NS(xls
)),
1915 FSNS(XML_xmlns
, XML_mc
), rStrm
.getNamespaceURL(OOX_NS(mce
)),
1916 FSNS(XML_xmlns
, XML_xdr
), rStrm
.getNamespaceURL(OOX_NS(dmlSpreadDr
)),
1917 FSNS(XML_xmlns
, XML_v2
), rStrm
.getNamespaceURL(OOX_NS(mceTest
)),
1918 FSNS( XML_mc
, XML_Ignorable
), "v2" );
1920 rComments
->startElement( XML_comments
,
1921 XML_xmlns
, rStrm
.getNamespaceURL(OOX_NS(xls
)),
1922 FSNS(XML_xmlns
, XML_xdr
), rStrm
.getNamespaceURL(OOX_NS(dmlSpreadDr
)) );
1924 rComments
->startElement(XML_authors
);
1926 typedef std::set
<OUString
> Authors
;
1929 size_t nNotes
= mrNotes
.GetSize();
1930 for( size_t i
= 0; i
< nNotes
; ++i
)
1932 aAuthors
.insert( XclXmlUtils::ToOUString( mrNotes
.GetRecord( i
)->GetAuthor() ) );
1935 for( const auto& rAuthor
: aAuthors
)
1937 rComments
->startElement(XML_author
);
1938 rComments
->writeEscaped( rAuthor
);
1939 rComments
->endElement( XML_author
);
1942 rComments
->endElement( XML_authors
);
1943 rComments
->startElement(XML_commentList
);
1945 Authors::const_iterator aAuthorsBegin
= aAuthors
.begin();
1946 for( size_t i
= 0; i
< nNotes
; ++i
)
1948 XclExpRecordList
< XclExpNote
>::RecordRefType xNote
= mrNotes
.GetRecord( i
);
1949 Authors::const_iterator aAuthor
= aAuthors
.find(
1950 XclXmlUtils::ToOUString( xNote
->GetAuthor() ) );
1951 sal_Int32 nAuthorId
= distance( aAuthorsBegin
, aAuthor
);
1952 xNote
->WriteXml( nAuthorId
, rStrm
);
1955 rComments
->endElement( XML_commentList
);
1956 rComments
->endElement( XML_comments
);
1961 // object manager =============================================================
1963 XclExpObjectManager::XclExpObjectManager( const XclExpRoot
& rRoot
) :
1968 mxEscherEx
= std::make_shared
<XclEscherEx
>( GetRoot(), *this, *mpDffStrm
);
1971 XclExpObjectManager::XclExpObjectManager( const XclExpObjectManager
& rParent
) :
1972 XclExpRoot( rParent
.GetRoot() )
1974 InitStream( false );
1976 mxEscherEx
= std::make_shared
<XclEscherEx
>( GetRoot(), *this, *mpDffStrm
, rParent
.mxEscherEx
.get() );
1979 XclExpObjectManager::~XclExpObjectManager()
1983 XclExpDffAnchorBase
* XclExpObjectManager::CreateDffAnchor() const
1985 return new XclExpDffSheetAnchor( GetRoot() );
1988 rtl::Reference
< XclExpRecordBase
> XclExpObjectManager::CreateDrawingGroup()
1990 return new XclExpMsoDrawingGroup( *mxEscherEx
);
1993 void XclExpObjectManager::StartSheet()
1995 mxObjList
= new XclExpObjList( GetRoot(), *mxEscherEx
);
1998 rtl::Reference
< XclExpRecordBase
> XclExpObjectManager::ProcessDrawing( const SdrPage
* pSdrPage
)
2001 mxEscherEx
->AddSdrPage( *pSdrPage
, GetOutput() != EXC_OUTPUT_BINARY
);
2002 // the first dummy object may still be open
2003 OSL_ENSURE( mxEscherEx
->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" );
2004 while( mxEscherEx
->GetGroupLevel() )
2005 mxEscherEx
->LeaveGroup();
2006 mxObjList
->EndSheet();
2010 rtl::Reference
< XclExpRecordBase
> XclExpObjectManager::ProcessDrawing( const Reference
< XShapes
>& rxShapes
)
2013 mxEscherEx
->AddUnoShapes( rxShapes
, GetOutput() != EXC_OUTPUT_BINARY
);
2014 // the first dummy object may still be open
2015 OSL_ENSURE( mxEscherEx
->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" );
2016 while( mxEscherEx
->GetGroupLevel() )
2017 mxEscherEx
->LeaveGroup();
2018 mxObjList
->EndSheet();
2022 void XclExpObjectManager::EndDocument()
2024 mxEscherEx
->EndDocument();
2027 XclExpMsoDrawing
* XclExpObjectManager::GetMsodrawingPerSheet()
2029 return mxObjList
->GetMsodrawingPerSheet();
2032 bool XclExpObjectManager::HasObj() const
2034 return !mxObjList
->empty();
2037 sal_uInt16
XclExpObjectManager::AddObj( std::unique_ptr
<XclObj
> pObjRec
)
2039 return mxObjList
->Add( std::move(pObjRec
) );
2042 std::unique_ptr
<XclObj
> XclExpObjectManager::RemoveLastObj()
2044 return mxObjList
->pop_back();
2047 void XclExpObjectManager::InitStream( bool bTempFile
)
2051 moTempFile
.emplace();
2052 mpDffStrm
= moTempFile
->GetStream( StreamMode::STD_READWRITE
);
2057 mpBackupStrm
= std::make_unique
<SvMemoryStream
>();
2058 mpDffStrm
= mpBackupStrm
.get();
2063 mpDffStrm
->SetEndian( SvStreamEndian::LITTLE
);
2066 XclExpEmbeddedObjectManager::XclExpEmbeddedObjectManager(
2067 const XclExpObjectManager
& rParent
, const Size
& rPageSize
, sal_Int32 nScaleX
, sal_Int32 nScaleY
) :
2068 XclExpObjectManager( rParent
),
2069 maPageSize( rPageSize
),
2070 mnScaleX( nScaleX
),
2075 XclExpDffAnchorBase
* XclExpEmbeddedObjectManager::CreateDffAnchor() const
2077 return new XclExpDffEmbeddedAnchor( GetRoot(), maPageSize
, mnScaleX
, mnScaleY
);
2080 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */